Skip to content

Commit 5a8b587

Browse files
committed
feat(sim): intrinsic and extrinsic as additional camera data
- added extrinsic and intrinsic matrices to camera interface - added extrinsic and intrinsic to mujoco camera set
1 parent 92b6aba commit 5a8b587

2 files changed

Lines changed: 41 additions & 3 deletions

File tree

python/rcs/camera/interface.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
import logging
22
from dataclasses import dataclass
33
from datetime import datetime
4-
from typing import Any, Protocol
4+
from typing import Any, Literal, Protocol
55

6+
import numpy as np
67
from rcs._core.common import BaseCameraConfig
78

89
logger = logging.getLogger(__name__)
@@ -14,6 +15,8 @@ class DataFrame:
1415
data: Any
1516
# timestamp in posix time
1617
timestamp: float | None = None
18+
intrinsics: np.ndarray[tuple[Literal[3, 4]], np.dtype[np.float64]] | None = None
19+
extrinsics: np.ndarray[tuple[Literal[4, 4]], np.dtype[np.float64]] | None = None
1720

1821

1922
@dataclass(kw_only=True)

python/rcs/camera/sim.py

Lines changed: 37 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,12 @@
11
import logging
22
from datetime import datetime
3+
from typing import Literal
34

5+
import mujoco
46
import numpy as np
57

68
# from rcs._core.common import BaseCameraConfig
9+
from rcs._core import common
710
from rcs._core.sim import FrameSet as _FrameSet
811
from rcs._core.sim import SimCameraConfig
912
from rcs._core.sim import SimCameraSet as _SimCameraSet
@@ -68,14 +71,46 @@ def _cpp_to_python_frames(self, cpp_frameset: _FrameSet | None) -> FrameSet | No
6871
near = self._sim.model.vis.map.znear * extent
6972
far = self._sim.model.vis.map.zfar * extent
7073
depth_np_frame = near / (1 - depth_np_frame * (1 - near / far))
74+
75+
intrinsics = self._intrinsics(color_name)
76+
extrinsics = self._extrinsics(color_name)
77+
7178
cameraframe = CameraFrame(
72-
color=DataFrame(data=color_np_frame, timestamp=cpp_frameset.timestamp),
73-
depth=DataFrame(data=depth_np_frame, timestamp=cpp_frameset.timestamp),
79+
color=DataFrame(
80+
data=color_np_frame, timestamp=cpp_frameset.timestamp, intrinsics=intrinsics, extrinsics=extrinsics
81+
),
82+
depth=DataFrame(
83+
data=depth_np_frame, timestamp=cpp_frameset.timestamp, intrinsics=intrinsics, extrinsics=extrinsics
84+
),
7485
)
7586
frame = Frame(camera=cameraframe, avg_timestamp=cpp_frameset.timestamp)
7687
frames[color_name] = frame
7788
return FrameSet(frames=frames, avg_timestamp=cpp_frameset.timestamp)
7889

90+
def _intrinsics(self, camera_name) -> np.ndarray[tuple[Literal[3, 4]], np.dtype[np.float64]]:
91+
cam_id = mujoco.mj_name2id(self._sim.model, mujoco.mjtObj.mjOBJ_CAMERA, self.cameras[camera_name].identifier)
92+
fovy = self._sim.model.cam_fovy[cam_id]
93+
fx = fy = 0.5 * self.cameras[camera_name].resolution_height / np.tan(fovy * np.pi / 360)
94+
return np.array(
95+
[
96+
[fx, 0, (self.cameras[camera_name].resolution_width - 1) / 2, 0],
97+
[0, fy, (self.cameras[camera_name].resolution_height - 1) / 2, 0],
98+
[0, 0, 1, 0],
99+
]
100+
)
101+
102+
def _extrinsics(self, camera_name) -> np.ndarray[tuple[Literal[4, 4]], np.dtype[np.float64]]:
103+
cam_id = mujoco.mj_name2id(self._sim.model, mujoco.mjtObj.mjOBJ_CAMERA, self.cameras[camera_name].identifier)
104+
xpos = self._sim.data.cam_xpos[cam_id]
105+
xmat = self._sim.data.cam_xmat[cam_id].reshape(3, 3)
106+
107+
cam = common.Pose(rotation=xmat, translation=xpos)
108+
# put z axis infront
109+
rotation_p = common.Pose(rpy_vector=[np.pi, 0, 0], translation=[0, 0, 0])
110+
cam = cam * rotation_p
111+
112+
return cam.inverse().pose_matrix()
113+
79114
def config(self, camera_name: str) -> SimCameraConfig:
80115
"""Should return the configuration of the camera with the given name."""
81116
return self.cameras[camera_name]

0 commit comments

Comments
 (0)