aligned to go2_rl_gym.
This commit is contained in:
@@ -60,14 +60,7 @@ python scripts/reinforcement_learning/rsl_rl/play.py --task=RobotLab-Go2-v0
|
|||||||
## Differences with `go2_rl_gym`
|
## Differences with `go2_rl_gym`
|
||||||
|
|
||||||
- Terrain's composition are different(see code).
|
- Terrain's composition are different(see code).
|
||||||
|
- tracking reward are different (fixed sigma vs. dynamic sigma).
|
||||||
- Rewards
|
|
||||||
- feet_regulation are lacked.
|
|
||||||
- dof_pos_limits are lacked.
|
|
||||||
- tracking reward are different (fixed sigma vs. dynamic sigma).
|
|
||||||
|
|
||||||
- Terminations:
|
|
||||||
- contact termination are lacked.
|
|
||||||
|
|
||||||
## Acknowledgements
|
## Acknowledgements
|
||||||
This repository would not exist without the following open-source projects:
|
This repository would not exist without the following open-source projects:
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ UNITREE_GO2_CFG = ArticulationCfg(
|
|||||||
spawn=sim_utils.UrdfFileCfg(
|
spawn=sim_utils.UrdfFileCfg(
|
||||||
fix_base=False,
|
fix_base=False,
|
||||||
merge_fixed_joints=True,
|
merge_fixed_joints=True,
|
||||||
replace_cylinders_with_capsules=False,
|
replace_cylinders_with_capsules=True,
|
||||||
asset_path=f"{ISAACLAB_ASSETS_DATA_DIR}/Robots/unitree/go2_description/urdf/go2_description.urdf",
|
asset_path=f"{ISAACLAB_ASSETS_DATA_DIR}/Robots/unitree/go2_description/urdf/go2_description.urdf",
|
||||||
activate_contact_sensors=True,
|
activate_contact_sensors=True,
|
||||||
rigid_props=sim_utils.RigidBodyPropertiesCfg(
|
rigid_props=sim_utils.RigidBodyPropertiesCfg(
|
||||||
|
|||||||
@@ -62,10 +62,10 @@ TERRAIN_CFG = terrain_gen.TerrainGeneratorCfg(
|
|||||||
holes=False,
|
holes=False,
|
||||||
),
|
),
|
||||||
"boxes": terrain_gen.MeshRandomGridTerrainCfg(
|
"boxes": terrain_gen.MeshRandomGridTerrainCfg(
|
||||||
proportion=0.15, grid_width=0.45, grid_height_range=(0.01, 0.15), platform_width=2.0
|
proportion=0.15, grid_width=0.45, grid_height_range=(0.05, 0.2), platform_width=2.0
|
||||||
),
|
),
|
||||||
"random_rough": terrain_gen.HfRandomUniformTerrainCfg(
|
"random_rough": terrain_gen.HfRandomUniformTerrainCfg(
|
||||||
proportion=0.15, noise_range=(0.01, 0.1), noise_step=0.01, border_width=0.25
|
proportion=0.15, noise_range=(0.02, 0.1), noise_step=0.02, border_width=0.25
|
||||||
),
|
),
|
||||||
"flat": terrain_gen.MeshPlaneTerrainCfg(proportion=0.15),
|
"flat": terrain_gen.MeshPlaneTerrainCfg(proportion=0.15),
|
||||||
"hf_pyramid_slope": terrain_gen.HfPyramidSlopedTerrainCfg(
|
"hf_pyramid_slope": terrain_gen.HfPyramidSlopedTerrainCfg(
|
||||||
@@ -143,7 +143,7 @@ class CommandsCfg:
|
|||||||
resampling_time_range=(5.0, 5.0),
|
resampling_time_range=(5.0, 5.0),
|
||||||
rel_standing_envs=0.1,
|
rel_standing_envs=0.1,
|
||||||
rel_heading_envs=1.0,
|
rel_heading_envs=1.0,
|
||||||
heading_command=False, # note here, no heading command!
|
heading_command=False,
|
||||||
heading_control_stiffness=0.5,
|
heading_control_stiffness=0.5,
|
||||||
debug_vis=True,
|
debug_vis=True,
|
||||||
cycle_time=0.5,
|
cycle_time=0.5,
|
||||||
@@ -405,7 +405,30 @@ class EventCfg:
|
|||||||
"make_consistent": True
|
"make_consistent": True
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
reset_base = EventTerm(
|
||||||
|
func=mdp.reset_root_state_uniform,
|
||||||
|
mode="reset",
|
||||||
|
params={
|
||||||
|
"pose_range": {"x": (-0.5, 0.5), "y": (-0.5, 0.5), "z": (0.0, 0.2), "yaw": (-3.14, 3.14)},
|
||||||
|
"velocity_range": {
|
||||||
|
"x": (-0.5, 0.5),
|
||||||
|
"y": (-0.5, 0.5),
|
||||||
|
"z": (-0.5, 0.5),
|
||||||
|
"roll": (-0.5, 0.5),
|
||||||
|
"pitch": (-0.5, 0.5),
|
||||||
|
"yaw": (-0.5, 0.5),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
)
|
||||||
|
randomize_apply_external_force_torque = EventTerm(
|
||||||
|
func=mdp.apply_external_force_torque,
|
||||||
|
mode="reset",
|
||||||
|
params={
|
||||||
|
"asset_cfg": SceneEntityCfg("robot", body_names=BASE_LINK_NAME),
|
||||||
|
"force_range": (-5.0, 5.0),
|
||||||
|
"torque_range": (-5.0, 5.0),
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
@configclass
|
@configclass
|
||||||
class RewardsCfg:
|
class RewardsCfg:
|
||||||
@@ -416,47 +439,38 @@ class RewardsCfg:
|
|||||||
weight=1.0,
|
weight=1.0,
|
||||||
params={"command_name": "base_velocity", "std": 0.5}
|
params={"command_name": "base_velocity", "std": 0.5}
|
||||||
)
|
)
|
||||||
|
|
||||||
track_ang_vel_z_exp = RewTerm(
|
track_ang_vel_z_exp = RewTerm(
|
||||||
func=mdp.track_ang_vel_z_exp,
|
func=mdp.track_ang_vel_z_exp,
|
||||||
weight=0.5,
|
weight=0.5,
|
||||||
params={"command_name": "base_velocity", "std": 0.5}
|
params={"command_name": "base_velocity", "std": 0.5}
|
||||||
)
|
)
|
||||||
|
|
||||||
lin_vel_z_l2 = RewTerm(func=mdp.lin_vel_z_l2, weight=-2.0)
|
lin_vel_z_l2 = RewTerm(func=mdp.lin_vel_z_l2, weight=-2.0)
|
||||||
|
|
||||||
ang_vel_xy_l2 = RewTerm(func=mdp.ang_vel_xy_l2, weight=-0.05)
|
ang_vel_xy_l2 = RewTerm(func=mdp.ang_vel_xy_l2, weight=-0.05)
|
||||||
|
|
||||||
flat_orientation_l2 = RewTerm(
|
flat_orientation_l2 = RewTerm(
|
||||||
func=mdp.flat_orientation_l2,
|
func=mdp.flat_orientation_l2,
|
||||||
weight=-3.0
|
weight=-3.0
|
||||||
)
|
)
|
||||||
|
|
||||||
base_height_l2 = RewTerm(
|
base_height_l2 = RewTerm(
|
||||||
func=mdp.base_height_l2,
|
func=mdp.base_height_l2,
|
||||||
weight=-1.0,
|
weight=-1.0,
|
||||||
params={
|
params={
|
||||||
"asset_cfg": SceneEntityCfg("robot", body_names=BASE_LINK_NAME),
|
"asset_cfg": SceneEntityCfg("robot", body_names=BASE_LINK_NAME),
|
||||||
"target_height": 0.38
|
"target_height": 0.38,
|
||||||
|
"sensor_cfg": SceneEntityCfg("height_scanner"),
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
dof_acc_l2 = RewTerm(
|
dof_acc_l2 = RewTerm(
|
||||||
func=mdp.joint_acc_l2,
|
func=mdp.joint_acc_l2,
|
||||||
weight=-2.0e-7,
|
weight=-2.0e-7,
|
||||||
params={"asset_cfg": SceneEntityCfg("robot", joint_names=JOINT_NAMES)}
|
params={"asset_cfg": SceneEntityCfg("robot", joint_names=JOINT_NAMES)}
|
||||||
)
|
)
|
||||||
|
|
||||||
action_rate_l2 = RewTerm(func=mdp.action_rate_l2, weight=-0.01)
|
action_rate_l2 = RewTerm(func=mdp.action_rate_l2, weight=-0.01)
|
||||||
|
|
||||||
action_smoothness_l2 = RewTerm(func=mdp.action_smoothness_l2, weight=-0.01)
|
action_smoothness_l2 = RewTerm(func=mdp.action_smoothness_l2, weight=-0.01)
|
||||||
|
|
||||||
undesired_contacts = RewTerm(
|
undesired_contacts = RewTerm(
|
||||||
func=mdp.undesired_contacts,
|
func=mdp.undesired_contacts,
|
||||||
weight=-1.0,
|
weight=-1.0,
|
||||||
params={"sensor_cfg": SceneEntityCfg("contact_forces", body_names=".*_thigh|.*_calf"), "threshold": 5.0},
|
params={"sensor_cfg": SceneEntityCfg("contact_forces", body_names=".*_thigh|.*_calf"), "threshold": 5.0},
|
||||||
)
|
)
|
||||||
|
|
||||||
hip_pos_penalty = RewTerm(
|
hip_pos_penalty = RewTerm(
|
||||||
func=mdp.hip_pos_penalty,
|
func=mdp.hip_pos_penalty,
|
||||||
weight=-0.05,
|
weight=-0.05,
|
||||||
@@ -467,23 +481,42 @@ class RewardsCfg:
|
|||||||
"command_threshold": 0.1,
|
"command_threshold": 0.1,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
joint_torques_l2 = RewTerm(
|
joint_torques_l2 = RewTerm(
|
||||||
func=mdp.joint_torques_l2,
|
func=mdp.joint_torques_l2,
|
||||||
weight=-1e-4,
|
weight=-1e-4,
|
||||||
params={"asset_cfg": SceneEntityCfg("robot", joint_names=JOINT_NAMES)}
|
params={"asset_cfg": SceneEntityCfg("robot", joint_names=JOINT_NAMES)}
|
||||||
)
|
)
|
||||||
|
|
||||||
joint_power = RewTerm(
|
joint_power = RewTerm(
|
||||||
func=mdp.joint_power,
|
func=mdp.joint_power,
|
||||||
weight=-2e-5,
|
weight=-2e-5,
|
||||||
params={"asset_cfg": SceneEntityCfg("robot", joint_names=JOINT_NAMES)}
|
params={"asset_cfg": SceneEntityCfg("robot", joint_names=JOINT_NAMES)}
|
||||||
)
|
)
|
||||||
|
feet_regulation = RewTerm(
|
||||||
|
func=mdp.feet_regulation,
|
||||||
|
weight=-0.05,
|
||||||
|
params={
|
||||||
|
"base_height_target": 0.38,
|
||||||
|
"asset_cfg": SceneEntityCfg("robot", body_names=FOOT_LINK_NAME),
|
||||||
|
"sensor_cfg": SceneEntityCfg("height_scanner"),
|
||||||
|
},
|
||||||
|
)
|
||||||
|
dof_pos_limits = RewTerm(
|
||||||
|
func=mdp.dof_pos_limits,
|
||||||
|
weight=-2.0,
|
||||||
|
params={"asset_cfg": SceneEntityCfg("robot")},
|
||||||
|
)
|
||||||
|
|
||||||
@configclass
|
@configclass
|
||||||
class TerminationsCfg:
|
class TerminationsCfg:
|
||||||
"""Termination terms for the MDP."""
|
"""Termination terms for the MDP."""
|
||||||
time_out = DoneTerm(func=mdp.time_out, time_out=True)
|
time_out = DoneTerm(func=mdp.time_out, time_out=True)
|
||||||
|
illegal_contact = DoneTerm(
|
||||||
|
func=mdp.illegal_contact,
|
||||||
|
params={
|
||||||
|
"sensor_cfg": SceneEntityCfg("contact_forces", body_names=BASE_LINK_NAME),
|
||||||
|
"threshold": 1.0
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
@configclass
|
@configclass
|
||||||
class CurriculumCfg:
|
class CurriculumCfg:
|
||||||
@@ -492,7 +525,7 @@ class CurriculumCfg:
|
|||||||
base_linear_velocity = CurrTerm(mdp.gradual_reward_weight_modification, params={
|
base_linear_velocity = CurrTerm(mdp.gradual_reward_weight_modification, params={
|
||||||
"term_name": "lin_vel_z_l2", "initial_weight": -2.0, "final_weight": -0.0, "start_it": 0, "end_it": 1500
|
"term_name": "lin_vel_z_l2", "initial_weight": -2.0, "final_weight": -0.0, "start_it": 0, "end_it": 1500
|
||||||
})
|
})
|
||||||
base_linear_velocity = CurrTerm(mdp.gradual_reward_weight_modification, params={
|
base_height_l2 = CurrTerm(mdp.gradual_reward_weight_modification, params={
|
||||||
"term_name": "base_height_l2", "initial_weight": -1.0, "final_weight": -10.0, "start_it": 0, "end_it": 5000
|
"term_name": "base_height_l2", "initial_weight": -1.0, "final_weight": -10.0, "start_it": 0, "end_it": 5000
|
||||||
})
|
})
|
||||||
ref_stand_envs = CurrTerm(mdp.gradual_ref_stand_modification, params={
|
ref_stand_envs = CurrTerm(mdp.gradual_ref_stand_modification, params={
|
||||||
@@ -535,7 +568,7 @@ class Go2EnvCfg(ManagerBasedRLEnvCfg):
|
|||||||
# Physics material settings from subclass
|
# Physics material settings from subclass
|
||||||
self.sim.physics_material = self.scene.terrain.physics_material
|
self.sim.physics_material = self.scene.terrain.physics_material
|
||||||
self.sim.physx.gpu_max_rigid_patch_count = 10 * 2**15
|
self.sim.physx.gpu_max_rigid_patch_count = 10 * 2**15
|
||||||
self.sim.physx.gpu_collision_stack_size = int(128 * 1024 * 1024) # 128 MB
|
self.sim.physx.gpu_collision_stack_size = int(64 * 1024 * 1024) # 128 MB
|
||||||
self.sim.physx.enable_external_forces_every_iteration = True
|
self.sim.physx.enable_external_forces_every_iteration = True
|
||||||
|
|
||||||
# Update sensor periods
|
# Update sensor periods
|
||||||
|
|||||||
@@ -555,3 +555,71 @@ def hip_pos_penalty(
|
|||||||
stand_still_scale * running_reward
|
stand_still_scale * running_reward
|
||||||
)
|
)
|
||||||
return reward
|
return reward
|
||||||
|
|
||||||
|
def feet_regulation(
|
||||||
|
env: ManagerBasedRLEnv,
|
||||||
|
base_height_target: float,
|
||||||
|
asset_cfg: SceneEntityCfg = SceneEntityCfg("robot"),
|
||||||
|
sensor_cfg: SceneEntityCfg | None = None,
|
||||||
|
) -> torch.Tensor:
|
||||||
|
|
||||||
|
asset: RigidObject = env.scene[asset_cfg.name]
|
||||||
|
feet_ids = asset_cfg.body_ids
|
||||||
|
|
||||||
|
feet_pos_w = asset.data.body_link_pos_w[:, feet_ids, :]
|
||||||
|
base_pos_w = asset.data.root_link_pos_w.unsqueeze(1)
|
||||||
|
feet_xy_vel_w = asset.data.body_lin_vel_w[:, feet_ids, :2]
|
||||||
|
|
||||||
|
base_z = asset.data.root_link_pos_w[:, 2]
|
||||||
|
|
||||||
|
if sensor_cfg is not None:
|
||||||
|
sensor: RayCaster = env.scene[sensor_cfg.name]
|
||||||
|
ray_hits_z = sensor.data.ray_hits_w[..., 2]
|
||||||
|
|
||||||
|
invalid = (
|
||||||
|
torch.isnan(ray_hits_z).any(dim=1)
|
||||||
|
| torch.isinf(ray_hits_z).any(dim=1)
|
||||||
|
| (torch.max(torch.abs(ray_hits_z), dim=1).values > 1e6)
|
||||||
|
)
|
||||||
|
|
||||||
|
estimated_ground_z = torch.mean(ray_hits_z, dim=1)
|
||||||
|
fallback_ground_z = base_z - base_height_target
|
||||||
|
estimated_ground_z = torch.where(invalid, fallback_ground_z, estimated_ground_z)
|
||||||
|
else:
|
||||||
|
estimated_ground_z = base_z - base_height_target
|
||||||
|
|
||||||
|
base_height = base_z - estimated_ground_z
|
||||||
|
|
||||||
|
gravity_w = torch.tensor(env.sim.cfg.gravity, device=env.device, dtype=feet_pos_w.dtype)
|
||||||
|
up_w = -gravity_w / torch.norm(gravity_w)
|
||||||
|
|
||||||
|
delta_feet_w = feet_pos_w - base_pos_w
|
||||||
|
feet2base_height = torch.sum(delta_feet_w * up_w.view(1, 1, 3), dim=-1)
|
||||||
|
|
||||||
|
feet_height = torch.clamp(base_height.unsqueeze(1) - feet2base_height, min=0.0)
|
||||||
|
|
||||||
|
reward = (
|
||||||
|
feet_xy_vel_w.pow(2).sum(dim=-1)
|
||||||
|
* torch.exp(-feet_height / (0.025 * base_height_target))
|
||||||
|
).sum(dim=-1)
|
||||||
|
|
||||||
|
reward *= torch.clamp(-env.scene["robot"].data.projected_gravity_b[:, 2], 0, 0.7) / 0.7
|
||||||
|
|
||||||
|
return reward
|
||||||
|
|
||||||
|
def dof_pos_limits(
|
||||||
|
env: ManagerBasedRLEnv,
|
||||||
|
asset_cfg: SceneEntityCfg = SceneEntityCfg("robot"),
|
||||||
|
) -> torch.Tensor:
|
||||||
|
asset = env.scene[asset_cfg.name]
|
||||||
|
|
||||||
|
joint_pos = asset.data.joint_pos
|
||||||
|
joint_limits = asset.data.soft_joint_pos_limits
|
||||||
|
|
||||||
|
lower = joint_limits[..., 0]
|
||||||
|
upper = joint_limits[..., 1]
|
||||||
|
|
||||||
|
out_of_limits = -(joint_pos - lower).clamp(max=0.0)
|
||||||
|
out_of_limits += (joint_pos - upper).clamp(min=0.0)
|
||||||
|
|
||||||
|
return torch.sum(out_of_limits, dim=1)
|
||||||
|
|||||||
@@ -39,8 +39,8 @@ class RslRlMoeCtsActorCriticCfg(RslRlPpoActorCriticCfg):
|
|||||||
expert_num = 8 # number of experts in the student model
|
expert_num = 8 # number of experts in the student model
|
||||||
latent_dim = 32
|
latent_dim = 32
|
||||||
norm_type = 'l2norm' # normalization type for encoders: l2norm, simnorm
|
norm_type = 'l2norm' # normalization type for encoders: l2norm, simnorm
|
||||||
teacher_encoder_hidden_dims = [512, 256, 128]
|
teacher_encoder_hidden_dims = [512, 256]
|
||||||
student_encoder_hidden_dims = [512, 256, 128]
|
student_encoder_hidden_dims = [512, 256, 256]
|
||||||
actor_hidden_dims=[512, 256, 128]
|
actor_hidden_dims=[512, 256, 128]
|
||||||
critic_hidden_dims=[512, 256, 128]
|
critic_hidden_dims=[512, 256, 128]
|
||||||
activation="elu"
|
activation="elu"
|
||||||
|
|||||||
Reference in New Issue
Block a user