Unverified Commit e5b43e96 authored by renezurbruegg's avatar renezurbruegg Committed by GitHub

Fixes FrameTransformer sensor visualization implementation (#15)

# Description

This MR fixes:
- FrameTransformer crashing when `debug_vis` is set to true
- Hard-coding of visualization configs inside the sensor implementation

## Type of change

- Bug fix (non-breaking change which fixes an issue)

## Checklist

- [x] I have run the [`pre-commit` checks](https://pre-commit.com/) with
`./orbit.sh --format`
- [ ] I have made corresponding changes to the documentation
- [x] My changes generate no new warnings
- [ ] I have added tests that prove my fix is effective or that my
feature works
- [x] I have updated the changelog and the corresponding version in the
extension's `config/extension.toml` file
- [x] I have added my name to the `CONTRIBUTORS.md` or my name already
exists there
parent ab3f3a36
[package]
# Note: Semantic Versioning is used: https://semver.org/
version = "0.9.36"
version = "0.9.37"
# Description
title = "ORBIT framework for Robot Learning"
......
Changelog
---------
0.9.37 (2023-11-06)
~~~~~~~~~~~~~~~~~~~
Fixed
^^^^^
* Fixed broken visualization in :mod:`omni.isaac.orbit.sensors.FrameTramsformer` class by overwriting the
correct ``_debug_vis_callback`` function.
* Moved the visualization marker configurations of sensors to their respective sensor configuration classes.
This allows users to set these configurations from the configuration object itself.
0.9.36 (2023-11-03)
~~~~~~~~~~~~~~~~~~~
......
......@@ -108,7 +108,7 @@ class AssetBase(ABC):
def has_debug_vis_implementation(self) -> bool:
"""Whether the asset has a debug visualization implemented."""
# check if function raises NotImplementedError
source_code = inspect.getsource(self._debug_vis_callback)
source_code = inspect.getsource(self._set_debug_vis_impl)
return "NotImplementedError" not in source_code
"""
......
......@@ -93,7 +93,7 @@ class CommandGeneratorBase(ABC):
def has_debug_vis_implementation(self) -> bool:
"""Whether the command generator has a debug visualization implemented."""
# check if function raises NotImplementedError
source_code = inspect.getsource(self._debug_vis_callback)
source_code = inspect.getsource(self._set_debug_vis_impl)
return "NotImplementedError" not in source_code
"""
......
......@@ -18,7 +18,6 @@ from pxr import PhysxSchema
import omni.isaac.orbit.utils.string as string_utils
from omni.isaac.orbit.markers import VisualizationMarkers
from omni.isaac.orbit.markers.config import CONTACT_SENSOR_MARKER_CFG
from ..sensor_base import SensorBase
from .contact_sensor_data import ContactSensorData
......@@ -280,8 +279,7 @@ class ContactSensor(SensorBase):
if debug_vis:
# create markers if necessary for the first tome
if not hasattr(self, "contact_visualizer"):
visualizer_cfg = CONTACT_SENSOR_MARKER_CFG.replace(prim_path="/Visuals/ContactSensor")
self.contact_visualizer = VisualizationMarkers(visualizer_cfg)
self.contact_visualizer = VisualizationMarkers(self.cfg.visualizer_cfg)
# set their visibility to true
self.contact_visualizer.set_visibility(True)
else:
......
......@@ -5,6 +5,8 @@
from __future__ import annotations
from omni.isaac.orbit.markers import VisualizationMarkersCfg
from omni.isaac.orbit.markers.config import CONTACT_SENSOR_MARKER_CFG
from omni.isaac.orbit.utils import configclass
from ..sensor_base_cfg import SensorBaseCfg
......@@ -33,3 +35,10 @@ class ContactSensorCfg(SensorBaseCfg):
If an empty list is provided, then only net contact forces are reported.
"""
visualizer_cfg: VisualizationMarkersCfg = CONTACT_SENSOR_MARKER_CFG.replace(prim_path="/Visuals/ContactSensor")
"""The configuration object for the visualization markers. Defaults to CONTACT_SENSOR_MARKER_CFG.
Note:
This attribute is only used when debug visualization is enabled.
"""
......@@ -14,7 +14,6 @@ from omni.isaac.core.prims import RigidPrimView
from pxr import UsdPhysics
from omni.isaac.orbit.markers import VisualizationMarkers
from omni.isaac.orbit.markers.config import FRAME_MARKER_CFG
from omni.isaac.orbit.utils.math import (
combine_frame_transforms,
convert_quat,
......@@ -72,9 +71,6 @@ class FrameTransformer(SensorBase):
# Create empty variables for storing output data
self._data: FrameTransformerData = FrameTransformerData()
# visualization markers
self.transform_visualizer = None
def __str__(self) -> str:
"""Returns: A string containing information about the instance."""
return (
......@@ -100,11 +96,6 @@ class FrameTransformer(SensorBase):
Operations
"""
def set_debug_vis(self, debug_vis: bool):
super().set_debug_vis(debug_vis)
if self.frame_transform_visualizer is not None:
self.frame_transform_visualizer.set_visibility(debug_vis)
def reset(self, env_ids: Sequence[int] | None = None):
# reset the timers and counters
super().reset(env_ids)
......@@ -341,11 +332,19 @@ class FrameTransformer(SensorBase):
self._data.target_pos_source[:] = target_pos_source.view(-1, total_num_frames, 3)
self._data.target_rot_source[:] = target_rot_source.view(-1, total_num_frames, 4)
def _debug_vis_impl(self):
# visualize the transform
if self.transform_visualizer is None:
cfg = FRAME_MARKER_CFG.replace(prim_path="/Visuals/FrameTransformer")
cfg.markers["frame"].scale = (0.05, 0.05, 0.05)
self.transform_visualizer = VisualizationMarkers(cfg)
def _set_debug_vis_impl(self, debug_vis: bool):
# set visibility of markers
# note: parent only deals with callbacks. not their visibility
if debug_vis:
if not hasattr(self, "frame_visualizer"):
self.frame_visualizer = VisualizationMarkers(self.cfg.visualizer_cfg)
# set their visibility to true
self.frame_visualizer.set_visibility(True)
else:
if hasattr(self, "frame_visualizer"):
self.frame_visualizer.set_visibility(False)
self.transform_visualizer.visualize(self._data.target_pos_w.view(-1, 3), self._data.target_rot_w.view(-1, 4))
def _debug_vis_callback(self, event):
# Update the visualized markers
if self.frame_visualizer is not None:
self.frame_visualizer.visualize(self._data.target_pos_w.view(-1, 3), self._data.target_rot_w.view(-1, 4))
......@@ -7,6 +7,7 @@ from __future__ import annotations
from dataclasses import MISSING
from omni.isaac.orbit.markers.config import FRAME_MARKER_CFG, VisualizationMarkersCfg
from omni.isaac.orbit.utils import configclass
from ..sensor_base_cfg import SensorBaseCfg
......@@ -60,3 +61,10 @@ class FrameTransformerCfg(SensorBaseCfg):
we can use a single FrameTransformer to track each foot's position and orientation in the body
frame using four frame offsets.
"""
visualizer_cfg: VisualizationMarkersCfg = FRAME_MARKER_CFG.replace(prim_path="/Visuals/FrameTransformer")
"""The configuration object for the visualization markers. Defaults to FRAME_MARKER_CFG.
Note:
This attribute is only used when debug visualization is enabled.
"""
......@@ -17,7 +17,6 @@ from omni.isaac.core.prims import RigidPrimView, XFormPrimView
from pxr import UsdGeom, UsdPhysics
from omni.isaac.orbit.markers import VisualizationMarkers
from omni.isaac.orbit.markers.config import RAY_CASTER_MARKER_CFG
from omni.isaac.orbit.terrains.trimesh.utils import make_plane
from omni.isaac.orbit.utils.math import quat_apply, quat_apply_yaw
from omni.isaac.orbit.utils.warp import convert_to_warp_mesh, raycast_mesh
......@@ -240,8 +239,7 @@ class RayCaster(SensorBase):
# note: parent only deals with callbacks. not their visibility
if debug_vis:
if not hasattr(self, "ray_visualizer"):
visualizer_cfg = RAY_CASTER_MARKER_CFG.replace(prim_path="/Visuals/RayCaster")
self.ray_visualizer = VisualizationMarkers(visualizer_cfg)
self.ray_visualizer = VisualizationMarkers(self.cfg.visualizer_cfg)
# set their visibility to true
self.ray_visualizer.set_visibility(True)
else:
......
......@@ -9,6 +9,8 @@ from __future__ import annotations
from dataclasses import MISSING
from omni.isaac.orbit.markers import VisualizationMarkersCfg
from omni.isaac.orbit.markers.config import RAY_CASTER_MARKER_CFG
from omni.isaac.orbit.utils import configclass
from ..sensor_base_cfg import SensorBaseCfg
......@@ -59,3 +61,10 @@ class RayCasterCfg(SensorBaseCfg):
For floating base robots, this is useful for simulating drift in the robot's pose estimation.
"""
visualizer_cfg: VisualizationMarkersCfg = RAY_CASTER_MARKER_CFG.replace(prim_path="/Visuals/FrameTransformer")
"""The configuration object for the visualization markers. Defaults to RAY_CASTER_MARKER_CFG.
Note:
This attribute is only used when debug visualization is enabled.
"""
......@@ -118,8 +118,7 @@ class SensorBase(ABC):
def has_debug_vis_implementation(self) -> bool:
"""Whether the sensor has a debug visualization implemented."""
# check if function raises NotImplementedError
# check if function raises NotImplementedError
source_code = inspect.getsource(self._debug_vis_callback)
source_code = inspect.getsource(self._set_debug_vis_impl)
return "NotImplementedError" not in source_code
"""
......
......@@ -182,7 +182,7 @@ def main():
# to step through each frame so the user can verify that the correct frame
# is being visualized as the frame names are printing to console
if not args_cli.visualize:
cfg = FRAME_MARKER_CFG.replace(prim_path="/Visuals/FrameTransformer")
cfg = FRAME_MARKER_CFG.replace(prim_path="/Visuals/FrameVisualizerFromScript")
cfg.markers["frame"].scale = (0.05, 0.05, 0.05)
transform_visualizer = VisualizationMarkers(cfg)
else:
......@@ -237,6 +237,7 @@ def main():
print(f"Displaying {frame_index}: {frame_name}")
frame_index += 1
frame_index = frame_index % len(frame_names)
# visualize frame
pos = scene["frame_transformer"].data.target_pos_w[:, frame_index]
rot = scene["frame_transformer"].data.target_rot_w[:, frame_index]
......
......@@ -18,7 +18,6 @@ from __future__ import annotations
import argparse
# omni-isaac-orbit
from omni.isaac.kit import SimulationApp
# add argparse arguments
......@@ -41,18 +40,17 @@ simulation_app = SimulationApp(config)
"""Rest everything follows."""
import numpy as np
import torch
import traceback
import carb
import omni.isaac.core.utils.prims as prim_utils
from omni.isaac.cloner import GridCloner
from omni.isaac.core.objects import DynamicSphere
from omni.isaac.core.prims import RigidPrimView
from omni.isaac.core.simulation_context import SimulationContext
from omni.isaac.core.utils.viewports import set_camera_view
import omni.isaac.orbit.sim as sim_utils
import omni.isaac.orbit.terrains as terrain_gen
from omni.isaac.orbit.sensors.ray_caster import RayCaster, RayCasterCfg, patterns
from omni.isaac.orbit.terrains.config.rough import ROUGH_TERRAINS_CFG
......@@ -70,16 +68,17 @@ def design_scene(sim: SimulationContext, num_envs: int = 2048):
prim_utils.define_prim("/World/envs/env_0")
# Define the scene
# -- Light
prim_utils.create_prim("/World/light", "DistantLight")
cfg = sim_utils.DistantLightCfg(intensity=2000)
cfg.func("/World/light", cfg)
# -- Balls
# -- Ball physics
DynamicSphere(
prim_path="/World/envs/env_0/ball",
translation=np.array([0.0, 0.0, 5.0]),
mass=0.5,
cfg = sim_utils.SphereCfg(
radius=0.25,
color=np.asarray((0.0, 0.0, 1.0)),
rigid_props=sim_utils.RigidBodyPropertiesCfg(),
mass_props=sim_utils.MassPropertiesCfg(mass=0.5),
collision_props=sim_utils.CollisionPropertiesCfg(),
visual_material=sim_utils.PreviewSurfaceCfg(diffuse_color=(0.0, 0.0, 1.0)),
)
cfg.func("/World/envs/env_0/ball", cfg, translation=(0.0, 0.0, 5.0))
# Clone the scene
cloner.define_base_env("/World/envs")
envs_prim_paths = cloner.generate_paths("/World/envs/env", num_paths=num_envs)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment