code: def test_ortho(self, device, dtype, batch_size):
      q = Quaternion.random(batch_size, device, dtype)
      b_R_a = So3(q).matrix()
      a_R_b = So3(q).inverse().matrix()
      a_R_a = (So3(q) * So3(q).inverse()).matrix()
  
      eye_mat = torch.eye(3, device=device, dtype=dtype)
      if batch_size is None:
          eye_mat = eye_mat[None]
          a_R_a = a_R_a[None]
          a_R_b = a_R_b[None]
          b_R_a = b_R_a[None]
      if batch_size is not None:
          eye_mat = eye_mat.repeat(batch_size, 1, 1)
  
      self.assert_close(a_R_a, eye_mat)
  
      for i in range(eye_mat.shape[0]):
          self.assert_close(a_R_a[i, :, :], eye_mat[i])
          self.assert_close(a_R_b[i, :, :] @ b_R_a[i, :, :], eye_mat[i])
          self.assert_close(b_R_a[i, :, :] @ a_R_b[i, :, :], eye_mat[i])
  
imports: import pytest
  import torch
  from kornia.geometry.conversions import euler_from_quaternion
  from kornia.geometry.liegroup import So3
  from kornia.geometry.quaternion import Quaternion
  from kornia.geometry.vector import Vector3
  from kornia.testing import BaseTester
label_desc: Use image node_id 21 for calling the TestSo3 obj's underlying member method code with example usage: obj.test_ortho(device, dtype, batch_size) without return types