Unverified Commit e444df7d authored by Mayank Mittal's avatar Mayank Mittal Committed by GitHub

Adapts terms to deal with slice values for SceneEntityCfg.body_ids (#447)

# Description

With commit d682c8dd, the code stopped working. Somehow, the tests did not
catch the issue, but it shows up when you run the workflows. Anyway, this
MR makes the fix necessary to deal with slices.

Fixes https://github.com/NVIDIA-Omniverse/orbit/issues/277 ,
https://github.com/NVIDIA-Omniverse/orbit/issues/276

## 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`
- [x] 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 run all the tests with `./orbit.sh --test` and they pass
- [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 51413145
[package] [package]
# Note: Semantic Versioning is used: https://semver.org/ # Note: Semantic Versioning is used: https://semver.org/
version = "0.12.3" version = "0.12.4"
# Description # Description
title = "ORBIT framework for Robot Learning" title = "ORBIT framework for Robot Learning"
......
Changelog Changelog
--------- ---------
0.12.4 (2024-03-11)
~~~~~~~~~~~~~~~~~~~
Fixed
^^^^^
* Adapted randomization terms to deal with ``slice`` for the body indices. Earlier, the terms were not
able to handle the slice object and were throwing an error.
* Added ``slice`` type-hinting to all body and joint related methods in the rigid body and articulation
classes. This is to make it clear that the methods can handle both list of indices and slices.
0.12.3 (2024-03-11) 0.12.3 (2024-03-11)
~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~
......
...@@ -235,8 +235,8 @@ class Articulation(RigidObject): ...@@ -235,8 +235,8 @@ class Articulation(RigidObject):
self, self,
position: torch.Tensor, position: torch.Tensor,
velocity: torch.Tensor, velocity: torch.Tensor,
joint_ids: Sequence[int] | None = None, joint_ids: Sequence[int] | slice | None = None,
env_ids: Sequence[int] | None = None, env_ids: Sequence[int] | slice | None = None,
): ):
"""Write joint positions and velocities to the simulation. """Write joint positions and velocities to the simulation.
...@@ -265,7 +265,7 @@ class Articulation(RigidObject): ...@@ -265,7 +265,7 @@ class Articulation(RigidObject):
def write_joint_stiffness_to_sim( def write_joint_stiffness_to_sim(
self, self,
stiffness: torch.Tensor | float, stiffness: torch.Tensor | float,
joint_ids: Sequence[int] | None = None, joint_ids: Sequence[int] | slice | None = None,
env_ids: Sequence[int] | None = None, env_ids: Sequence[int] | None = None,
): ):
"""Write joint stiffness into the simulation. """Write joint stiffness into the simulation.
...@@ -291,7 +291,7 @@ class Articulation(RigidObject): ...@@ -291,7 +291,7 @@ class Articulation(RigidObject):
def write_joint_damping_to_sim( def write_joint_damping_to_sim(
self, self,
damping: torch.Tensor | float, damping: torch.Tensor | float,
joint_ids: Sequence[int] | None = None, joint_ids: Sequence[int] | slice | None = None,
env_ids: Sequence[int] | None = None, env_ids: Sequence[int] | None = None,
): ):
"""Write joint damping into the simulation. """Write joint damping into the simulation.
...@@ -319,7 +319,7 @@ class Articulation(RigidObject): ...@@ -319,7 +319,7 @@ class Articulation(RigidObject):
def write_joint_effort_limit_to_sim( def write_joint_effort_limit_to_sim(
self, self,
limits: torch.Tensor | float, limits: torch.Tensor | float,
joint_ids: Sequence[int] | None = None, joint_ids: Sequence[int] | slice | None = None,
env_ids: Sequence[int] | None = None, env_ids: Sequence[int] | None = None,
): ):
"""Write joint effort limits into the simulation. """Write joint effort limits into the simulation.
...@@ -349,7 +349,7 @@ class Articulation(RigidObject): ...@@ -349,7 +349,7 @@ class Articulation(RigidObject):
def write_joint_armature_to_sim( def write_joint_armature_to_sim(
self, self,
armature: torch.Tensor | float, armature: torch.Tensor | float,
joint_ids: Sequence[int] | None = None, joint_ids: Sequence[int] | slice | None = None,
env_ids: Sequence[int] | None = None, env_ids: Sequence[int] | None = None,
): ):
"""Write joint armature into the simulation. """Write joint armature into the simulation.
...@@ -374,7 +374,7 @@ class Articulation(RigidObject): ...@@ -374,7 +374,7 @@ class Articulation(RigidObject):
def write_joint_friction_to_sim( def write_joint_friction_to_sim(
self, self,
joint_friction: torch.Tensor | float, joint_friction: torch.Tensor | float,
joint_ids: Sequence[int] | None = None, joint_ids: Sequence[int] | slice | None = None,
env_ids: Sequence[int] | None = None, env_ids: Sequence[int] | None = None,
): ):
"""Write joint friction into the simulation. """Write joint friction into the simulation.
...@@ -401,7 +401,7 @@ class Articulation(RigidObject): ...@@ -401,7 +401,7 @@ class Articulation(RigidObject):
""" """
def set_joint_position_target( def set_joint_position_target(
self, target: torch.Tensor, joint_ids: Sequence[int] | None = None, env_ids: Sequence[int] | None = None self, target: torch.Tensor, joint_ids: Sequence[int] | slice | None = None, env_ids: Sequence[int] | None = None
): ):
"""Set joint position targets into internal buffers. """Set joint position targets into internal buffers.
...@@ -423,7 +423,7 @@ class Articulation(RigidObject): ...@@ -423,7 +423,7 @@ class Articulation(RigidObject):
self._data.joint_pos_target[env_ids, joint_ids] = target self._data.joint_pos_target[env_ids, joint_ids] = target
def set_joint_velocity_target( def set_joint_velocity_target(
self, target: torch.Tensor, joint_ids: Sequence[int] | None = None, env_ids: Sequence[int] | None = None self, target: torch.Tensor, joint_ids: Sequence[int] | slice | None = None, env_ids: Sequence[int] | None = None
): ):
"""Set joint velocity targets into internal buffers. """Set joint velocity targets into internal buffers.
...@@ -445,7 +445,7 @@ class Articulation(RigidObject): ...@@ -445,7 +445,7 @@ class Articulation(RigidObject):
self._data.joint_vel_target[env_ids, joint_ids] = target self._data.joint_vel_target[env_ids, joint_ids] = target
def set_joint_effort_target( def set_joint_effort_target(
self, target: torch.Tensor, joint_ids: Sequence[int] | None = None, env_ids: Sequence[int] | None = None self, target: torch.Tensor, joint_ids: Sequence[int] | slice | None = None, env_ids: Sequence[int] | None = None
): ):
"""Set joint efforts into internal buffers. """Set joint efforts into internal buffers.
......
...@@ -222,7 +222,7 @@ class RigidObject(AssetBase): ...@@ -222,7 +222,7 @@ class RigidObject(AssetBase):
self, self,
forces: torch.Tensor, forces: torch.Tensor,
torques: torch.Tensor, torques: torch.Tensor,
body_ids: Sequence[int] | None = None, body_ids: Sequence[int] | slice | None = None,
env_ids: Sequence[int] | None = None, env_ids: Sequence[int] | None = None,
): ):
"""Set external force and torque to apply on the asset's bodies in their local frame. """Set external force and torque to apply on the asset's bodies in their local frame.
...@@ -261,6 +261,8 @@ class RigidObject(AssetBase): ...@@ -261,6 +261,8 @@ class RigidObject(AssetBase):
# -- body_ids # -- body_ids
if body_ids is None: if body_ids is None:
body_ids = torch.arange(self.num_bodies, dtype=torch.long, device=self.device) body_ids = torch.arange(self.num_bodies, dtype=torch.long, device=self.device)
elif isinstance(body_ids, slice):
body_ids = torch.arange(self.num_bodies, dtype=torch.long, device=self.device)[body_ids]
elif not isinstance(body_ids, torch.Tensor): elif not isinstance(body_ids, torch.Tensor):
body_ids = torch.tensor(body_ids, dtype=torch.long, device=self.device) body_ids = torch.tensor(body_ids, dtype=torch.long, device=self.device)
......
...@@ -62,7 +62,12 @@ def randomize_rigid_body_material( ...@@ -62,7 +62,12 @@ def randomize_rigid_body_material(
num_envs = env.scene.num_envs num_envs = env.scene.num_envs
# resolve environment ids # resolve environment ids
if env_ids is None: if env_ids is None:
env_ids = torch.arange(num_envs) env_ids = torch.arange(num_envs, device="cpu")
# resolve body indices
if isinstance(asset_cfg.body_ids, slice):
body_ids = torch.arange(asset.num_bodies, dtype=torch.int, device="cpu")[asset_cfg.body_ids]
else:
body_ids = torch.tensor(asset_cfg.body_ids, dtype=torch.int, device="cpu")
# sample material properties from the given ranges # sample material properties from the given ranges
material_buckets = torch.zeros(num_buckets, 3) material_buckets = torch.zeros(num_buckets, 3)
...@@ -74,11 +79,10 @@ def randomize_rigid_body_material( ...@@ -74,11 +79,10 @@ def randomize_rigid_body_material(
materials = material_buckets[material_ids] materials = material_buckets[material_ids]
# resolve the global body indices from the env_ids and the env_body_ids # resolve the global body indices from the env_ids and the env_body_ids
bodies_per_env = asset.body_physx_view.count // num_envs # - number of bodies per spawned asset bodies_per_env = asset.body_physx_view.count // num_envs # - number of bodies per spawned asset
indices = torch.tensor(asset_cfg.body_ids, dtype=torch.int).repeat(len(env_ids), 1) indices = body_ids.repeat(len(env_ids), 1)
indices += env_ids.unsqueeze(1) * bodies_per_env indices += env_ids.unsqueeze(1) * bodies_per_env
# set the material properties into the physics simulation # set the material properties into the physics simulation
# TODO: Need to use CPU tensors for now. Check if this changes in the new release
asset.body_physx_view.set_material_properties(materials, indices) asset.body_physx_view.set_material_properties(materials, indices)
...@@ -96,18 +100,22 @@ def add_body_mass( ...@@ -96,18 +100,22 @@ def add_body_mass(
num_envs = env.scene.num_envs num_envs = env.scene.num_envs
# resolve environment ids # resolve environment ids
if env_ids is None: if env_ids is None:
env_ids = torch.arange(num_envs) env_ids = torch.arange(num_envs, device="cpu")
# resolve body indices
if isinstance(asset_cfg.body_ids, slice):
body_ids = torch.arange(asset.num_bodies, dtype=torch.int, device="cpu")[asset_cfg.body_ids]
else:
body_ids = torch.tensor(asset_cfg.body_ids, dtype=torch.int, device="cpu")
# get the current masses of the bodies (num_assets x num_bodies) # get the current masses of the bodies (num_assets x num_bodies)
masses = asset.body_physx_view.get_masses() masses = asset.body_physx_view.get_masses()
masses += sample_uniform(*mass_range, masses.shape, device=masses.device) masses += sample_uniform(*mass_range, masses.shape, device=masses.device)
# resolve the global body indices from the env_ids and the env_body_ids # resolve the global body indices from the env_ids and the env_body_ids
bodies_per_env = asset.body_physx_view.count // env.num_envs bodies_per_env = asset.body_physx_view.count // env.num_envs
indices = torch.tensor(asset_cfg.body_ids, dtype=torch.int).repeat(len(env_ids), 1) indices = body_ids.repeat(len(env_ids), 1)
indices += env_ids.unsqueeze(1) * bodies_per_env indices += env_ids.unsqueeze(1) * bodies_per_env
# set the mass into the physics simulation # set the mass into the physics simulation
# TODO: Need to use CPU tensors for now. Check if this changes in the new release
asset.body_physx_view.set_masses(masses, indices) asset.body_physx_view.set_masses(masses, indices)
...@@ -123,7 +131,7 @@ def apply_external_force_torque( ...@@ -123,7 +131,7 @@ def apply_external_force_torque(
This function creates a set of random forces and torques sampled from the given ranges. The number of forces This function creates a set of random forces and torques sampled from the given ranges. The number of forces
and torques is equal to the number of bodies times the number of environments. The forces and torques are and torques is equal to the number of bodies times the number of environments. The forces and torques are
applied to the bodies by calling ``asset.set_external_force_and_torque``. The forces and torques are only applied to the bodies by calling ``asset.set_external_force_and_torque``. The forces and torques are only
applied when ``asset.write_data_to_sim()`` is called. applied when ``asset.write_data_to_sim()`` is called in the environment.
""" """
# extract the used quantities (to enable type-hinting) # extract the used quantities (to enable type-hinting)
asset: RigidObject = env.scene[asset_cfg.name] asset: RigidObject = env.scene[asset_cfg.name]
...@@ -131,9 +139,11 @@ def apply_external_force_torque( ...@@ -131,9 +139,11 @@ def apply_external_force_torque(
# resolve environment ids # resolve environment ids
if env_ids is None: if env_ids is None:
env_ids = torch.arange(num_envs) env_ids = torch.arange(num_envs)
# resolve number of bodies
num_bodies = len(asset_cfg.body_ids) if isinstance(asset_cfg.body_ids, list) else asset.num_bodies
# sample random forces and torques # sample random forces and torques
size = (len(env_ids), len(asset_cfg.body_ids), 3) size = (len(env_ids), num_bodies, 3)
forces = sample_uniform(*force_range, size, asset.device) forces = sample_uniform(*force_range, size, asset.device)
torques = sample_uniform(*torque_range, size, asset.device) torques = sample_uniform(*torque_range, size, asset.device)
# set the forces and torques into the buffers # set the forces and torques into the buffers
......
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