|
1 | 1 | import logging |
2 | 2 | from datetime import datetime |
| 3 | +from typing import Literal |
3 | 4 |
|
| 5 | +import mujoco |
4 | 6 | import numpy as np |
5 | 7 |
|
6 | 8 | # from rcs._core.common import BaseCameraConfig |
| 9 | +from rcs._core import common |
7 | 10 | from rcs._core.sim import FrameSet as _FrameSet |
8 | 11 | from rcs._core.sim import SimCameraConfig |
9 | 12 | from rcs._core.sim import SimCameraSet as _SimCameraSet |
@@ -68,14 +71,46 @@ def _cpp_to_python_frames(self, cpp_frameset: _FrameSet | None) -> FrameSet | No |
68 | 71 | near = self._sim.model.vis.map.znear * extent |
69 | 72 | far = self._sim.model.vis.map.zfar * extent |
70 | 73 | 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 | + |
71 | 78 | 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 | + ), |
74 | 85 | ) |
75 | 86 | frame = Frame(camera=cameraframe, avg_timestamp=cpp_frameset.timestamp) |
76 | 87 | frames[color_name] = frame |
77 | 88 | return FrameSet(frames=frames, avg_timestamp=cpp_frameset.timestamp) |
78 | 89 |
|
| 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 | + |
79 | 114 | def config(self, camera_name: str) -> SimCameraConfig: |
80 | 115 | """Should return the configuration of the camera with the given name.""" |
81 | 116 | return self.cameras[camera_name] |
|
0 commit comments