-
Notifications
You must be signed in to change notification settings - Fork 2.8k
Adds visual-based tactile sensor with shape sensing example #3420
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
clean up license and configs; use full import path; add doc for visuo_tactile_sensor
| References | ||
| ~~~~~~~~~~ | ||
|
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@iakinola23 Could you help view this documentation here? Thanks!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hi @iakinola23 updated the documentation with your edits.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@kellyguo11 Hi Kelly, I will upload the npz binaries, and the USD files to nucleus once the licensing concerns are resolved. Thanks!
kellyguo11
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
just a few high-level comments, haven't gone through the code in detail yet
| taxim_gelsight = gelsightRender("gelsight_r15") | ||
| import ipdb | ||
|
|
||
| ipdb.set_trace() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why is there a breakpoint here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
deleted in the newest commit.
| self._camera_sensor = TiledCamera(self.cfg.camera_cfg) | ||
|
|
||
| # Initialize camera if not already done | ||
| # TODO: Juana: this is a hack to initialize the camera sensor. Should camera_sensor be managed by TacSL sensor or InteractiveScene? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
maybe we can do something similar as the Raycaster camera?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hi Kelly, I checked the RayCasterCamera implementation, and it differs slightly from the tacsl sensor logic. The tacsl_sensor includes a camera sensor that can be enabled or disabled via the cfg, while RayCasterCamera only uses CameraData without having a camera or other sensor as a member. I’ve kept the current implementation and cleaned up the comments. Please let me know if you have any further concerns or suggestions.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
images should be .jpg
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
all changed to jpg format and documentation is updated accordingly.
| .. code-block:: bash | ||
| conda activate env_isaaclab | ||
| pip install opencv-python==4.11.0 trimesh==4.5.1 imageio==2.37.0 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
do we need to add these to setup.py?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added opencv-python to setup.py; trimesh is already included, and imageio's dependency is not required in the newest commit.
| license agreement from NVIDIA CORPORATION is strictly prohibited. | ||
| ---------------- | ||
| Tensorized implementation of RGB rendering of gelsight-style visuo-tactile sensors |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can you also add any licenses required for gelsight under docs/licenses?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Updated the license header to be consistent with other files.
|
please also make sure to run ./isaaclab.sh -f for the linter checks |
| return dzdx, dzdy | ||
|
|
||
|
|
||
| def generate_normals(height_map): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
generate_normals not needed and deprecated. only the tensorized version is used.
| self.background_tensor = torch.tensor(self.background, device=self.device) | ||
| print("Gelsight initialization done!") | ||
|
|
||
| def render(self, heightMap): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Delete render as it is not used. Only the tensorized version (render_tensorized ) is used.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
deleted render , generate_normals, and compute_image_gradient , padding as well.
|
Thank you for making TacSL available on IsaacLab! I have three quick questions:
Thanks! |
|
@ooctipus @Mayankm96 could you please help do a review of this one? |
|
@zxhuang97 Hi, thanks for your questions and for checking out TacSL on IsaacLab.
Hope this helps! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Only this diagram seems to be getting used. Please remove any unused images.
| conf_r15 = { | ||
| "data_dir": "gelsight_r15_data", | ||
| "background_path": "bg.jpg", | ||
| "calib_path": "polycalib.npz", | ||
| "real_bg": "real_bg.npy", | ||
| "h": 320, | ||
| "w": 240, | ||
| "numBins": 120, | ||
| "pixmm": 0.0877, | ||
| } | ||
| conf_gs_mini = { | ||
| "data_dir": "gs_mini_data", | ||
| "background_path": "bg.jpg", | ||
| "calib_path": "polycalib.npz", | ||
| "real_bg": "real_bg.npy", | ||
| "h": 240, | ||
| "w": 320, | ||
| "numBins": 120, | ||
| "pixmm": 0.065, | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Following all other sensors, please make these into configclass objects with the correct doc-strings. We usually don't want to keep sensor-specific settings in the core codebase.
Sensors configuration live here: https://github.com/isaac-sim/IsaacLab/tree/main/source/isaaclab_assets/isaaclab_assets/sensors
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please choose variable names that are intuitive to read and understand. "h" and "w" are insufficient.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the suggestion. A Config class has been added here and gelsight configs are put under isaaclab_asets/sensors
| ) | ||
|
|
||
|
|
||
| def mkdir_helper(dir_path): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please add type annotations correctly along with docstrings to the code here.
| """Visualize the tactile shear field. | ||
| Args: | ||
| tactile_normal_force: Array of tactile normal forces. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Missing shape information.
| """Visualize the penetration depth. | ||
| Args: | ||
| penetration_depth_img: Image of penetration depth. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Missing shape information. How are the defaults chosen? Would be good to have some reference.
source/isaaclab/isaaclab/sensors/tacsl_sensor/visuotactile_render.py
Outdated
Show resolved
Hide resolved
| """Generate the gradient magnitude and direction of the height map. | ||
| Args: | ||
| img: Input height map tensor. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Missing shape information.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
| kernel_sz: Size of the kernel. Defaults to 5. | ||
| Returns: | ||
| Filtering kernel. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Missing shape information.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
| """Apply Gaussian filtering to the input image tensor. | ||
| Args: | ||
| img: Input image tensor. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Missing shape information.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
| if self.cfg.debug_vis: | ||
| self._initialize_visualization() | ||
|
|
||
| def get_initial_render(self) -> dict | None: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this value used anywhere downstream? How does it handle nominal value when environments are getting reseted? I was wondering if this call should happen inside the sensor reset
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually, the sensor uses this stored "no-contact" image to calculate deformation (diff = nominal - current) every step. Capturing it once should be enough and safe because a reset might happen while the robot is holding an object.
I've also added the warning to the docstring. It now explicitly states that the user must ensure the sensor is in a "no contact" state when calling this method to avoid incorrect baselines. Thanks for pointing this out—your feedback helped clarify this important detail.
|
|
||
| import isaacsim.core.utils.torch as torch_utils | ||
| import omni.log | ||
| from isaacsim.core.prims import SdfShapePrim |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As we are working towards getting rid of isaacsim dependencies, would it be possible to use PhysX views directly and not rely on Isaac Sim classes for SDF? I don't think they are doing much besides creating the PhysX views internally.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Changed to call create_sdf_shape_view from physx view directly.
| from scipy.spatial.transform import Rotation as R | ||
| from typing import TYPE_CHECKING, Any | ||
|
|
||
| import isaacsim.core.utils.torch as torch_utils |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is it possible to use the math utils provided with Isaac Lab: isaaclab.utils.math?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
| # Timing statistics | ||
| ######################################################################################### | ||
|
|
||
| def get_timing_summary(self) -> dict: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To stay consistent with other sensor classes, this shouldn't belong to the sensor class itself. All benchmarking should be done outside in user code.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Removed benchmarking code.
source/isaaclab/isaaclab/sensors/tacsl_sensor/visuotactile_sensor.py
Outdated
Show resolved
Hide resolved
| compliant_contact_stiffness: float | None = None | ||
| compliant_contact_damping: float | None = None |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Missing doc strings.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
| func: Callable = from_files.spawn_from_usd_with_physics_material_on_prim | ||
| compliant_contact_stiffness: float | None = None | ||
| compliant_contact_damping: float | None = None | ||
| apply_physics_material_prim_path: str | None = None |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
apply sounds more of a function name which makes it confusing. My expectation would be that this is a bool variable which says whether to apply or not. But it is a string. Is there a better name we can use here instead that is less ambiguou?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Updated to "physics_material_prim_path", hope it's less confusing :)
source/isaaclab/isaaclab/sim/spawners/from_files/from_files_cfg.py
Outdated
Show resolved
Hide resolved
| func: Callable = from_files.spawn_from_usd_with_physics_material_on_prim | ||
| compliant_contact_stiffness: float | None = None | ||
| compliant_contact_damping: float | None = None | ||
| apply_physics_material_prim_path: str | None = None |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
does this only work for one rigidbody in the usd?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added support for multiple rigidbodies here, thanks.
source/isaaclab/isaaclab/sensors/tacsl_sensor/visuotactile_sensor_cfg.py
Show resolved
Hide resolved
| contact_object_velocities = self._contact_object_body_view.get_velocities() | ||
| contact_object_linvel_w = contact_object_velocities[env_ids, :3] | ||
| contact_object_angvel_w = contact_object_velocities[env_ids, 3:] | ||
|
|
||
| elastomer_velocities = self._elastomer_body_view.get_velocities() | ||
| elastomer_linvel_w = elastomer_velocities[env_ids, :3] | ||
| elastomer_angvel_w = elastomer_velocities[env_ids, 3:] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
One thing to be careful with here is that the velocities returned from the body view are the velocity of the COM of that body. If your *_body_view.get_coms() has non zero transforms your velocity values will be incorrect. I would suggest getting the getting the COMs of the contact body and elastomer body at init and then doing the linear velocity transforms (see IMU update call)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for pointing that out and for the detailed explanation. I’ll update the implementation here to use the COMs of the contact body and elastomer body for the velocity transforms as you suggested.
…der.py Co-authored-by: Mayank Mittal <[email protected]> Signed-off-by: Juana <[email protected]>
…der.py Co-authored-by: Mayank Mittal <[email protected]> Signed-off-by: Juana <[email protected]>
…sor.py Co-authored-by: Mayank Mittal <[email protected]> Signed-off-by: Juana <[email protected]>
…sor.py Co-authored-by: Mayank Mittal <[email protected]> Signed-off-by: Juana <[email protected]>
…sor_cfg.py Co-authored-by: James Tigue <[email protected]> Signed-off-by: Juana <[email protected]>
…g.py Co-authored-by: Mayank Mittal <[email protected]> Signed-off-by: Juana <[email protected]>
Description
This is an implementation of TacSL integrated with Isaac Lab, which demonstrates how to properly configure and use tactile sensors to obtain realistic sensor outputs including tactile RGB images, force fields, and other relevant tactile measurements.
Fixes # (issue)
Type of change
Screenshots
The screenshots of added documentation and simulation outputs.



Checklist
pre-commitchecks with./isaaclab.sh --formatconfig/extension.tomlfileCONTRIBUTORS.mdor my name already exists there