2
2
import os
3
3
import time
4
4
import math
5
+ from functools import lru_cache
5
6
6
7
import cv2
7
8
import numpy as np
@@ -66,6 +67,14 @@ class Camera(Sensor):
66
67
The far plane of the camera.
67
68
transform : np.ndarray, shape (4, 4), optional
68
69
The transform matrix of the camera.
70
+ env_idx : int, optional
71
+ The index of the environment to track the camera.
72
+ debug : bool, optional
73
+ Whether to use the debug camera. It enables to create cameras that can used to monitor / debug the
74
+ simulation without being part of the "sensors". Their output is rendered by the usual simple Rasterizer
75
+ systematically, no matter if BatchRender and RayTracer is enabled. This way, it is possible to record the
76
+ simulation with arbitrary resolution and camera pose, without interfering with what robots can perceive
77
+ from their environment. Defaults to False.
69
78
"""
70
79
71
80
def __init__ (
@@ -87,6 +96,7 @@ def __init__(
87
96
far = 100.0 ,
88
97
transform = None ,
89
98
env_idx = None ,
99
+ debug = False ,
90
100
):
91
101
self ._idx = idx
92
102
self ._uid = gs .UID ()
@@ -111,6 +121,7 @@ def __init__(
111
121
self ._is_built = False
112
122
self ._attached_link = None
113
123
self ._attached_offset_T = None
124
+ self ._debug = debug
114
125
115
126
self ._env_idx = env_idx
116
127
self ._envs_offset = None
@@ -139,11 +150,10 @@ def build(self):
139
150
140
151
self ._envs_offset = torch .as_tensor (self ._visualizer ._scene .envs_offset , dtype = gs .tc_float , device = gs .device )
141
152
142
- self ._batch_renderer = self ._visualizer .batch_renderer
143
153
self ._rasterizer = self ._visualizer .rasterizer
144
- self ._raytracer = self ._visualizer .raytracer
154
+ self ._raytracer = self ._visualizer .raytracer if not self ._debug else None
155
+ self ._batch_renderer = self ._visualizer .batch_renderer if not self ._debug else None
145
156
146
- self ._rasterizer .add_camera (self )
147
157
if self ._batch_renderer is not None :
148
158
self ._rgb_stacked = True
149
159
self ._other_stacked = True
@@ -157,6 +167,7 @@ def build(self):
157
167
self ._rgb_stacked = False
158
168
self ._other_stacked = False
159
169
else :
170
+ self ._rasterizer .add_camera (self )
160
171
self ._rgb_stacked = self ._visualizer ._context .env_separate_rigid
161
172
self ._other_stacked = self ._visualizer ._context .env_separate_rigid
162
173
@@ -323,13 +334,13 @@ def _batch_render(
323
334
# If n_envs == 0, the second dimension of the output is camera.
324
335
# Only return the current camera's image
325
336
if rgb_arr :
326
- rgb_arr = rgb_arr [self ._idx ]
337
+ rgb_arr = rgb_arr [self .idx ]
327
338
if depth :
328
- depth_arr = depth_arr [self ._idx ]
339
+ depth_arr = depth_arr [self .idx ]
329
340
if segmentation :
330
- seg_arr = seg_arr [self ._idx ]
341
+ seg_arr = seg_arr [self .idx ]
331
342
if normal :
332
- normal_arr = normal_arr [self ._idx ]
343
+ normal_arr = normal_arr [self .idx ]
333
344
return rgb_arr , depth_arr , seg_arr , normal_arr
334
345
335
346
@gs .assert_built
@@ -533,7 +544,6 @@ def render_pointcloud(self, world_frame=True):
533
544
point_cloud = point_cloud [:, :3 ].reshape ((* depth_arr .shape , 3 ))
534
545
return point_cloud , mask
535
546
536
- @gs .assert_built
537
547
def set_pose (self , transform = None , pos = None , lookat = None , up = None , env_idx = None ):
538
548
"""
539
549
Set the pose of the camera.
@@ -608,9 +618,10 @@ def set_pose(self, transform=None, pos=None, lookat=None, up=None, env_idx=None)
608
618
self ._multi_env_transform_tensor [env_idx ] = transform
609
619
self ._multi_env_quat_tensor [env_idx ] = _T_to_quat_for_madrona (transform )
610
620
611
- self ._rasterizer .update_camera (self )
612
621
if self ._raytracer is not None :
613
622
self ._raytracer .update_camera (self )
623
+ elif self ._batch_renderer is None :
624
+ self ._rasterizer .update_camera (self )
614
625
615
626
@gs .assert_built
616
627
def set_params (self , fov = None , aperture = None , focus_dist = None , intrinsics = None ):
@@ -651,9 +662,10 @@ def set_params(self, fov=None, aperture=None, focus_dist=None, intrinsics=None):
651
662
else :
652
663
self ._fov = intrinsics_fov
653
664
654
- self ._rasterizer .update_camera (self )
655
665
if self ._raytracer is not None :
656
666
self ._raytracer .update_camera (self )
667
+ elif self ._batch_renderer is None :
668
+ self ._rasterizer .update_camera (self )
657
669
658
670
@gs .assert_built
659
671
def start_recording (self ):
@@ -753,7 +765,7 @@ def is_built(self):
753
765
754
766
@property
755
767
def idx (self ):
756
- """The integer index of the camera."""
768
+ """The global integer index of the camera."""
757
769
return self ._idx
758
770
759
771
@property
@@ -839,6 +851,11 @@ def env_idx(self):
839
851
"""Index of the environment being tracked by the camera."""
840
852
return self ._env_idx
841
853
854
+ @property
855
+ def debug (self ):
856
+ """Whether the camera is a debug camera."""
857
+ return self ._debug
858
+
842
859
@property
843
860
def pos (self ):
844
861
"""The current position of the camera for the tracked environment."""
0 commit comments