|
15 | 15 | import omni.kit.app |
16 | 16 | import omni.timeline |
17 | 17 |
|
| 18 | +from omni.isaac.lab.assets.articulation.articulation import Articulation |
| 19 | + |
18 | 20 | if TYPE_CHECKING: |
19 | 21 | from omni.isaac.lab.envs import DirectRLEnv, ManagerBasedEnv, ViewerCfg |
20 | 22 |
|
@@ -59,12 +61,15 @@ def __init__(self, env: ManagerBasedEnv | DirectRLEnv, cfg: ViewerCfg): |
59 | 61 | self.set_view_env_index(self.cfg.env_index) |
60 | 62 | # set the camera origin to the center of the environment |
61 | 63 | self.update_view_to_env() |
62 | | - elif self.cfg.origin_type == "asset_root": |
| 64 | + elif self.cfg.origin_type == "asset_root" or self.cfg.origin_type == "asset_body": |
63 | 65 | # note: we do not yet update camera for tracking an asset origin, as the asset may not yet be |
64 | 66 | # in the scene when this is called. Instead, we subscribe to the post update event to update the camera |
65 | 67 | # at each rendering step. |
66 | 68 | if self.cfg.asset_name is None: |
67 | 69 | raise ValueError(f"No asset name provided for viewer with origin type: '{self.cfg.origin_type}'.") |
| 70 | + if self.cfg.origin_type == "asset_body": |
| 71 | + if self.cfg.body_name is None: |
| 72 | + raise ValueError(f"No body name provided for viewer with origin type: '{self.cfg.origin_type}'.") |
68 | 73 | else: |
69 | 74 | # set the camera origin to the center of the world |
70 | 75 | self.update_view_to_world() |
@@ -160,6 +165,41 @@ def update_view_to_asset_root(self, asset_name: str): |
160 | 165 | # update the camera view |
161 | 166 | self.update_view_location() |
162 | 167 |
|
| 168 | + def update_view_to_asset_body(self, asset_name: str, body_name: str): |
| 169 | + """Updates the viewer's origin based upon the body of an asset in the scene. |
| 170 | +
|
| 171 | + Args: |
| 172 | + asset_name: The name of the asset in the scene. The name should match the name of the |
| 173 | + asset in the scene. |
| 174 | + body_name: The name of the body in the asset. |
| 175 | +
|
| 176 | + Raises: |
| 177 | + ValueError: If the asset is not in the scene or the body is not valid. |
| 178 | + """ |
| 179 | + # check if the asset is in the scene |
| 180 | + if self.cfg.asset_name != asset_name: |
| 181 | + asset_entities = [*self._env.scene.rigid_objects.keys(), *self._env.scene.articulations.keys()] |
| 182 | + if asset_name not in asset_entities: |
| 183 | + raise ValueError(f"Asset '{asset_name}' is not in the scene. Available entities: {asset_entities}.") |
| 184 | + # check if the body is in the asset |
| 185 | + asset: Articulation = self._env.scene[asset_name] |
| 186 | + if body_name not in asset.body_names: |
| 187 | + raise ValueError( |
| 188 | + f"'{body_name}' is not a body of Asset '{asset_name}'. Available bodies: {asset.body_names}." |
| 189 | + ) |
| 190 | + # get the body index |
| 191 | + body_id, _ = asset.find_bodies(body_name) |
| 192 | + # update the asset name |
| 193 | + self.cfg.asset_name = asset_name |
| 194 | + # set origin type to asset_body |
| 195 | + self.cfg.origin_type = "asset_body" |
| 196 | + # update the camera origins |
| 197 | + self.viewer_origin = ( |
| 198 | + self._env.scene[self.cfg.asset_name].data.body_link_pos_w[self.cfg.env_index, body_id].view(3) |
| 199 | + ) |
| 200 | + # update the camera view |
| 201 | + self.update_view_location() |
| 202 | + |
163 | 203 | def update_view_location(self, eye: Sequence[float] | None = None, lookat: Sequence[float] | None = None): |
164 | 204 | """Updates the camera view pose based on the current viewer origin and the eye and lookat positions. |
165 | 205 |
|
@@ -190,3 +230,5 @@ def _update_tracking_callback(self, event): |
190 | 230 | # in other cases, the camera view is static and does not need to be updated continuously |
191 | 231 | if self.cfg.origin_type == "asset_root" and self.cfg.asset_name is not None: |
192 | 232 | self.update_view_to_asset_root(self.cfg.asset_name) |
| 233 | + if self.cfg.origin_type == "asset_body" and self.cfg.asset_name is not None and self.cfg.body_name is not None: |
| 234 | + self.update_view_to_asset_body(self.cfg.asset_name, self.cfg.body_name) |
0 commit comments