@@ -65,15 +65,41 @@ def get_depth(self):
6565 np.ndarray: Depth map as a numpy array, with values representing
6666 distance from the camera in meters
6767 """
68+ # Get depth map from MuJoCo
6869 _ , depth = self .render (depth = True , segmentation = False )
70+
71+ # Convert MuJoCo depth to real depth
6972 from physics_simulator .utils .camera_utils import get_real_depth_map
70-
7173 depth = get_real_depth_map (self .simulator , depth )
72-
74+
75+ # Flip vertically to match standard image coordinates
7376 depth = np .flipud (depth )
7477
7578 return depth
7679
80+ def _calculate_intrinsics_from_fovy (self ):
81+ """Calculate camera intrinsics from MuJoCo fovy parameter.
82+
83+ MuJoCo cameras only have fovy (field of view in y direction).
84+ We calculate fx, fy, cx, cy from fovy and image dimensions.
85+ """
86+ # Get camera ID and fovy from MuJoCo
87+ cam_id = self .simulator .model .camera_name2id (self .name )
88+ fovy_rad = self .simulator .model .cam_fovy [cam_id ] * np .pi / 180.0 # Convert to radians
89+
90+ # Calculate focal length from fovy
91+ # f = height / (2 * tan(fovy/2))
92+ focal_length = self .height / (2 * np .tan (fovy_rad / 2 ))
93+
94+ # For square pixels, fx = fy = focal_length
95+ fx = fy = focal_length
96+
97+ # Principal point at image center
98+ cx = self .width / 2
99+ cy = self .height / 2
100+
101+ return fx , fy , cx , cy
102+
77103 def get_point_cloud (self ) -> np .ndarray :
78104 """Generate a 3D point cloud from the depth data in world coordinates.
79105
@@ -91,13 +117,16 @@ def get_point_cloud(self) -> np.ndarray:
91117 # Get depth map
92118 depth_map = self .get_depth ()
93119
94- # Generate point cloud in camera frame using intrinsic parameters
120+ # Calculate intrinsics from MuJoCo fovy
121+ fx , fy , cx , cy = self ._calculate_intrinsics_from_fovy ()
122+
123+ # Generate point cloud in camera frame using calculated intrinsic parameters
95124 point_cloud_camera = get_point_cloud_from_depth (
96125 depth_image = depth_map ,
97- fx = self . fx ,
98- fy = self . fy ,
99- cx = self . cx ,
100- cy = self . cy
126+ fx = fx ,
127+ fy = fy ,
128+ cx = cx ,
129+ cy = cy
101130 )
102131
103132 # Filter the point cloud to remove invalid points
@@ -154,15 +183,21 @@ def get_point_cloud_wrt_robot(self, robot, downsample_factor=2, max_distance=2.0
154183 from physics_simulator .utils .camera_utils import get_real_depth_map
155184 depth_map = get_real_depth_map (self .simulator , depth_map )
156185
186+ # Flip vertically to match standard image coordinates (same as get_depth method)
187+ depth_map = np .flipud (depth_map )
188+
189+ # Calculate intrinsics from MuJoCo fovy first
190+ fx , fy , cx , cy = self ._calculate_intrinsics_from_fovy ()
191+
157192 # Downsample for performance if requested
158193 if downsample_factor > 1 :
159194 depth_map = depth_map [::downsample_factor , ::downsample_factor ]
160- fx_scaled = self . fx / downsample_factor
161- fy_scaled = self . fy / downsample_factor
162- cx_scaled = self . cx / downsample_factor
163- cy_scaled = self . cy / downsample_factor
195+ fx_scaled = fx / downsample_factor
196+ fy_scaled = fy / downsample_factor
197+ cx_scaled = cx / downsample_factor
198+ cy_scaled = cy / downsample_factor
164199 else :
165- fx_scaled , fy_scaled , cx_scaled , cy_scaled = self . fx , self . fy , self . cx , self . cy
200+ fx_scaled , fy_scaled , cx_scaled , cy_scaled = fx , fy , cx , cy
166201
167202 # Generate point cloud in camera frame (optimized)
168203 height , width = depth_map .shape
0 commit comments