Skip to content

Commit a355128

Browse files
committed
Implement randomize_actuator_stiffness_and_dampning for explicit actuator models. #1000
Set default stiffness, damping for explicit actuators #1006 fixes randomize_joint_parameters shape mismatch #1011
1 parent 9cc298e commit a355128

File tree

4 files changed

+63
-63
lines changed

4 files changed

+63
-63
lines changed

CONTRIBUTORS.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ Guidelines for modifications:
7474
* Zhengyu Zhang
7575
* Ziqi Fan
7676
* Qian Wan
77-
* Wei Yang
77+
* Ryley McCarroll
7878

7979
## Acknowledgements
8080

source/extensions/omni.isaac.lab/omni/isaac/lab/actuators/actuator_base.py

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -207,6 +207,7 @@ def _parse_joint_parameter(
207207
TypeError: If the parameter value is not of the expected type.
208208
TypeError: If the default value is not of the expected type.
209209
ValueError: If the parameter value is None and no default value is provided.
210+
ValueError: If the default value tensor is the wrong shape.
210211
"""
211212
# create parameter buffer
212213
param = torch.zeros(self._num_envs, self.num_joints, device=self._device)
@@ -231,7 +232,14 @@ def _parse_joint_parameter(
231232
param[:] = float(default_value)
232233
elif isinstance(default_value, torch.Tensor):
233234
# if tensor, then use the same tensor for all joints
234-
param[:] = default_value.float()
235+
if default_value.shape == (self._num_envs, self.num_joints):
236+
param = default_value.float()
237+
else:
238+
raise ValueError(
239+
"Invalid default value tensor shape.\n"
240+
f"Got: {default_value.shape}\n"
241+
f"Expected: {(self._num_envs, self.num_joints)}"
242+
)
235243
else:
236244
raise TypeError(
237245
f"Invalid type for default value: {type(default_value)} for "

source/extensions/omni.isaac.lab/omni/isaac/lab/assets/articulation/articulation.py

Lines changed: 13 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1105,12 +1105,10 @@ def _process_actuators_cfg(self):
11051105
self._has_implicit_actuators = False
11061106

11071107
# cache the values coming from the usd
1108-
usd_stiffness = self.root_physx_view.get_dof_stiffnesses().clone()
1109-
usd_damping = self.root_physx_view.get_dof_dampings().clone()
1110-
usd_armature = self.root_physx_view.get_dof_armatures().clone()
1111-
usd_friction = self.root_physx_view.get_dof_friction_coefficients().clone()
1112-
usd_effort_limit = self.root_physx_view.get_dof_max_forces().clone()
1113-
usd_velocity_limit = self.root_physx_view.get_dof_max_velocities().clone()
1108+
self._data.default_joint_stiffness = self.root_physx_view.get_dof_stiffnesses().to(self.device).clone()
1109+
self._data.default_joint_damping = self.root_physx_view.get_dof_dampings().to(self.device).clone()
1110+
self._data.default_joint_armature = self.root_physx_view.get_dof_armatures().to(self.device).clone()
1111+
self._data.default_joint_friction = self.root_physx_view.get_dof_friction_coefficients().to(self.device).clone()
11141112

11151113
# iterate over all actuator configurations
11161114
for actuator_name, actuator_cfg in self.cfg.actuators.items():
@@ -1134,12 +1132,12 @@ def _process_actuators_cfg(self):
11341132
),
11351133
num_envs=self.num_instances,
11361134
device=self.device,
1137-
stiffness=usd_stiffness[:, joint_ids],
1138-
damping=usd_damping[:, joint_ids],
1139-
armature=usd_armature[:, joint_ids],
1140-
friction=usd_friction[:, joint_ids],
1141-
effort_limit=usd_effort_limit[:, joint_ids],
1142-
velocity_limit=usd_velocity_limit[:, joint_ids],
1135+
stiffness=self._data.default_joint_stiffness[:, joint_ids],
1136+
damping=self._data.default_joint_damping[:, joint_ids],
1137+
armature=self._data.default_joint_armature[:, joint_ids],
1138+
friction=self._data.default_joint_friction[:, joint_ids],
1139+
effort_limit=self.root_physx_view.get_dof_max_forces().to(self.device).clone()[:, joint_ids],
1140+
velocity_limit=self.root_physx_view.get_dof_max_velocities().to(self.device).clone()[:, joint_ids],
11431141
)
11441142
# log information on actuator groups
11451143
omni.log.info(
@@ -1165,14 +1163,9 @@ def _process_actuators_cfg(self):
11651163
self.write_joint_effort_limit_to_sim(1.0e9, joint_ids=actuator.joint_indices)
11661164
self.write_joint_armature_to_sim(actuator.armature, joint_ids=actuator.joint_indices)
11671165
self.write_joint_friction_to_sim(actuator.friction, joint_ids=actuator.joint_indices)
1168-
1169-
# set the default joint parameters based on the changes from the actuators
1170-
self._data.default_joint_stiffness = self.root_physx_view.get_dof_stiffnesses().to(device=self.device).clone()
1171-
self._data.default_joint_damping = self.root_physx_view.get_dof_dampings().to(device=self.device).clone()
1172-
self._data.default_joint_armature = self.root_physx_view.get_dof_armatures().to(device=self.device).clone()
1173-
self._data.default_joint_friction = (
1174-
self.root_physx_view.get_dof_friction_coefficients().to(device=self.device).clone()
1175-
)
1166+
# Store the actual default stiffness and damping values for explicit actuators (not written the sim)
1167+
self._data.default_joint_stiffness[:, actuator.joint_indices] = actuator.stiffness
1168+
self._data.default_joint_damping[:, actuator.joint_indices] = actuator.damping
11761169

11771170
# perform some sanity checks to ensure actuators are prepared correctly
11781171
total_act_joints = sum(actuator.num_joints for actuator in self.actuators.values())

source/extensions/omni.isaac.lab/omni/isaac/lab/envs/mdp/events.py

Lines changed: 40 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -300,54 +300,53 @@ def randomize_actuator_gains(
300300
.. tip::
301301
For implicit actuators, this function uses CPU tensors to assign the actuator gains into the simulation.
302302
In such cases, it is recommended to use this function only during the initialization of the environment.
303-
304-
Raises:
305-
NotImplementedError: If the joint indices are in explicit motor mode. This operation is currently
306-
not supported for explicit actuator models.
307303
"""
308-
# extract the used quantities (to enable type-hinting)
304+
# Extract the used quantities (to enable type-hinting)
309305
asset: Articulation = env.scene[asset_cfg.name]
310306

311-
# resolve environment ids
307+
# Resolve environment ids
312308
if env_ids is None:
313309
env_ids = torch.arange(env.scene.num_envs, device=asset.device)
314310

315-
# resolve joint indices
316-
if asset_cfg.joint_ids == slice(None):
317-
joint_ids_list = range(asset.num_joints)
318-
joint_ids = slice(None) # for optimization purposes
319-
else:
320-
joint_ids_list = asset_cfg.joint_ids
321-
joint_ids = torch.tensor(asset_cfg.joint_ids, dtype=torch.int, device=asset.device)
311+
joint_ids_list = list(range(asset.num_joints)) if isinstance(asset_cfg.joint_ids, slice) else asset_cfg.joint_ids
322312

323-
# check if none of the joint indices are in explicit motor mode
324-
for joint_index in joint_ids_list:
325-
for act_name, actuator in asset.actuators.items():
326-
# if joint indices are a slice (i.e., all joints are captured) or the joint index is in the actuator
327-
if actuator.joint_indices == slice(None) or joint_index in actuator.joint_indices:
328-
if not isinstance(actuator, ImplicitActuator):
329-
raise NotImplementedError(
330-
"Event term 'randomize_actuator_stiffness_and_damping' is performed on asset"
331-
f" '{asset_cfg.name}' on the joint '{asset.joint_names[joint_index]}' ('{joint_index}') which"
332-
f" uses an explicit actuator model '{act_name}<{actuator.__class__.__name__}>'. This operation"
333-
" is currently not supported for explicit actuator models."
334-
)
313+
def randomize(data: torch.Tensor, params: tuple[float, float]) -> torch.Tensor:
314+
return _randomize_prop_by_op(
315+
data, params, env_ids, target_joint_indices, operation=operation, distribution=distribution
316+
)
335317

336-
# sample joint properties from the given ranges and set into the physics simulation
337-
# -- stiffness
338-
if stiffness_distribution_params is not None:
339-
stiffness = asset.data.default_joint_stiffness.to(asset.device).clone()
340-
stiffness = _randomize_prop_by_op(
341-
stiffness, stiffness_distribution_params, env_ids, joint_ids, operation=operation, distribution=distribution
342-
)[env_ids][:, joint_ids]
343-
asset.write_joint_stiffness_to_sim(stiffness, joint_ids=joint_ids, env_ids=env_ids)
344-
# -- damping
345-
if damping_distribution_params is not None:
346-
damping = asset.data.default_joint_damping.to(asset.device).clone()
347-
damping = _randomize_prop_by_op(
348-
damping, damping_distribution_params, env_ids, joint_ids, operation=operation, distribution=distribution
349-
)[env_ids][:, joint_ids]
350-
asset.write_joint_damping_to_sim(damping, joint_ids=joint_ids, env_ids=env_ids)
318+
# Loop through actuators and randomize gains
319+
for actuator in asset.actuators.values():
320+
# Resolve joint indices for each actuator
321+
# Only target the joints specified by the asset_cfg.joint_ids (joint_ids_list)
322+
if isinstance(actuator.joint_indices, slice): # All joints of the articulation are this actuator type
323+
target_joint_indices = torch.tensor(joint_ids_list, dtype=torch.int, device=asset.device)
324+
else:
325+
target_joint_indices = torch.tensor(
326+
list(set(actuator.joint_indices).intersection(joint_ids_list)), dtype=torch.int, device=asset.device
327+
)
328+
if not target_joint_indices.nbytes: # Skip when there are no joints
329+
continue
330+
331+
all_envs = torch.arange(env.scene.num_envs, device=asset.device)
332+
# Randomize stiffness
333+
if stiffness_distribution_params is not None:
334+
stiffness = asset.data.default_joint_stiffness.to(asset.device).clone()
335+
randomize(stiffness, stiffness_distribution_params)
336+
actuator.stiffness = stiffness[all_envs[:, None], actuator.joint_indices]
337+
if isinstance(actuator, ImplicitActuator):
338+
asset.write_joint_stiffness_to_sim(
339+
stiffness[env_ids][:, target_joint_indices], joint_ids=target_joint_indices, env_ids=env_ids
340+
)
341+
# Randomize damping
342+
if damping_distribution_params is not None:
343+
damping = asset.data.default_joint_damping.to(asset.device).clone()
344+
randomize(damping, damping_distribution_params)
345+
actuator.damping = damping[all_envs[:, None], actuator.joint_indices]
346+
if isinstance(actuator, ImplicitActuator):
347+
asset.write_joint_damping_to_sim(
348+
damping[env_ids][:, target_joint_indices], joint_ids=target_joint_indices, env_ids=env_ids
349+
)
351350

352351

353352
def randomize_joint_parameters(
@@ -383,7 +382,7 @@ def randomize_joint_parameters(
383382

384383
# resolve joint indices
385384
if asset_cfg.joint_ids == slice(None):
386-
joint_ids = slice(None) # for optimization purposes
385+
joint_ids = torch.arange(asset.num_joints, dtype=torch.int, device=asset.device)
387386
else:
388387
joint_ids = torch.tensor(asset_cfg.joint_ids, dtype=torch.int, device=asset.device)
389388

0 commit comments

Comments
 (0)