Unverified Commit 7b92c575 authored by Mayank Mittal's avatar Mayank Mittal Committed by GitHub

Decouples rigid object and articulation asset classes (#644)

# Description

Since we override a lot of the functions from RigidObject inside the
Articulation class, we don't need to rely on inheritance anymore.
Duplicacy in the code makes it easier to understand the two classes'
functionalities without severely added overhead from the maintenance
side. Moreover, conceptually, it can be motivated that the two are
independent concepts.

This MR decouples the rigid object and articulation concepts in the
framework.

## Type of change

- Breaking change (fix or feature that would cause existing
functionality to not work as expected)
- This change requires a documentation update

## Checklist

- [x] I have run the [`pre-commit` checks](https://pre-commit.com/) with
`./isaaclab.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 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

---------
Co-authored-by: 's avatarDavid Hoeller <dhoeller@nvidia.com>
parent 809d090d
[package] [package]
# Note: Semantic Versioning is used: https://semver.org/ # Note: Semantic Versioning is used: https://semver.org/
version = "0.20.5" version = "0.20.6"
# Description # Description
title = "Isaac Lab framework for Robot Learning" title = "Isaac Lab framework for Robot Learning"
......
Changelog Changelog
--------- ---------
0.20.6 (2024-08-02)
~~~~~~~~~~~~~~~~~~~
Changed
^^^^^^^
* Removed the hierarchy from :class:`~omni.isaac.lab.assets.RigidObject` class to
:class:`~omni.isaac.lab.assets.Articulation` class. Previously, the articulation class overrode almost
all the functions of the rigid object class making the hierarchy redundant. Now, the articulation class
is a standalone class that does not inherit from the rigid object class. This does add some code
duplication but the simplicity and clarity of the code is improved.
0.20.5 (2024-08-02) 0.20.5 (2024-08-02)
~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~
......
...@@ -8,21 +8,25 @@ from dataclasses import MISSING ...@@ -8,21 +8,25 @@ from dataclasses import MISSING
from omni.isaac.lab.actuators import ActuatorBaseCfg from omni.isaac.lab.actuators import ActuatorBaseCfg
from omni.isaac.lab.utils import configclass from omni.isaac.lab.utils import configclass
from ..rigid_object import RigidObjectCfg from ..asset_base_cfg import AssetBaseCfg
from .articulation import Articulation from .articulation import Articulation
@configclass @configclass
class ArticulationCfg(RigidObjectCfg): class ArticulationCfg(AssetBaseCfg):
"""Configuration parameters for an articulation.""" """Configuration parameters for an articulation."""
class_type: type = Articulation
@configclass @configclass
class InitialStateCfg(RigidObjectCfg.InitialStateCfg): class InitialStateCfg(AssetBaseCfg.InitialStateCfg):
"""Initial state of the articulation.""" """Initial state of the articulation."""
# root position # root velocity
lin_vel: tuple[float, float, float] = (0.0, 0.0, 0.0)
"""Linear velocity of the root in simulation world frame. Defaults to (0.0, 0.0, 0.0)."""
ang_vel: tuple[float, float, float] = (0.0, 0.0, 0.0)
"""Angular velocity of the root in simulation world frame. Defaults to (0.0, 0.0, 0.0)."""
# joint state
joint_pos: dict[str, float] = {".*": 0.0} joint_pos: dict[str, float] = {".*": 0.0}
"""Joint positions of the joints. Defaults to 0.0 for all joints.""" """Joint positions of the joints. Defaults to 0.0 for all joints."""
joint_vel: dict[str, float] = {".*": 0.0} joint_vel: dict[str, float] = {".*": 0.0}
...@@ -32,10 +36,17 @@ class ArticulationCfg(RigidObjectCfg): ...@@ -32,10 +36,17 @@ class ArticulationCfg(RigidObjectCfg):
# Initialize configurations. # Initialize configurations.
## ##
class_type: type = Articulation
init_state: InitialStateCfg = InitialStateCfg() init_state: InitialStateCfg = InitialStateCfg()
"""Initial state of the articulated object. Defaults to identity pose with zero velocity and zero joint state.""" """Initial state of the articulated object. Defaults to identity pose with zero velocity and zero joint state."""
soft_joint_pos_limit_factor: float = 1.0 soft_joint_pos_limit_factor: float = 1.0
"""Fraction specifying the range of DOF position limits (parsed from the asset) to use. """Fraction specifying the range of DOF position limits (parsed from the asset) to use. Defaults to 1.0.
Defaults to 1.0."""
The joint position limits are scaled by this factor to allow for a limited range of motion.
This is accessible in the articulation data through :attr:`ArticulationData.soft_joint_pos_limits` attribute.
"""
actuators: dict[str, ActuatorBaseCfg] = MISSING actuators: dict[str, ActuatorBaseCfg] = MISSING
"""Actuators for the robot with corresponding joint names.""" """Actuators for the robot with corresponding joint names."""
...@@ -120,6 +120,10 @@ class RigidObject(AssetBase): ...@@ -120,6 +120,10 @@ class RigidObject(AssetBase):
def update(self, dt: float): def update(self, dt: float):
self._data.update(dt) self._data.update(dt)
"""
Operations - Finders.
"""
def find_bodies(self, name_keys: str | Sequence[str], preserve_order: bool = False) -> tuple[list[int], list[str]]: def find_bodies(self, name_keys: str | Sequence[str], preserve_order: bool = False) -> tuple[list[int], list[str]]:
"""Find bodies in the articulation based on the name keys. """Find bodies in the articulation based on the name keys.
......
...@@ -33,24 +33,20 @@ class RigidObjectData: ...@@ -33,24 +33,20 @@ class RigidObjectData:
is older than the current simulation timestamp. The timestamp is updated whenever the data is updated. is older than the current simulation timestamp. The timestamp is updated whenever the data is updated.
""" """
_root_physx_view: physx.RigidBodyView
"""The root rigid body view of the object.
Note:
Internally, this is stored as a weak reference to avoid circular references between the asset class
and the data container. This is important to avoid memory leaks.
"""
def __init__(self, root_physx_view: physx.RigidBodyView, device: str): def __init__(self, root_physx_view: physx.RigidBodyView, device: str):
"""Initializes the rigid object data. """Initializes the rigid object data.
Args: Args:
root_physx_view: The root rigid body view of the object. root_physx_view: The root rigid body view.
device: The device used for processing. device: The device used for processing.
""" """
# Set the parameters # Set the parameters
self.device = device self.device = device
self._root_physx_view = weakref.proxy(root_physx_view) # weak reference to avoid circular references # Set the root rigid body view
# note: this is stored as a weak reference to avoid circular references between the asset class
# and the data container. This is important to avoid memory leaks.
self._root_physx_view: physx.RigidBodyView = weakref.proxy(root_physx_view)
# Set initial time stamp # Set initial time stamp
self._sim_timestamp = 0.0 self._sim_timestamp = 0.0
...@@ -76,6 +72,7 @@ class RigidObjectData: ...@@ -76,6 +72,7 @@ class RigidObjectData:
Args: Args:
dt: The time step for the update. This must be a positive value. dt: The time step for the update. This must be a positive value.
""" """
# update the simulation timestamp
self._sim_timestamp += dt self._sim_timestamp += dt
## ##
...@@ -97,7 +94,7 @@ class RigidObjectData: ...@@ -97,7 +94,7 @@ class RigidObjectData:
""" """
default_mass: torch.Tensor = None default_mass: torch.Tensor = None
""" Default mass provided by simulation. Shape is (num_instances, num_bodies).""" """Default mass read from the simulation. Shape is (num_instances, num_bodies)."""
## ##
# Properties. # Properties.
...@@ -133,8 +130,7 @@ class RigidObjectData: ...@@ -133,8 +130,7 @@ class RigidObjectData:
def body_acc_w(self): def body_acc_w(self):
"""Acceleration of all bodies. Shape is (num_instances, 1, 6). """Acceleration of all bodies. Shape is (num_instances, 1, 6).
This quantity is the acceleration of the rigid bodies' center of mass frame. The acceleration This quantity is the acceleration of the rigid bodies' center of mass frame.
is computed using finite differencing of the linear and angular velocities of the bodies.
""" """
if self._body_acc_w.timestamp < self._sim_timestamp: if self._body_acc_w.timestamp < self._sim_timestamp:
# note: we use finite differencing to compute acceleration # note: we use finite differencing to compute acceleration
...@@ -158,6 +154,10 @@ class RigidObjectData: ...@@ -158,6 +154,10 @@ class RigidObjectData:
forward_w = math_utils.quat_apply(self.root_quat_w, self.FORWARD_VEC_B) forward_w = math_utils.quat_apply(self.root_quat_w, self.FORWARD_VEC_B)
return torch.atan2(forward_w[:, 1], forward_w[:, 0]) return torch.atan2(forward_w[:, 1], forward_w[:, 0])
##
# Derived properties.
##
@property @property
def root_pos_w(self) -> torch.Tensor: def root_pos_w(self) -> torch.Tensor:
"""Root position in simulation world frame. Shape is (num_instances, 3). """Root position in simulation world frame. Shape is (num_instances, 3).
...@@ -255,3 +255,19 @@ class RigidObjectData: ...@@ -255,3 +255,19 @@ class RigidObjectData:
This quantity is the angular velocity of the rigid bodies' center of mass frame. This quantity is the angular velocity of the rigid bodies' center of mass frame.
""" """
return self.body_state_w[..., 10:13] return self.body_state_w[..., 10:13]
@property
def body_lin_acc_w(self) -> torch.Tensor:
"""Linear acceleration of all bodies in simulation world frame. Shape is (num_instances, num_bodies, 3).
This quantity is the linear acceleration of the rigid bodies' center of mass frame.
"""
return self.body_acc_w[..., 0:3]
@property
def body_ang_acc_w(self) -> torch.Tensor:
"""Angular acceleration of all bodies in simulation world frame. Shape is (num_instances, num_bodies, 3).
This quantity is the angular acceleration of the rigid bodies' center of mass frame.
"""
return self.body_acc_w[..., 3:6]
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