[Bug Report] Invalid behavior of joints reset functions
Describe the bug
The mdp.reset_joints_by_offset and mdp.reset_joints_by_scale functions cannot target specific joints and cannot be combined.
Steps to reproduce
When defining multiple reset events (as done in the Isaac-Cartpole-v0 task for example):
@configclass
class EventCfg:
"""Configuration for events."""
# reset
reset_cart_position = EventTerm(
func=mdp.reset_joints_by_offset,
mode="reset",
params={
"asset_cfg": SceneEntityCfg("robot", joint_names=["slider_to_cart"]),
"position_range": (-1.0, 1.0),
"velocity_range": (-0.5, 0.5),
},
)
reset_pole_position = EventTerm(
func=mdp.reset_joints_by_offset,
mode="reset",
params={
"asset_cfg": SceneEntityCfg("robot", joint_names=["cart_to_pole"]),
"position_range": (-0.25 * math.pi, 0.25 * math.pi),
"velocity_range": (-0.25 * math.pi, 0.25 * math.pi),
},
)
each EventTerm overrides previous ones and applies to all joints, unless I am missing something.
I think this happens because the starting point is always the default joints position / velocity and no filter is done, ignoring the joint_names attribute of the SceneEntityCfg parameter:
def reset_joints_by_scale(...):
...
# get default joint state
joint_pos = asset.data.default_joint_pos[env_ids].clone()
joint_vel = asset.data.default_joint_vel[env_ids].clone()
# bias these values randomly
joint_pos += math_utils.sample_uniform(*position_range, joint_pos.shape, joint_pos.device)
joint_vel += math_utils.sample_uniform(*velocity_range, joint_vel.shape, joint_vel.device)
...
# set into the physics simulation
asset.write_joint_state_to_sim(joint_pos, joint_vel, env_ids=env_ids)
To overcome this problem I defined a reset_joints_to_default function
def reset_joints_to_default(
env: ManagerBasedEnv,
env_ids: torch.Tensor,
asset_cfg: SceneEntityCfg = SceneEntityCfg("robot"),
):
"""Reset the robot joints to default position and velocity"""
# extract the used quantities (to enable type-hinting)
asset: Articulation = env.scene[asset_cfg.name]
# get default joint state
joint_pos = asset.data.default_joint_pos[env_ids].clone()
joint_vel = asset.data.default_joint_vel[env_ids].clone()
# set into the physics simulation
asset.write_joint_state_to_sim(joint_pos, joint_vel, env_ids=env_ids)
that I use in the first EventTerm and then use a modified reset_joints_by_offset in subsequent EventTerm.
def reset_joints_by_offset(...):
...
# get current joint state
joint_pos_all = asset.data.joint_pos[env_ids]
joint_vel_all = asset.data.joint_vel[env_ids]
# fetch targeted joints
joint_pos = joint_pos_all[:, asset_cfg.joint_ids]
joint_vel = joint_vel_all[:, asset_cfg.joint_ids]
# bias these values randomly
joint_pos += math_utils.sample_uniform(*position_range, joint_pos.shape, joint_pos.device)
joint_vel += math_utils.sample_uniform(*velocity_range, joint_vel.shape, joint_vel.device)
# update joint state
joint_pos_all[:, asset_cfg.joint_ids] = joint_pos
joint_vel_all[:, asset_cfg.joint_ids] = joint_vel
...
# set into the physics simulation
asset.write_joint_state_to_sim(joint_pos_all, joint_vel_all, env_ids=env_ids)
System Info
Additional context
If you think the solution I currently use is valid, I can create a pull request with this implementation (it seems to be working well on my side).
Checklist
- [x] I have checked that there is no similar issue in the repo (required)
- [x] I have checked that the issue is not in running Isaac Sim itself and is related to the repo
Acceptance Criteria
Add the criteria for which this task is considered done. If not known at issue creation time, you can add this once the issue is assigned.
- [ ] It is possible to target specific joints in the
reset_joints_by_offsetorreset_joints_by_scalefunctions. - [ ] It is possible to combine multiple
EventTermobjects that use thereset_joints_by_offsetorreset_joints_by_scalefunctions.
Thanks for reporting this! Would be great if you could create a PR for the fix!
Yes sure, I will create it soon.