add go2 articulation cfg from unitree_rl_lab; align domain rand with go2_rl_gym.
This commit is contained in:
@@ -5,17 +5,71 @@
|
||||
Reference: https://github.com/unitreerobotics/unitree_ros
|
||||
"""
|
||||
|
||||
import os
|
||||
import isaaclab.sim as sim_utils
|
||||
from isaaclab.actuators import DCMotorCfg
|
||||
from isaaclab.assets.articulation import ArticulationCfg
|
||||
from isaaclab.utils import configclass
|
||||
|
||||
from robot_lab.assets import ISAACLAB_ASSETS_DATA_DIR
|
||||
from robot_lab.assets.unitree_actuator import UnitreeActuatorCfg_Go2HV
|
||||
|
||||
##
|
||||
# Configuration
|
||||
##
|
||||
@configclass
|
||||
class UnitreeArticulationCfg(ArticulationCfg):
|
||||
"""Configuration for Unitree articulations."""
|
||||
|
||||
UNITREE_GO2_CFG = ArticulationCfg(
|
||||
joint_sdk_names: list[str] = None
|
||||
|
||||
soft_joint_pos_limit_factor = 0.9
|
||||
|
||||
|
||||
@configclass
|
||||
class UnitreeUrdfFileCfg(sim_utils.UrdfFileCfg):
|
||||
fix_base: bool = False
|
||||
activate_contact_sensors: bool = True
|
||||
replace_cylinders_with_capsules = True
|
||||
joint_drive = sim_utils.UrdfConverterCfg.JointDriveCfg(
|
||||
gains=sim_utils.UrdfConverterCfg.JointDriveCfg.PDGainsCfg(stiffness=0, damping=0)
|
||||
)
|
||||
articulation_props = sim_utils.ArticulationRootPropertiesCfg(
|
||||
enabled_self_collisions=True,
|
||||
solver_position_iteration_count=8,
|
||||
solver_velocity_iteration_count=4,
|
||||
)
|
||||
rigid_props = sim_utils.RigidBodyPropertiesCfg(
|
||||
disable_gravity=False,
|
||||
retain_accelerations=False,
|
||||
linear_damping=0.0,
|
||||
angular_damping=0.0,
|
||||
max_linear_velocity=1000.0,
|
||||
max_angular_velocity=1000.0,
|
||||
max_depenetration_velocity=1.0,
|
||||
)
|
||||
|
||||
def replace_asset(self, meshes_dir, urdf_path):
|
||||
"""Replace the asset with a temporary copy to avoid modifying the original asset.
|
||||
|
||||
When need to change the collisions, place the modified URDF file separately in this repository,
|
||||
and let `meshes_dir` be provided by `unitree_ros`.
|
||||
This function will auto construct a complete `robot_description` file structure in the `/tmp` directory.
|
||||
Note: The mesh references inside the URDF should be in the same directory level as the URDF itself.
|
||||
"""
|
||||
tmp_meshes_dir = "/tmp/IsaacLab/unitree_rl_lab/meshes"
|
||||
if os.path.exists(tmp_meshes_dir):
|
||||
os.remove(tmp_meshes_dir)
|
||||
os.makedirs("/tmp/IsaacLab/unitree_rl_lab", exist_ok=True)
|
||||
os.symlink(meshes_dir, tmp_meshes_dir)
|
||||
|
||||
self.asset_path = "/tmp/IsaacLab/unitree_rl_lab/robot.urdf"
|
||||
if os.path.exists(self.asset_path):
|
||||
os.remove(self.asset_path)
|
||||
os.symlink(urdf_path, self.asset_path)
|
||||
|
||||
# Go2 config from robot_lab [https://github.com/fan-ziqi/robot_lab]
|
||||
GO2_CFG_ROBOTLAB = ArticulationCfg(
|
||||
spawn=sim_utils.UrdfFileCfg(
|
||||
fix_base=False,
|
||||
merge_fixed_joints=True,
|
||||
@@ -66,5 +120,39 @@ UNITREE_GO2_CFG = ArticulationCfg(
|
||||
),
|
||||
},
|
||||
)
|
||||
"""Configuration of Unitree Go2 using DC motor.
|
||||
"""
|
||||
|
||||
|
||||
|
||||
# Go2 config from unitree_rl_lab [https://github.com/unitreerobotics/unitree_rl_lab]
|
||||
GO2_CFG_UNITREE = UnitreeArticulationCfg(
|
||||
spawn=UnitreeUrdfFileCfg(
|
||||
asset_path=f"{ISAACLAB_ASSETS_DATA_DIR}/go2/urdf/go2.urdf",
|
||||
),
|
||||
init_state=ArticulationCfg.InitialStateCfg(
|
||||
pos=(0.0, 0.0, 0.4),
|
||||
joint_pos={
|
||||
".*R_hip_joint": -0.1,
|
||||
".*L_hip_joint": 0.1,
|
||||
"F[L,R]_thigh_joint": 0.8,
|
||||
"R[L,R]_thigh_joint": 1.0,
|
||||
".*_calf_joint": -1.5,
|
||||
},
|
||||
joint_vel={".*": 0.0},
|
||||
),
|
||||
actuators={
|
||||
"GO2HV": UnitreeActuatorCfg_Go2HV(
|
||||
joint_names_expr=[".*"],
|
||||
stiffness=25.0,
|
||||
damping=0.5,
|
||||
friction=0.01,
|
||||
),
|
||||
},
|
||||
# fmt: off
|
||||
joint_sdk_names=[
|
||||
"FR_hip_joint", "FR_thigh_joint", "FR_calf_joint",
|
||||
"FL_hip_joint", "FL_thigh_joint", "FL_calf_joint",
|
||||
"RR_hip_joint", "RR_thigh_joint", "RR_calf_joint",
|
||||
"RL_hip_joint", "RL_thigh_joint", "RL_calf_joint"
|
||||
],
|
||||
# fmt: on
|
||||
)
|
||||
|
||||
130
source/robot_lab/robot_lab/assets/unitree_actuator.py
Normal file
130
source/robot_lab/robot_lab/assets/unitree_actuator.py
Normal file
@@ -0,0 +1,130 @@
|
||||
# Unitree actuator class that implements a torque-speed curve for the actuators.
|
||||
# source: https://github.com/unitreerobotics/unitree_rl_lab
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import torch
|
||||
from dataclasses import MISSING
|
||||
|
||||
from isaaclab.actuators import DelayedPDActuator, DelayedPDActuatorCfg
|
||||
from isaaclab.utils import configclass
|
||||
from isaaclab.utils.types import ArticulationActions
|
||||
|
||||
|
||||
class UnitreeActuator(DelayedPDActuator):
|
||||
"""Unitree actuator class that implements a torque-speed curve for the actuators.
|
||||
|
||||
The torque-speed curve is defined as follows:
|
||||
|
||||
Torque Limit, N·m
|
||||
^
|
||||
Y2──────────|
|
||||
|──────────────Y1
|
||||
| │\
|
||||
| │ \
|
||||
| │ \
|
||||
| | \
|
||||
------------+--------------|------> velocity: rad/s
|
||||
X1 X2
|
||||
|
||||
- Y1: Peak Torque Test (Torque and Speed in the Same Direction)
|
||||
- Y2: Peak Torque Test (Torque and Speed in the Opposite Direction)
|
||||
- X1: Maximum Speed at Full Torque (T-N Curve Knee Point)
|
||||
- X2: No-Load Speed Test
|
||||
|
||||
- Fs: Static friction coefficient
|
||||
- Fd: Dynamic friction coefficient
|
||||
- Va: Velocity at which the friction is fully activated
|
||||
"""
|
||||
|
||||
cfg: UnitreeActuatorCfg
|
||||
|
||||
armature: torch.Tensor
|
||||
"""The armature of the actuator joints. Shape is (num_envs, num_joints).
|
||||
armature = J2 + J1 * i2 ^ 2 + Jr * (i1 * i2) ^ 2
|
||||
"""
|
||||
|
||||
def __init__(self, cfg: UnitreeActuatorCfg, *args, **kwargs):
|
||||
super().__init__(cfg, *args, **kwargs)
|
||||
|
||||
self._joint_vel = torch.zeros_like(self.computed_effort)
|
||||
self._effort_y1 = self._parse_joint_parameter(cfg.Y1, 1e9)
|
||||
self._effort_y2 = self._parse_joint_parameter(cfg.Y2, cfg.Y1)
|
||||
self._velocity_x1 = self._parse_joint_parameter(cfg.X1, 1e9)
|
||||
self._velocity_x2 = self._parse_joint_parameter(cfg.X2, 1e9)
|
||||
self._friction_static = self._parse_joint_parameter(cfg.Fs, 0.0)
|
||||
self._friction_dynamic = self._parse_joint_parameter(cfg.Fd, 0.0)
|
||||
self._activation_vel = self._parse_joint_parameter(cfg.Va, 0.01)
|
||||
|
||||
def compute(
|
||||
self, control_action: ArticulationActions, joint_pos: torch.Tensor, joint_vel: torch.Tensor
|
||||
) -> ArticulationActions:
|
||||
# save current joint vel
|
||||
self._joint_vel[:] = joint_vel
|
||||
# calculate the desired joint torques
|
||||
control_action = super().compute(control_action, joint_pos, joint_vel)
|
||||
|
||||
# apply friction model on the torque
|
||||
self.applied_effort -= (
|
||||
self._friction_static * torch.tanh(joint_vel / self._activation_vel) + self._friction_dynamic * joint_vel
|
||||
)
|
||||
|
||||
control_action.joint_positions = None
|
||||
control_action.joint_velocities = None
|
||||
control_action.joint_efforts = self.applied_effort
|
||||
|
||||
return control_action
|
||||
|
||||
def _clip_effort(self, effort: torch.Tensor) -> torch.Tensor:
|
||||
# check if the effort is the same direction as the joint velocity
|
||||
same_direction = (self._joint_vel * effort) > 0
|
||||
max_effort = torch.where(same_direction, self._effort_y1, self._effort_y2)
|
||||
# check if the joint velocity is less than the max speed at full torque
|
||||
max_effort = torch.where(
|
||||
self._joint_vel.abs() < self._velocity_x1, max_effort, self._compute_effort_limit(max_effort)
|
||||
)
|
||||
return torch.clip(effort, -max_effort, max_effort)
|
||||
|
||||
def _compute_effort_limit(self, max_effort):
|
||||
k = -max_effort / (self._velocity_x2 - self._velocity_x1)
|
||||
limit = k * (self._joint_vel.abs() - self._velocity_x1) + max_effort
|
||||
return limit.clip(min=0.0)
|
||||
|
||||
|
||||
@configclass
|
||||
class UnitreeActuatorCfg(DelayedPDActuatorCfg):
|
||||
"""
|
||||
Configuration for Unitree actuators.
|
||||
"""
|
||||
|
||||
class_type: type = UnitreeActuator
|
||||
|
||||
X1: float = 1e9
|
||||
"""Maximum Speed at Full Torque(T-N Curve Knee Point) Unit: rad/s"""
|
||||
|
||||
X2: float = 1e9
|
||||
"""No-Load Speed Test Unit: rad/s"""
|
||||
|
||||
Y1: float = MISSING
|
||||
"""Peak Torque Test(Torque and Speed in the Same Direction) Unit: N*m"""
|
||||
|
||||
Y2: float | None = None
|
||||
"""Peak Torque Test(Torque and Speed in the Opposite Direction) Unit: N*m"""
|
||||
|
||||
Fs: float = 0.0
|
||||
""" Static friction coefficient """
|
||||
|
||||
Fd: float = 0.0
|
||||
""" Dynamic friction coefficient """
|
||||
|
||||
Va: float = 0.01
|
||||
""" Velocity at which the friction is fully activated """
|
||||
|
||||
|
||||
@configclass
|
||||
class UnitreeActuatorCfg_Go2HV(UnitreeActuatorCfg):
|
||||
X1 = 13.5
|
||||
X2 = 30
|
||||
Y1 = 20.2
|
||||
Y2 = 23.4
|
||||
|
||||
@@ -18,7 +18,7 @@ from isaaclab.utils.noise import AdditiveUniformNoiseCfg as Unoise
|
||||
import isaaclab.terrains as terrain_gen
|
||||
|
||||
import robot_lab.tasks.go2.mdp as mdp
|
||||
from robot_lab.assets.unitree import UNITREE_GO2_CFG
|
||||
from robot_lab.assets.unitree import GO2_CFG_ROBOTLAB, GO2_CFG_UNITREE
|
||||
|
||||
JOINT_NAMES = [
|
||||
"FL_hip_joint", "FL_thigh_joint", "FL_calf_joint",
|
||||
@@ -105,7 +105,7 @@ class Go2SceneCfg(InteractiveSceneCfg):
|
||||
debug_vis=False
|
||||
)
|
||||
|
||||
robot: ArticulationCfg = UNITREE_GO2_CFG.replace(prim_path="{ENV_REGEX_NS}/Robot")
|
||||
robot: ArticulationCfg = GO2_CFG_ROBOTLAB.replace(prim_path="{ENV_REGEX_NS}/Robot")
|
||||
|
||||
height_scanner = RayCasterCfg(
|
||||
prim_path="{ENV_REGEX_NS}/Robot/base",
|
||||
@@ -331,7 +331,7 @@ class EventCfg:
|
||||
func=mdp.reset_joints_by_scale,
|
||||
mode="reset",
|
||||
params={
|
||||
"position_range": (0.8, 1.2),
|
||||
"position_range": (0.5, 1.5),
|
||||
"velocity_range": (0.0, 0.0),
|
||||
},
|
||||
)
|
||||
@@ -387,15 +387,7 @@ class EventCfg:
|
||||
},
|
||||
},
|
||||
)
|
||||
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
|
||||
class RewardsCfg:
|
||||
|
||||
Reference in New Issue
Block a user