Skip to content

Commit 3d836ab

Browse files
Reverts the setting of joint velocity limits for implicit actuators (#1873)
# Description The previous fix in #1654 was checking if `effort_limits_sim` is None instead of checking `cfg.effort_limits_sim` for explicit actuators. This did NOT work as effort limits sim is a tensor that gets assigned the value on initialization. The new fix now adds an implicit/explicit model attribute to the actuator model to ensure the right defaults are getting set. It moves all the implicit actuator warning code to its class to keep the articulation class cleaner. We also revert the behavior of setting velocity limits for implicit actuators to the state before #1509. Before that change, the parameter `velocity_limit` was set in the configurations but not getting passed through. The MR #1509 allowed these values to be set which caused many of the assets to not train anymore or behave differently between IsaacLab versions. We now revert this behavior with a warning. If users want to set the limits, they should use the `effort_limit_sim` and `velocity_limit_sim` quantities. Fixes #1837 ## Type of change - Bug fix (non-breaking change which fixes an issue) ## Screenshot The training of Allegro hand environment: * Green: The current main at 6a415df * Black: This MR * Orange: Commenting out the setting of `write_joint_velocity_to_sim` which was introduced in #1509. ![image](https://github.com/user-attachments/assets/8ca1ded2-7d8f-4123-aea8-9082559885d7) ## 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 - [ ] 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 --------- Signed-off-by: Mayank Mittal <[email protected]> Co-authored-by: James Tigue <[email protected]>
1 parent 46594e0 commit 3d836ab

File tree

11 files changed

+673
-210
lines changed

11 files changed

+673
-210
lines changed

docs/source/refs/release_notes.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,7 @@ Breaking Changes
8181
* Restructures extension folders and removes old imitation learning scripts by @kellyguo11
8282
* Renames default conda and venv Python environment from ``isaaclab`` to ``env_isaaclab`` by @Toni-SM
8383

84+
8485
Migration Guide
8586
---------------
8687

source/isaaclab/config/extension.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
[package]
22

33
# Note: Semantic Versioning is used: https://semver.org/
4-
version = "0.34.3"
4+
version = "0.34.4"
55

66
# Description
77
title = "Isaac Lab framework for Robot Learning"

source/isaaclab/docs/CHANGELOG.rst

Lines changed: 32 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,35 @@
11
Changelog
22
---------
33

4+
0.34.4 (2025-03-01)
5+
~~~~~~~~~~~~~~~~~~~
6+
7+
Added
8+
^^^^^
9+
10+
* Added a new attribute :attr:`is_implicit_model` to the :class:`isaaclab.actuators.ActuatorBase` class to
11+
indicate if the actuator model is implicit or explicit. This helps checking that the correct model type
12+
is being used when initializing the actuator models.
13+
14+
Fixed
15+
^^^^^
16+
17+
* Added copy of configurations to :class:`~isaaclab.assets.AssetBase` and :class:`~isaaclab.sensors.SensorBase`
18+
to prevent modifications of the configurations from leaking outside of the classes.
19+
* Fixed the case where setting velocity/effort limits for the simulation in the
20+
:class:`~isaaclab.actuators.ActuatorBaseCfg` class was not being used to update the actuator-specific
21+
velocity/effort limits.
22+
23+
Changed
24+
^^^^^^^
25+
26+
* Moved warnings and checks for implicit actuator models to the :class:`~isaaclab.actuators.ImplicitActuator` class.
27+
* Reverted to IsaacLab v1.3 behavior where :attr:`isaaclab.actuators.ImplicitActuatorCfg.velocity_limit`
28+
attribute was not used for setting the velocity limits in the simulation. This makes it possible to deploy
29+
policies from previous release without any changes. If users want to set the velocity limits for the simulation,
30+
they should use the :attr:`isaaclab.actuators.ImplicitActuatorCfg.velocity_limit_sim` attribute instead.
31+
32+
433
0.34.3 (2025-02-28)
534
~~~~~~~~~~~~~~~~~~~
635

@@ -13,7 +42,7 @@ Added
1342

1443

1544
0.34.2 (2025-02-21)
16-
~~~~~~~~~~~~~~~~~~~~
45+
~~~~~~~~~~~~~~~~~~~
1746

1847
Fixed
1948
^^^^^
@@ -38,8 +67,8 @@ Fixed
3867
Fixed
3968
^^^^^
4069

41-
* Adds attributes velocity_limits_sim and effort_limits_sim to :class:`isaaclab.actuators.AssetBaseCfg` to separate
42-
solver limits from actuator limits.
70+
* Added attributes :attr:`velocity_limits_sim` and :attr:`effort_limits_sim` to the
71+
:class:`isaaclab.actuators.ActuatorBaseCfg` class to separate solver limits from actuator limits.
4372

4473

4574
0.33.17 (2025-02-13)

source/isaaclab/isaaclab/actuators/actuator_base.py

Lines changed: 61 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
import torch
99
from abc import ABC, abstractmethod
1010
from collections.abc import Sequence
11-
from typing import TYPE_CHECKING
11+
from typing import TYPE_CHECKING, ClassVar
1212

1313
import isaaclab.utils.string as string_utils
1414
from isaaclab.utils.types import ArticulationActions
@@ -36,28 +36,63 @@ class ActuatorBase(ABC):
3636
To see how the class is used, check the :class:`isaaclab.assets.Articulation` class.
3737
"""
3838

39+
is_implicit_model: ClassVar[bool] = False
40+
"""Flag indicating if the actuator is an implicit or explicit actuator model.
41+
42+
If a class inherits from :class:`ImplicitActuator`, then this flag should be set to :obj:`True`.
43+
"""
44+
3945
computed_effort: torch.Tensor
4046
"""The computed effort for the actuator group. Shape is (num_envs, num_joints)."""
47+
4148
applied_effort: torch.Tensor
42-
"""The applied effort for the actuator group. Shape is (num_envs, num_joints)."""
49+
"""The applied effort for the actuator group. Shape is (num_envs, num_joints).
50+
51+
This is the effort obtained after clipping the :attr:`computed_effort` based on the
52+
actuator characteristics.
53+
"""
54+
4355
effort_limit: torch.Tensor
44-
"""The effort limit for the actuator group. Shape is (num_envs, num_joints)."""
56+
"""The effort limit for the actuator group. Shape is (num_envs, num_joints).
57+
58+
For implicit actuators, the :attr:`effort_limit` and :attr:`effort_limit_sim` are the same.
59+
"""
60+
61+
effort_limit_sim: torch.Tensor
62+
"""The effort limit for the actuator group in the simulation. Shape is (num_envs, num_joints).
63+
64+
For implicit actuators, the :attr:`effort_limit` and :attr:`effort_limit_sim` are the same.
65+
"""
66+
4567
velocity_limit: torch.Tensor
46-
"""The velocity limit for the actuator group. Shape is (num_envs, num_joints)."""
68+
"""The velocity limit for the actuator group. Shape is (num_envs, num_joints).
69+
70+
For implicit actuators, the :attr:`velocity_limit` and :attr:`velocity_limit_sim` are the same.
71+
"""
72+
73+
velocity_limit_sim: torch.Tensor
74+
"""The velocity limit for the actuator group in the simulation. Shape is (num_envs, num_joints).
75+
76+
For implicit actuators, the :attr:`velocity_limit` and :attr:`velocity_limit_sim` are the same.
77+
"""
78+
4779
stiffness: torch.Tensor
4880
"""The stiffness (P gain) of the PD controller. Shape is (num_envs, num_joints)."""
81+
4982
damping: torch.Tensor
5083
"""The damping (D gain) of the PD controller. Shape is (num_envs, num_joints)."""
84+
5185
armature: torch.Tensor
5286
"""The armature of the actuator joints. Shape is (num_envs, num_joints)."""
87+
5388
friction: torch.Tensor
5489
"""The joint friction of the actuator joints. Shape is (num_envs, num_joints)."""
5590

5691
def __init__(
5792
self,
5893
cfg: ActuatorBaseCfg,
5994
joint_names: list[str],
60-
joint_ids: slice | Sequence[int],
95+
joint_ids: slice | torch.Tensor,
6196
num_envs: int,
6297
device: str,
6398
stiffness: torch.Tensor | float = 0.0,
@@ -69,9 +104,12 @@ def __init__(
69104
):
70105
"""Initialize the actuator.
71106
72-
Note:
73-
The actuator parameters are parsed from the configuration and stored as buffers. If the parameters
74-
are not specified in the configuration, then the default values provided in the arguments are used.
107+
The actuator parameters are parsed from the configuration and stored as buffers. If the parameters
108+
are not specified in the configuration, then their values provided in the constructor are used.
109+
110+
.. note::
111+
The values in the constructor are typically obtained through the USD schemas corresponding
112+
to the joints in the actuator model.
75113
76114
Args:
77115
cfg: The configuration of the actuator model.
@@ -100,18 +138,24 @@ def __init__(
100138
self._joint_names = joint_names
101139
self._joint_indices = joint_ids
102140

141+
# For explicit models, we do not want to enforce the effort limit through the solver
142+
# (unless it is explicitly set)
143+
if not ActuatorBase.is_implicit_model and self.cfg.effort_limit_sim is None:
144+
self.cfg.effort_limit_sim = 1.0e9
145+
103146
# parse joint stiffness and damping
104147
self.stiffness = self._parse_joint_parameter(self.cfg.stiffness, stiffness)
105148
self.damping = self._parse_joint_parameter(self.cfg.damping, damping)
106149
# parse joint armature and friction
107150
self.armature = self._parse_joint_parameter(self.cfg.armature, armature)
108151
self.friction = self._parse_joint_parameter(self.cfg.friction, friction)
109152
# parse joint limits
110-
# note: for velocity limits, we don't have USD parameter, so default is infinity
111-
self.effort_limit = self._parse_joint_parameter(self.cfg.effort_limit, effort_limit)
112-
self.velocity_limit = self._parse_joint_parameter(self.cfg.velocity_limit, velocity_limit)
113-
self.effort_limit_sim = self._parse_joint_parameter(self.cfg.effort_limit_sim, effort_limit)
153+
# -- velocity
114154
self.velocity_limit_sim = self._parse_joint_parameter(self.cfg.velocity_limit_sim, velocity_limit)
155+
self.velocity_limit = self._parse_joint_parameter(self.cfg.velocity_limit, self.velocity_limit_sim)
156+
# -- effort
157+
self.effort_limit_sim = self._parse_joint_parameter(self.cfg.effort_limit_sim, effort_limit)
158+
self.effort_limit = self._parse_joint_parameter(self.cfg.effort_limit, self.effort_limit_sim)
115159

116160
# create commands buffers for allocation
117161
self.computed_effort = torch.zeros(self._num_envs, self.num_joints, device=self._device)
@@ -123,8 +167,12 @@ def __str__(self) -> str:
123167
joint_indices = self.joint_indices
124168
if joint_indices == slice(None):
125169
joint_indices = list(range(self.num_joints))
170+
# resolve model type (implicit or explicit)
171+
model_type = "implicit" if self.is_implicit_model else "explicit"
172+
126173
return (
127174
f"<class {self.__class__.__name__}> object:\n"
175+
f"\tModel type : {model_type}\n"
128176
f"\tNumber of joints : {self.num_joints}\n"
129177
f"\tJoint names expression: {self.cfg.joint_names_expr}\n"
130178
f"\tJoint names : {self.joint_names}\n"
@@ -146,7 +194,7 @@ def joint_names(self) -> list[str]:
146194
return self._joint_names
147195

148196
@property
149-
def joint_indices(self) -> slice | Sequence[int]:
197+
def joint_indices(self) -> slice | torch.Tensor:
150198
"""Articulation's joint indices that are part of the group.
151199
152200
Note:

source/isaaclab/isaaclab/actuators/actuator_cfg.py

Lines changed: 46 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -36,42 +36,73 @@ class ActuatorBaseCfg:
3636
This limit is used to clip the computed torque sent to the simulation. If None, the limit is set to the value
3737
specified in the USD joint prim.
3838
39+
.. attention::
40+
41+
The :attr:`effort_limit_sim` attribute should be used to set the effort limit for the simulation physics
42+
solver.
43+
44+
The :attr:`effort_limit` attribute is used for clipping the effort output of the actuator model *only*
45+
in the case of explicit actuators, such as the :class:`~isaaclab.actuators.IdealPDActuator`.
46+
3947
.. note::
4048
41-
For ImplicitActuators this value will be collapsed with effort_limit_sim due to duplicating functionality. If
42-
both are set the effort_limit_sim will be used priority.
49+
For implicit actuators, the attributes :attr:`effort_limit` and :attr:`effort_limit_sim` are equivalent.
50+
However, we suggest using the :attr:`effort_limit_sim` attribute because it is more intuitive.
51+
4352
"""
4453

4554
velocity_limit: dict[str, float] | float | None = None
4655
"""Velocity limit of the joints in the group. Defaults to None.
4756
4857
This limit is used by the actuator model. If None, the limit is set to the value specified in the USD joint prim.
4958
50-
.. note::
59+
.. attention::
60+
61+
The :attr:`velocity_limit_sim` attribute should be used to set the velocity limit for the simulation physics
62+
solver.
5163
52-
velocity_limit is not used in ActuatorBaseCfg but is provided for inherited version like
53-
:class:`isaaclab.actuators.DCMotor`.
64+
The :attr:`velocity_limit` attribute is used for clipping the effort output of the actuator model *only*
65+
in the case of explicit actuators, such as the :class:`~isaaclab.actuators.IdealPDActuator`.
5466
5567
.. note::
5668
57-
For ImplicitActuators this value will be collapsed with velocity_limit_sim due to duplicating functionality. If
58-
both are set the effort_limit_sim will be used priority.
69+
For implicit actuators, the attribute :attr:`velocity_limit` is not used. This is to stay backwards compatible
70+
with previous versions of the Isaac Lab, where this parameter was unused since PhysX did not support setting
71+
the velocity limit for the joints using the Tensor API.
5972
"""
6073

6174
effort_limit_sim: dict[str, float] | float | None = None
62-
"""Force/Torque limit of the joints in the group that will be propagated to the simulation physics solver. Defaults to None.
75+
"""Effort limit of the joints in the group applied to the simulation physics solver. Defaults to None.
76+
77+
The effort limit is used to constrain the computed joint efforts in the physics engine. If the computed effort
78+
exceeds this limit, the physics engine will clip the effort to this value.
79+
80+
Since explicit actuators (e.g. DC motor), compute and clip the effort in the actuator model, this limit is by
81+
default set to a large value to prevent the physics engine from any additional clipping. However, at times,
82+
it may be necessary to set this limit to a smaller value as a safety measure.
83+
84+
If None, the limit is resolved based on the type of actuator model:
85+
86+
* For implicit actuators, the limit is set to the value specified in the USD joint prim.
87+
* For explicit actuators, the limit is set to 1.0e9.
6388
64-
If None, the limit is set to the value specified in the USD joint prim for ImplicitActuators or 1.0e9 for explicit
65-
actuators (e.g. IdealPDActuator). The simulation effort limits prevent computed torques from exceeding the specified
66-
limit. If effort limits are too tight issues with solver convergence may occur. It is suggested to keep these value large.
6789
"""
6890

6991
velocity_limit_sim: dict[str, float] | float | None = None
70-
"""Velocity limit of the joints in the group that will be propagated to the simulation physics solver. Defaults to None.
92+
"""Velocity limit of the joints in the group applied to the simulation physics solver. Defaults to None.
93+
94+
The velocity limit is used to constrain the joint velocities in the physics engine.
95+
The joint will only be able to reach this velocity if the :attr:`effort_limit_sim` is sufficiently large.
96+
If the joint is moving faster than this velocity, the physics engine will actually try to brake the joint
97+
to reach this velocity.
98+
99+
If None, the limit is set to the value specified in the USD joint prim for both implicit and explicit actuators.
100+
101+
.. tip::
102+
If the velocity limit is too tight, the physics engine may have trouble converging to a solution.
103+
In such cases, we recommend either keeping this value sufficiently large or tuning the stiffness and damping
104+
parameters of the joint to ensure the limits are not violated.
71105
72-
If None, the limit is set to the value specified in the USD joint prim. Resulting solver solutions will constrain
73-
velocities by these limits. If velocity_limit_sim is too tight issues with solver convergence may occur. It is
74-
suggested to keep these value large.
75106
"""
76107

77108
stiffness: dict[str, float] | float | None = MISSING

source/isaaclab/isaaclab/actuators/actuator_pd.py

Lines changed: 57 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@
99
from collections.abc import Sequence
1010
from typing import TYPE_CHECKING
1111

12+
import omni.log
13+
1214
from isaaclab.utils import DelayBuffer, LinearInterpolation
1315
from isaaclab.utils.types import ArticulationActions
1416

@@ -37,10 +39,10 @@ class ImplicitActuator(ActuatorBase):
3739
generally more accurate than the explicit PD control law used in :class:`IdealPDActuator` when the simulation
3840
time-step is large.
3941
40-
.. note::
41-
42-
The articulation class sets the stiffness and damping parameters from the configuration into the simulation.
43-
Thus, the parameters are not used in this class.
42+
The articulation class sets the stiffness and damping parameters from the implicit actuator configuration
43+
into the simulation. Thus, the class does not perform its own computations on the joint action that
44+
needs to be applied to the simulation. However, it computes the approximate torques for the actuated joint
45+
since PhysX does not expose this quantity explicitly.
4446
4547
.. caution::
4648
@@ -51,6 +53,57 @@ class ImplicitActuator(ActuatorBase):
5153
cfg: ImplicitActuatorCfg
5254
"""The configuration for the actuator model."""
5355

56+
def __init__(self, cfg: ImplicitActuatorCfg, *args, **kwargs):
57+
# effort limits
58+
if cfg.effort_limit_sim is None and cfg.effort_limit is not None:
59+
# throw a warning that we have a replacement for the deprecated parameter
60+
omni.log.warn(
61+
"The <ImplicitActuatorCfg> object has a value for 'effort_limit'."
62+
" This parameter will be removed in the future."
63+
" To set the effort limit, please use 'effort_limit_sim' instead."
64+
)
65+
cfg.effort_limit_sim = cfg.effort_limit
66+
elif cfg.effort_limit_sim is not None and cfg.effort_limit is None:
67+
# TODO: Eventually we want to get rid of 'effort_limit' for implicit actuators.
68+
# We should do this once all parameters have an "_sim" suffix.
69+
cfg.effort_limit = cfg.effort_limit_sim
70+
elif cfg.effort_limit_sim is not None and cfg.effort_limit is not None:
71+
if cfg.effort_limit_sim != cfg.effort_limit:
72+
raise ValueError(
73+
"The <ImplicitActuatorCfg> object has set both 'effort_limit_sim' and 'effort_limit'"
74+
f" and they have different values {cfg.effort_limit_sim} != {cfg.effort_limit}."
75+
" Please only set 'effort_limit_sim' for implicit actuators."
76+
)
77+
78+
# velocity limits
79+
if cfg.velocity_limit_sim is None and cfg.velocity_limit is not None:
80+
# throw a warning that previously this was not set
81+
# it leads to different simulation behavior so we want to remain backwards compatible
82+
omni.log.warn(
83+
"The <ImplicitActuatorCfg> object has a value for 'velocity_limit'."
84+
" Previously, although this value was specified, it was not getting used by implicit"
85+
" actuators. Since this parameter affects the simulation behavior, we continue to not"
86+
" use it. This parameter will be removed in the future."
87+
" To set the velocity limit, please use 'velocity_limit_sim' instead."
88+
)
89+
cfg.velocity_limit = None
90+
elif cfg.velocity_limit_sim is not None and cfg.velocity_limit is None:
91+
# TODO: Eventually we want to get rid of 'velocity_limit' for implicit actuators.
92+
# We should do this once all parameters have an "_sim" suffix.
93+
cfg.velocity_limit = cfg.velocity_limit_sim
94+
elif cfg.velocity_limit_sim is not None and cfg.velocity_limit is not None:
95+
if cfg.velocity_limit_sim != cfg.velocity_limit:
96+
raise ValueError(
97+
"The <ImplicitActuatorCfg> object has set both 'velocity_limit_sim' and 'velocity_limit'"
98+
f" and they have different values {cfg.velocity_limit_sim} != {cfg.velocity_limit}."
99+
" Please only set 'velocity_limit_sim' for implicit actuators."
100+
)
101+
102+
# set implicit actuator model flag
103+
ImplicitActuator.is_implicit_model = True
104+
# call the base class
105+
super().__init__(cfg, *args, **kwargs)
106+
54107
"""
55108
Operations.
56109
"""

0 commit comments

Comments
 (0)