Unverified Commit 13146109 authored by Mayank Mittal's avatar Mayank Mittal Committed by GitHub

Uses Orbit's SimContext for camera unit tests (#504)

# Description

Earlier, we used Isaac Sim's sim context, which set the backend to torch
on CPU. However, we want to make sure things work fine on GPU. This MR
uses Orbit's sim context class for better integration testing.

## Type of change

- Bug fix (non-breaking change which fixes an issue)

## Checklist

- [x] I have run the [`pre-commit` checks](https://pre-commit.com/) with
`./orbit.sh --format`
- [ ] I have made corresponding changes to the documentation
- [x] My changes generate no new warnings
- [ ] I have added tests that prove my fix is effective or that my
feature works
- [x] I have run all the tests with `./orbit.sh --test` and they pass
- [ ] I have updated the changelog and the corresponding version in the
extension's `config/extension.toml` file
- [x] I have added my name to the `CONTRIBUTORS.md` or my name already
exists there
parent 19851b9b
...@@ -220,10 +220,13 @@ class Camera(SensorBase): ...@@ -220,10 +220,13 @@ class Camera(SensorBase):
# resolve env_ids # resolve env_ids
if env_ids is None: if env_ids is None:
env_ids = self._ALL_INDICES env_ids = self._ALL_INDICES
# convert matrices to numpy tensors
if isinstance(matrices, torch.Tensor):
matrices = matrices.cpu().numpy()
else:
matrices = np.asarray(matrices, dtype=float)
# iterate over env_ids # iterate over env_ids
for i, matrix in zip(env_ids, matrices): for i, intrinsic_matrix in zip(env_ids, matrices):
# convert to numpy for sanity
intrinsic_matrix = np.asarray(matrix, dtype=float)
# extract parameters from matrix # extract parameters from matrix
f_x = intrinsic_matrix[0, 0] f_x = intrinsic_matrix[0, 0]
c_x = intrinsic_matrix[0, 2] c_x = intrinsic_matrix[0, 2]
......
...@@ -96,21 +96,21 @@ class TestCamera(unittest.TestCase): ...@@ -96,21 +96,21 @@ class TestCamera(unittest.TestCase):
# Check if camera is initialized # Check if camera is initialized
self.assertTrue(camera._is_initialized) self.assertTrue(camera._is_initialized)
# Check if camera prim is set correctly and that it is a camera prim # Check if camera prim is set correctly and that it is a camera prim
self.assertTrue(camera._sensor_prims[0].GetPath().pathString == self.camera_cfg.prim_path) self.assertEqual(camera._sensor_prims[0].GetPath().pathString, self.camera_cfg.prim_path)
self.assertTrue(isinstance(camera._sensor_prims[0], UsdGeom.Camera)) self.assertIsInstance(camera._sensor_prims[0], UsdGeom.Camera)
# Simulate for a few steps # Simulate for a few steps
# note: This is a workaround to ensure that the textures are loaded. # note: This is a workaround to ensure that the textures are loaded.
# Check "Known Issues" section in the documentation for more details. # Check "Known Issues" section in the documentation for more details.
for _ in range(5): for _ in range(5):
self.sim.step() self.sim.step()
# Check buffers that exists and have correct shapes # Check buffers that exists and have correct shapes
self.assertTrue(camera.data.pos_w.shape == (1, 3)) self.assertEqual(camera.data.pos_w.shape, (1, 3))
self.assertTrue(camera.data.quat_w_ros.shape == (1, 4)) self.assertEqual(camera.data.quat_w_ros.shape, (1, 4))
self.assertTrue(camera.data.quat_w_world.shape == (1, 4)) self.assertEqual(camera.data.quat_w_world.shape, (1, 4))
self.assertTrue(camera.data.quat_w_opengl.shape == (1, 4)) self.assertEqual(camera.data.quat_w_opengl.shape, (1, 4))
self.assertTrue(camera.data.intrinsic_matrices.shape == (1, 3, 3)) self.assertEqual(camera.data.intrinsic_matrices.shape, (1, 3, 3))
self.assertTrue(camera.data.image_shape == (self.camera_cfg.height, self.camera_cfg.width)) self.assertEqual(camera.data.image_shape, (self.camera_cfg.height, self.camera_cfg.width))
self.assertTrue(camera.data.info == [{self.camera_cfg.data_types[0]: None}]) self.assertEqual(camera.data.info, [{self.camera_cfg.data_types[0]: None}])
# Simulate physics # Simulate physics
for _ in range(10): for _ in range(10):
# perform rendering # perform rendering
...@@ -119,7 +119,7 @@ class TestCamera(unittest.TestCase): ...@@ -119,7 +119,7 @@ class TestCamera(unittest.TestCase):
camera.update(self.dt) camera.update(self.dt)
# check image data # check image data
for im_data in camera.data.output.to_dict().values(): for im_data in camera.data.output.to_dict().values():
self.assertTrue(im_data.shape == (1, self.camera_cfg.height, self.camera_cfg.width)) self.assertEqual(im_data.shape, (1, self.camera_cfg.height, self.camera_cfg.width))
def test_camera_init_offset(self): def test_camera_init_offset(self):
"""Test camera initialization with offset using different conventions.""" """Test camera initialization with offset using different conventions."""
...@@ -155,11 +155,11 @@ class TestCamera(unittest.TestCase): ...@@ -155,11 +155,11 @@ class TestCamera(unittest.TestCase):
# play sim # play sim
self.sim.reset() self.sim.reset()
# retrieve camera pose # retrieve camera pose using USD API
prim_tf_ros = camera_ros._sensor_prims[0].ComputeLocalToWorldTransform(Usd.TimeCode.Default()) prim_tf_ros = camera_ros._sensor_prims[0].ComputeLocalToWorldTransform(Usd.TimeCode.Default())
prim_tf_opengl = camera_opengl._sensor_prims[0].ComputeLocalToWorldTransform(Usd.TimeCode.Default()) prim_tf_opengl = camera_opengl._sensor_prims[0].ComputeLocalToWorldTransform(Usd.TimeCode.Default())
prim_tf_world = camera_world._sensor_prims[0].ComputeLocalToWorldTransform(Usd.TimeCode.Default()) prim_tf_world = camera_world._sensor_prims[0].ComputeLocalToWorldTransform(Usd.TimeCode.Default())
# convert them from column-major to row-major
prim_tf_ros = np.transpose(prim_tf_ros) prim_tf_ros = np.transpose(prim_tf_ros)
prim_tf_opengl = np.transpose(prim_tf_opengl) prim_tf_opengl = np.transpose(prim_tf_opengl)
prim_tf_world = np.transpose(prim_tf_world) prim_tf_world = np.transpose(prim_tf_world)
...@@ -185,10 +185,10 @@ class TestCamera(unittest.TestCase): ...@@ -185,10 +185,10 @@ class TestCamera(unittest.TestCase):
) )
# check if transform correctly set in output # check if transform correctly set in output
np.testing.assert_allclose(camera_ros.data.pos_w[0], cam_cfg_offset_ros.offset.pos, rtol=1e-5) np.testing.assert_allclose(camera_ros.data.pos_w[0].cpu().numpy(), cam_cfg_offset_ros.offset.pos, rtol=1e-5)
np.testing.assert_allclose(camera_ros.data.quat_w_ros[0], QUAT_ROS, rtol=1e-5) np.testing.assert_allclose(camera_ros.data.quat_w_ros[0].cpu().numpy(), QUAT_ROS, rtol=1e-5)
np.testing.assert_allclose(camera_ros.data.quat_w_opengl[0], QUAT_OPENGL, rtol=1e-5) np.testing.assert_allclose(camera_ros.data.quat_w_opengl[0].cpu().numpy(), QUAT_OPENGL, rtol=1e-5)
np.testing.assert_allclose(camera_ros.data.quat_w_world[0], QUAT_WORLD, rtol=1e-5) np.testing.assert_allclose(camera_ros.data.quat_w_world[0].cpu().numpy(), QUAT_WORLD, rtol=1e-5)
def test_multi_camera_init(self): def test_multi_camera_init(self):
"""Test multi-camera initialization.""" """Test multi-camera initialization."""
...@@ -204,6 +204,7 @@ class TestCamera(unittest.TestCase): ...@@ -204,6 +204,7 @@ class TestCamera(unittest.TestCase):
# play sim # play sim
self.sim.reset() self.sim.reset()
# Simulate for a few steps # Simulate for a few steps
# note: This is a workaround to ensure that the textures are loaded. # note: This is a workaround to ensure that the textures are loaded.
# Check "Known Issues" section in the documentation for more details. # Check "Known Issues" section in the documentation for more details.
...@@ -219,27 +220,52 @@ class TestCamera(unittest.TestCase): ...@@ -219,27 +220,52 @@ class TestCamera(unittest.TestCase):
# check image data # check image data
for cam in [cam_1, cam_2]: for cam in [cam_1, cam_2]:
for im_data in cam.data.output.to_dict().values(): for im_data in cam.data.output.to_dict().values():
self.assertTrue(im_data.shape == (1, self.camera_cfg.height, self.camera_cfg.width)) self.assertEqual(im_data.shape, (1, self.camera_cfg.height, self.camera_cfg.width))
def test_camera_set_world_poses(self): def test_camera_set_world_poses(self):
"""Test camera function to set specific world pose.""" """Test camera function to set specific world pose."""
camera = Camera(self.camera_cfg) camera = Camera(self.camera_cfg)
# play sim # play sim
self.sim.reset() self.sim.reset()
# convert to torch tensors
position = torch.tensor([POSITION], dtype=torch.float32, device=camera.device)
orientation = torch.tensor([QUAT_WORLD], dtype=torch.float32, device=camera.device)
# set new pose # set new pose
camera.set_world_poses(torch.tensor([POSITION]), torch.tensor([QUAT_WORLD]), convention="world") camera.set_world_poses(position.clone(), orientation.clone(), convention="world")
np.testing.assert_allclose(camera.data.pos_w, [POSITION], rtol=1e-5)
np.testing.assert_allclose(camera.data.quat_w_world, [QUAT_WORLD], rtol=1e-5) # Simulate for a few steps
# note: This is a workaround to ensure that the textures are loaded.
# Check "Known Issues" section in the documentation for more details.
for _ in range(5):
self.sim.step()
# check if transform correctly set in output
torch.testing.assert_close(camera.data.pos_w, position)
torch.testing.assert_close(camera.data.quat_w_world, orientation)
def test_camera_set_world_poses_from_view(self): def test_camera_set_world_poses_from_view(self):
"""Test camera function to set specific world pose from view.""" """Test camera function to set specific world pose from view."""
camera = Camera(self.camera_cfg) camera = Camera(self.camera_cfg)
# play sim # play sim
self.sim.reset() self.sim.reset()
# convert to torch tensors
eyes = torch.tensor([POSITION], dtype=torch.float32, device=camera.device)
targets = torch.tensor([[0.0, 0.0, 0.0]], dtype=torch.float32, device=camera.device)
quat_ros_gt = torch.tensor([QUAT_ROS], dtype=torch.float32, device=camera.device)
# set new pose # set new pose
camera.set_world_poses_from_view(torch.tensor([POSITION]), torch.tensor([[0.0, 0.0, 0.0]])) camera.set_world_poses_from_view(eyes.clone(), targets.clone())
np.testing.assert_allclose(camera.data.pos_w, [POSITION], rtol=1e-5)
np.testing.assert_allclose(camera.data.quat_w_ros, [QUAT_ROS], rtol=1e-5) # Simulate for a few steps
# note: This is a workaround to ensure that the textures are loaded.
# Check "Known Issues" section in the documentation for more details.
for _ in range(5):
self.sim.step()
# check if transform correctly set in output
torch.testing.assert_close(camera.data.pos_w, eyes)
torch.testing.assert_close(camera.data.quat_w_ros, quat_ros_gt)
def test_intrinsic_matrix(self): def test_intrinsic_matrix(self):
"""Checks that the camera's set and retrieve methods work for intrinsic matrix.""" """Checks that the camera's set and retrieve methods work for intrinsic matrix."""
...@@ -251,14 +277,16 @@ class TestCamera(unittest.TestCase): ...@@ -251,14 +277,16 @@ class TestCamera(unittest.TestCase):
self.sim.reset() self.sim.reset()
# Desired properties (obtained from realsense camera at 320x240 resolution) # Desired properties (obtained from realsense camera at 320x240 resolution)
rs_intrinsic_matrix = [229.31640625, 0.0, 164.810546875, 0.0, 229.826171875, 122.1650390625, 0.0, 0.0, 1.0] rs_intrinsic_matrix = [229.31640625, 0.0, 164.810546875, 0.0, 229.826171875, 122.1650390625, 0.0, 0.0, 1.0]
rs_intrinsic_matrix = np.array(rs_intrinsic_matrix).reshape(3, 3) rs_intrinsic_matrix = torch.tensor(rs_intrinsic_matrix, device=camera.device).reshape(3, 3).unsqueeze(0)
# Set matrix into simulator # Set matrix into simulator
camera.set_intrinsic_matrices([rs_intrinsic_matrix]) camera.set_intrinsic_matrices(rs_intrinsic_matrix.clone())
# Simulate for a few steps # Simulate for a few steps
# note: This is a workaround to ensure that the textures are loaded. # note: This is a workaround to ensure that the textures are loaded.
# Check "Known Issues" section in the documentation for more details. # Check "Known Issues" section in the documentation for more details.
for _ in range(5): for _ in range(5):
self.sim.step() self.sim.step()
# Simulate physics # Simulate physics
for _ in range(10): for _ in range(10):
# perform rendering # perform rendering
...@@ -266,12 +294,11 @@ class TestCamera(unittest.TestCase): ...@@ -266,12 +294,11 @@ class TestCamera(unittest.TestCase):
# update camera # update camera
camera.update(self.dt) camera.update(self.dt)
# Check that matrix is correct # Check that matrix is correct
K = camera.data.intrinsic_matrices[0].numpy()
# TODO: This is not correctly setting all values in the matrix since the # TODO: This is not correctly setting all values in the matrix since the
# vertical aperture and aperture offsets are not being set correctly # vertical aperture and aperture offsets are not being set correctly
# This is a bug in the simulator. # This is a bug in the simulator.
self.assertAlmostEqual(rs_intrinsic_matrix[0, 0], K[0, 0], 4) torch.testing.assert_close(rs_intrinsic_matrix[0, 0, 0], camera.data.intrinsic_matrices[0, 0, 0])
# self.assertAlmostEqual(rs_intrinsic_matrix[1, 1], K[1, 1], 4) # torch.testing.assert_close(rs_intrinsic_matrix[0, 1, 1], camera.data.intrinsic_matrices[0, 1, 1])
def test_camera_resolution_all_colorize(self): def test_camera_resolution_all_colorize(self):
"""Test camera resolution is correctly set for all types with colorization enabled.""" """Test camera resolution is correctly set for all types with colorization enabled."""
...@@ -293,10 +320,11 @@ class TestCamera(unittest.TestCase): ...@@ -293,10 +320,11 @@ class TestCamera(unittest.TestCase):
# Play sim # Play sim
self.sim.reset() self.sim.reset()
# Simulate for a few steps # Simulate for a few steps
# note: This is a workaround to ensure that the textures are loaded. # note: This is a workaround to ensure that the textures are loaded.
# Check "Known Issues" section in the documentation for more details. # Check "Known Issues" section in the documentation for more details.
for _ in range(12): for _ in range(5):
self.sim.step() self.sim.step()
camera.update(self.dt) camera.update(self.dt)
...@@ -382,10 +410,15 @@ class TestCamera(unittest.TestCase): ...@@ -382,10 +410,15 @@ class TestCamera(unittest.TestCase):
camera_cfg.height = 480 camera_cfg.height = 480
camera_cfg.width = 640 camera_cfg.width = 640
camera = Camera(camera_cfg) camera = Camera(camera_cfg)
# Play simulator # Play simulator
self.sim.reset() self.sim.reset()
# Set camera pose # Set camera pose
camera.set_world_poses_from_view(torch.tensor([[2.5, 2.5, 2.5]]), torch.tensor([[0.0, 0.0, 0.0]])) eyes = torch.tensor([[2.5, 2.5, 2.5]], dtype=torch.float32, device=camera.device)
targets = torch.tensor([[0.0, 0.0, 0.0]], dtype=torch.float32, device=camera.device)
camera.set_world_poses_from_view(eyes, targets)
# Simulate for a few steps # Simulate for a few steps
# note: This is a workaround to ensure that the textures are loaded. # note: This is a workaround to ensure that the textures are loaded.
# Check "Known Issues" section in the documentation for more details. # Check "Known Issues" section in the documentation for more details.
...@@ -414,7 +447,7 @@ class TestCamera(unittest.TestCase): ...@@ -414,7 +447,7 @@ class TestCamera(unittest.TestCase):
print("----------------------------------------") print("----------------------------------------")
# Check image data # Check image data
for im_data in camera.data.output.values(): for im_data in camera.data.output.values():
self.assertTrue(im_data.shape == (1, camera_cfg.height, camera_cfg.width)) self.assertEqual(im_data.shape, (1, camera_cfg.height, camera_cfg.width))
""" """
Helper functions. Helper functions.
......
...@@ -113,15 +113,15 @@ class TestWarpCamera(unittest.TestCase): ...@@ -113,15 +113,15 @@ class TestWarpCamera(unittest.TestCase):
for _ in range(5): for _ in range(5):
self.sim.step() self.sim.step()
# Check buffers that exists and have correct shapes # Check buffers that exists and have correct shapes
self.assertTrue(camera.data.pos_w.shape == (1, 3)) self.assertEqual(camera.data.pos_w.shape, (1, 3))
self.assertTrue(camera.data.quat_w_ros.shape == (1, 4)) self.assertEqual(camera.data.quat_w_ros.shape, (1, 4))
self.assertTrue(camera.data.quat_w_world.shape == (1, 4)) self.assertEqual(camera.data.quat_w_world.shape, (1, 4))
self.assertTrue(camera.data.quat_w_opengl.shape == (1, 4)) self.assertEqual(camera.data.quat_w_opengl.shape, (1, 4))
self.assertTrue(camera.data.intrinsic_matrices.shape == (1, 3, 3)) self.assertEqual(camera.data.intrinsic_matrices.shape, (1, 3, 3))
self.assertTrue( self.assertEqual(
camera.data.image_shape == (self.camera_cfg.pattern_cfg.height, self.camera_cfg.pattern_cfg.width) camera.data.image_shape, (self.camera_cfg.pattern_cfg.height, self.camera_cfg.pattern_cfg.width)
) )
self.assertTrue(camera.data.info == [{self.camera_cfg.data_types[0]: None}]) self.assertEqual(camera.data.info, [{self.camera_cfg.data_types[0]: None}])
# Simulate physics # Simulate physics
for _ in range(10): for _ in range(10):
# perform rendering # perform rendering
...@@ -130,8 +130,8 @@ class TestWarpCamera(unittest.TestCase): ...@@ -130,8 +130,8 @@ class TestWarpCamera(unittest.TestCase):
camera.update(self.dt) camera.update(self.dt)
# check image data # check image data
for im_data in camera.data.output.to_dict().values(): for im_data in camera.data.output.to_dict().values():
self.assertTrue( self.assertEqual(
im_data.shape == (1, self.camera_cfg.pattern_cfg.height, self.camera_cfg.pattern_cfg.width) im_data.shape, (1, self.camera_cfg.pattern_cfg.height, self.camera_cfg.pattern_cfg.width)
) )
def test_camera_resolution(self): def test_camera_resolution(self):
...@@ -193,15 +193,15 @@ class TestWarpCamera(unittest.TestCase): ...@@ -193,15 +193,15 @@ class TestWarpCamera(unittest.TestCase):
camera_ros.update(self.dt) camera_ros.update(self.dt)
# check that all transforms are set correctly # check that all transforms are set correctly
np.testing.assert_allclose(camera_ros.data.pos_w[0].numpy(), cam_cfg_offset_ros.offset.pos) np.testing.assert_allclose(camera_ros.data.pos_w[0].cpu().numpy(), cam_cfg_offset_ros.offset.pos)
np.testing.assert_allclose(camera_opengl.data.pos_w[0].numpy(), cam_cfg_offset_opengl.offset.pos) np.testing.assert_allclose(camera_opengl.data.pos_w[0].cpu().numpy(), cam_cfg_offset_opengl.offset.pos)
np.testing.assert_allclose(camera_world.data.pos_w[0].numpy(), cam_cfg_offset_world.offset.pos) np.testing.assert_allclose(camera_world.data.pos_w[0].cpu().numpy(), cam_cfg_offset_world.offset.pos)
# check if transform correctly set in output # check if transform correctly set in output
np.testing.assert_allclose(camera_ros.data.pos_w[0], cam_cfg_offset_ros.offset.pos, rtol=1e-5) np.testing.assert_allclose(camera_ros.data.pos_w[0].cpu().numpy(), cam_cfg_offset_ros.offset.pos, rtol=1e-5)
np.testing.assert_allclose(camera_ros.data.quat_w_ros[0], QUAT_ROS, rtol=1e-5) np.testing.assert_allclose(camera_ros.data.quat_w_ros[0].cpu().numpy(), QUAT_ROS, rtol=1e-5)
np.testing.assert_allclose(camera_ros.data.quat_w_opengl[0], QUAT_OPENGL, rtol=1e-5) np.testing.assert_allclose(camera_ros.data.quat_w_opengl[0].cpu().numpy(), QUAT_OPENGL, rtol=1e-5)
np.testing.assert_allclose(camera_ros.data.quat_w_world[0], QUAT_WORLD, rtol=1e-5) np.testing.assert_allclose(camera_ros.data.quat_w_world[0].cpu().numpy(), QUAT_WORLD, rtol=1e-5)
def test_multi_camera_init(self): def test_multi_camera_init(self):
"""Test multi-camera initialization.""" """Test multi-camera initialization."""
...@@ -223,6 +223,7 @@ class TestWarpCamera(unittest.TestCase): ...@@ -223,6 +223,7 @@ class TestWarpCamera(unittest.TestCase):
# play sim # play sim
self.sim.reset() self.sim.reset()
# Simulate for a few steps # Simulate for a few steps
# note: This is a workaround to ensure that the textures are loaded. # note: This is a workaround to ensure that the textures are loaded.
# Check "Known Issues" section in the documentation for more details. # Check "Known Issues" section in the documentation for more details.
...@@ -238,8 +239,8 @@ class TestWarpCamera(unittest.TestCase): ...@@ -238,8 +239,8 @@ class TestWarpCamera(unittest.TestCase):
# check image data # check image data
for cam in [cam_1, cam_2]: for cam in [cam_1, cam_2]:
for im_data in cam.data.output.to_dict().values(): for im_data in cam.data.output.to_dict().values():
self.assertTrue( self.assertEqual(
im_data.shape == (1, self.camera_cfg.pattern_cfg.height, self.camera_cfg.pattern_cfg.width) im_data.shape, (1, self.camera_cfg.pattern_cfg.height, self.camera_cfg.pattern_cfg.width)
) )
def test_camera_set_world_poses(self): def test_camera_set_world_poses(self):
...@@ -247,20 +248,33 @@ class TestWarpCamera(unittest.TestCase): ...@@ -247,20 +248,33 @@ class TestWarpCamera(unittest.TestCase):
camera = RayCasterCamera(self.camera_cfg) camera = RayCasterCamera(self.camera_cfg)
# play sim # play sim
self.sim.reset() self.sim.reset()
# convert to torch tensors
position = torch.tensor([POSITION], dtype=torch.float32, device=camera.device)
orientation = torch.tensor([QUAT_WORLD], dtype=torch.float32, device=camera.device)
# set new pose # set new pose
camera.set_world_poses(torch.tensor([POSITION]), torch.tensor([QUAT_WORLD]), convention="world") camera.set_world_poses(position.clone(), orientation.clone(), convention="world")
np.testing.assert_allclose(camera.data.pos_w, [POSITION], rtol=1e-5)
np.testing.assert_allclose(camera.data.quat_w_world, [QUAT_WORLD], rtol=1e-5) # check if transform correctly set in output
torch.testing.assert_close(camera.data.pos_w, position)
torch.testing.assert_close(camera.data.quat_w_world, orientation)
def test_camera_set_world_poses_from_view(self): def test_camera_set_world_poses_from_view(self):
"""Test camera function to set specific world pose from view.""" """Test camera function to set specific world pose from view."""
camera = RayCasterCamera(self.camera_cfg) camera = RayCasterCamera(self.camera_cfg)
# play sim # play sim
self.sim.reset() self.sim.reset()
# convert to torch tensors
eyes = torch.tensor([POSITION], dtype=torch.float32, device=camera.device)
targets = torch.tensor([[0.0, 0.0, 0.0]], dtype=torch.float32, device=camera.device)
quat_ros_gt = torch.tensor([QUAT_ROS], dtype=torch.float32, device=camera.device)
# set new pose # set new pose
camera.set_world_poses_from_view(torch.tensor([POSITION]), torch.tensor([[0.0, 0.0, 0.0]])) camera.set_world_poses_from_view(eyes.clone(), targets.clone())
np.testing.assert_allclose(camera.data.pos_w, [POSITION], rtol=1e-5)
np.testing.assert_allclose(camera.data.quat_w_ros, [QUAT_ROS], rtol=1e-5) # check if transform correctly set in output
torch.testing.assert_close(camera.data.pos_w, eyes)
torch.testing.assert_close(camera.data.quat_w_ros, quat_ros_gt)
def test_intrinsic_matrix(self): def test_intrinsic_matrix(self):
"""Checks that the camera's set and retrieve methods work for intrinsic matrix.""" """Checks that the camera's set and retrieve methods work for intrinsic matrix."""
...@@ -272,9 +286,9 @@ class TestWarpCamera(unittest.TestCase): ...@@ -272,9 +286,9 @@ class TestWarpCamera(unittest.TestCase):
self.sim.reset() self.sim.reset()
# Desired properties (obtained from realsense camera at 320x240 resolution) # Desired properties (obtained from realsense camera at 320x240 resolution)
rs_intrinsic_matrix = [229.31640625, 0.0, 164.810546875, 0.0, 229.826171875, 122.1650390625, 0.0, 0.0, 1.0] rs_intrinsic_matrix = [229.31640625, 0.0, 164.810546875, 0.0, 229.826171875, 122.1650390625, 0.0, 0.0, 1.0]
rs_intrinsic_matrix = torch.tensor(rs_intrinsic_matrix).reshape(3, 3).unsqueeze(0) rs_intrinsic_matrix = torch.tensor(rs_intrinsic_matrix, device=camera.device).reshape(3, 3).unsqueeze(0)
# Set matrix into simulator # Set matrix into simulator
camera.set_intrinsic_matrices(rs_intrinsic_matrix) camera.set_intrinsic_matrices(rs_intrinsic_matrix.clone())
# Simulate for a few steps # Simulate for a few steps
# note: This is a workaround to ensure that the textures are loaded. # note: This is a workaround to ensure that the textures are loaded.
# Check "Known Issues" section in the documentation for more details. # Check "Known Issues" section in the documentation for more details.
...@@ -287,12 +301,11 @@ class TestWarpCamera(unittest.TestCase): ...@@ -287,12 +301,11 @@ class TestWarpCamera(unittest.TestCase):
# update camera # update camera
camera.update(self.dt) camera.update(self.dt)
# Check that matrix is correct # Check that matrix is correct
K = camera.data.intrinsic_matrices[0].numpy()
# TODO: This is not correctly setting all values in the matrix since the # TODO: This is not correctly setting all values in the matrix since the
# vertical aperture and aperture offsets are not being set correctly # vertical aperture and aperture offsets are not being set correctly
# This is a bug in the simulator. # This is a bug in the simulator.
self.assertAlmostEqual(rs_intrinsic_matrix[0, 0, 0].numpy(), K[0, 0], 4) torch.testing.assert_close(rs_intrinsic_matrix[0, 0, 0], camera.data.intrinsic_matrices[0, 0, 0])
# self.assertAlmostEqual(rs_intrinsic_matrix[1, 1], K[1, 1], 4) # torch.testing.assert_close(rs_intrinsic_matrix[0, 1, 1], camera.data.intrinsic_matrices[0, 1, 1])
def test_throughput(self): def test_throughput(self):
"""Checks that the single camera gets created properly with a rig.""" """Checks that the single camera gets created properly with a rig."""
...@@ -307,10 +320,15 @@ class TestWarpCamera(unittest.TestCase): ...@@ -307,10 +320,15 @@ class TestWarpCamera(unittest.TestCase):
camera_cfg.pattern_cfg.height = 480 camera_cfg.pattern_cfg.height = 480
camera_cfg.pattern_cfg.width = 640 camera_cfg.pattern_cfg.width = 640
camera = RayCasterCamera(camera_cfg) camera = RayCasterCamera(camera_cfg)
# Play simulator # Play simulator
self.sim.reset() self.sim.reset()
# Set camera pose # Set camera pose
camera.set_world_poses_from_view(torch.tensor([[2.5, 2.5, 2.5]]), torch.tensor([[0.0, 0.0, 0.0]])) eyes = torch.tensor([[2.5, 2.5, 2.5]], dtype=torch.float32, device=camera.device)
targets = torch.tensor([[0.0, 0.0, 0.0]], dtype=torch.float32, device=camera.device)
camera.set_world_poses_from_view(eyes, targets)
# Simulate for a few steps # Simulate for a few steps
# note: This is a workaround to ensure that the textures are loaded. # note: This is a workaround to ensure that the textures are loaded.
# Check "Known Issues" section in the documentation for more details. # Check "Known Issues" section in the documentation for more details.
...@@ -339,7 +357,7 @@ class TestWarpCamera(unittest.TestCase): ...@@ -339,7 +357,7 @@ class TestWarpCamera(unittest.TestCase):
print("----------------------------------------") print("----------------------------------------")
# Check image data # Check image data
for im_data in camera.data.output.values(): for im_data in camera.data.output.values():
self.assertTrue(im_data.shape == (1, camera_cfg.pattern_cfg.height, camera_cfg.pattern_cfg.width)) self.assertEqual(im_data.shape, (1, camera_cfg.pattern_cfg.height, camera_cfg.pattern_cfg.width))
def test_output_equal_to_usdcamera(self): def test_output_equal_to_usdcamera(self):
camera_pattern_cfg = patterns.PinholeCameraPatternCfg( camera_pattern_cfg = patterns.PinholeCameraPatternCfg(
...@@ -378,9 +396,12 @@ class TestWarpCamera(unittest.TestCase): ...@@ -378,9 +396,12 @@ class TestWarpCamera(unittest.TestCase):
self.sim.reset() self.sim.reset()
self.sim.play() self.sim.play()
# convert to torch tensors
eyes = torch.tensor([[2.5, 2.5, 4.5]], dtype=torch.float32, device=camera_warp.device)
targets = torch.tensor([[0.0, 0.0, 0.0]], dtype=torch.float32, device=camera_warp.device)
# set views # set views
camera_warp.set_world_poses_from_view(torch.tensor([[2.5, 2.5, 4.5]]), torch.tensor([[0.0, 0.0, 0.0]])) camera_warp.set_world_poses_from_view(eyes, targets)
camera_usd.set_world_poses_from_view(torch.tensor([[2.5, 2.5, 4.5]]), torch.tensor([[0.0, 0.0, 0.0]])) camera_usd.set_world_poses_from_view(eyes, targets)
# perform steps # perform steps
for _ in range(5): for _ in range(5):
...@@ -391,19 +412,21 @@ class TestWarpCamera(unittest.TestCase): ...@@ -391,19 +412,21 @@ class TestWarpCamera(unittest.TestCase):
camera_warp.update(self.dt) camera_warp.update(self.dt)
# check image data # check image data
np.testing.assert_allclose( torch.testing.assert_close(
camera_usd.data.output["distance_to_image_plane"].numpy(), camera_usd.data.output["distance_to_image_plane"],
camera_warp.data.output["distance_to_image_plane"].numpy(), camera_warp.data.output["distance_to_image_plane"],
rtol=5e-3, rtol=5e-3,
atol=1e-4,
) )
np.testing.assert_allclose( torch.testing.assert_close(
camera_usd.data.output["distance_to_camera"].numpy(), camera_usd.data.output["distance_to_camera"],
camera_warp.data.output["distance_to_camera"].numpy(), camera_warp.data.output["distance_to_camera"],
rtol=5e-3, rtol=5e-3,
atol=1e-4,
) )
np.testing.assert_allclose( torch.testing.assert_close(
camera_usd.data.output["normals"].numpy()[..., :3], camera_usd.data.output["normals"][..., :3],
camera_warp.data.output["normals"].numpy(), camera_warp.data.output["normals"],
rtol=1e-5, rtol=1e-5,
atol=1e-4, atol=1e-4,
) )
...@@ -457,19 +480,21 @@ class TestWarpCamera(unittest.TestCase): ...@@ -457,19 +480,21 @@ class TestWarpCamera(unittest.TestCase):
camera_warp.update(self.dt) camera_warp.update(self.dt)
# check image data # check image data
np.testing.assert_allclose( torch.testing.assert_close(
camera_usd.data.output["distance_to_image_plane"].numpy(), camera_usd.data.output["distance_to_image_plane"],
camera_warp.data.output["distance_to_image_plane"].numpy(), camera_warp.data.output["distance_to_image_plane"],
rtol=5e-3, rtol=5e-3,
atol=1e-4,
) )
np.testing.assert_allclose( torch.testing.assert_close(
camera_usd.data.output["distance_to_camera"].numpy(), camera_usd.data.output["distance_to_camera"],
camera_warp.data.output["distance_to_camera"].numpy(), camera_warp.data.output["distance_to_camera"],
rtol=5e-3, rtol=5e-3,
atol=1e-4,
) )
np.testing.assert_allclose( torch.testing.assert_close(
camera_usd.data.output["normals"].numpy()[..., :3], camera_usd.data.output["normals"][..., :3],
camera_warp.data.output["normals"].numpy(), camera_warp.data.output["normals"],
rtol=1e-5, rtol=1e-5,
atol=1e-4, atol=1e-4,
) )
...@@ -538,25 +563,25 @@ class TestWarpCamera(unittest.TestCase): ...@@ -538,25 +563,25 @@ class TestWarpCamera(unittest.TestCase):
camera_warp.update(self.dt) camera_warp.update(self.dt)
# check if pos and orientation are correct # check if pos and orientation are correct
np.testing.assert_allclose(camera_warp.data.pos_w[0].numpy(), camera_usd.data.pos_w[0].numpy(), rtol=1e-5) torch.testing.assert_close(camera_warp.data.pos_w[0], camera_usd.data.pos_w[0])
np.testing.assert_allclose( torch.testing.assert_close(camera_warp.data.quat_w_ros[0], camera_usd.data.quat_w_ros[0])
camera_warp.data.quat_w_ros[0].numpy(), camera_usd.data.quat_w_ros[0].numpy(), rtol=1e-5
)
# check image data # check image data
np.testing.assert_allclose( torch.testing.assert_close(
camera_usd.data.output["distance_to_image_plane"].numpy(), camera_usd.data.output["distance_to_image_plane"],
camera_warp.data.output["distance_to_image_plane"].numpy(), camera_warp.data.output["distance_to_image_plane"],
rtol=5e-3, rtol=5e-3,
atol=1e-4,
) )
np.testing.assert_allclose( torch.testing.assert_close(
camera_usd.data.output["distance_to_camera"].numpy(), camera_usd.data.output["distance_to_camera"],
camera_warp.data.output["distance_to_camera"].numpy(), camera_warp.data.output["distance_to_camera"],
rtol=5e-3, rtol=5e-3,
atol=1e-4,
) )
np.testing.assert_allclose( torch.testing.assert_close(
camera_usd.data.output["normals"].numpy()[..., :3], camera_usd.data.output["normals"][..., :3],
camera_warp.data.output["normals"].numpy(), camera_warp.data.output["normals"],
rtol=1e-5, rtol=1e-5,
atol=1e-4, atol=1e-4,
) )
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment