Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
121 changes: 101 additions & 20 deletions robolab/robots/galbot_golf.py
Original file line number Diff line number Diff line change
Expand Up @@ -134,14 +134,28 @@ def _galbot_golf_robot_cfg(
init_joint_pos: dict[str, float] | None = None,
init_pos: tuple[float, float, float] = (0.0, 0.0, 0.0),
) -> ArticulationCfg:
"""Build a Golf articulation config while preserving the received USD physics properties."""
"""Build a Golf articulation config with Sim2Real gains and controller gravity compensation.

Stiffness, damping, and effort limits are sourced from the
``galbot-one-golf-sim2real-v1`` system-identification profile
(synthnova/src/synthnova/robots/cfg/galbot_one_golf.toml).
Left/right arm gains are symmetrised and rounded to integers.

Gravity compensation is realised by disabling per-link gravity in the
physics engine (``disable_gravity=True``), matching the behaviour of the
real robot's controller-side compensation.
"""
return ArticulationCfg(
prim_path="{ENV_REGEX_NS}/robot",
spawn=sim_utils.UsdFileCfg(
usd_path=GALBOT_GOLF_USD_PATH,
variants=GALBOT_GOLF_USD_VARIANTS,
activate_contact_sensors=True,
rigid_props=sim_utils.RigidBodyPropertiesCfg(
# Simulate controller-side gravity compensation: the real robot
# compensates gravity in its low-level controller, so the
# joint-position PD loops only see tracking error, not gravity load.
disable_gravity=True,
max_depenetration_velocity=5.0,
),
articulation_props=sim_utils.ArticulationRootPropertiesCfg(
Expand All @@ -167,35 +181,102 @@ def _galbot_golf_robot_cfg(
),
soft_joint_pos_limit_factor=1.0,
actuators={
# Preserve all drive properties authored in the supplied PhysX USD.
# --- Leg linkage (Sim2Real profile, per-joint) ---
# The five leg joints span three torque tiers; all values are
# taken directly from the system-identification profile.
"legs": ImplicitActuatorCfg(
joint_names_expr=["leg_joint.*"],
effort_limit_sim=None,
velocity_limit_sim=None,
stiffness=None,
damping=None,
effort_limit_sim={
"leg_joint1": 433,
"leg_joint2": 433,
"leg_joint3": 204,
"leg_joint4": 70,
"leg_joint5": 70,
},
velocity_limit_sim={
"leg_joint1": 2.094395,
"leg_joint2": 2.094395,
"leg_joint3": 3.141593,
"leg_joint4": 3.141593,
"leg_joint5": 3.141593,
},
stiffness={
"leg_joint1": 8660,
"leg_joint2": 8660,
"leg_joint3": 4080,
"leg_joint4": 1400,
"leg_joint5": 1400,
},
damping={
"leg_joint1": 727,
"leg_joint2": 567,
"leg_joint3": 222,
"leg_joint4": 88,
"leg_joint5": 85,
},
),
# --- Head pan / tilt ---
"head": ImplicitActuatorCfg(
joint_names_expr=["head_joint.*"],
effort_limit_sim=None,
velocity_limit_sim=None,
stiffness=None,
damping=None,
effort_limit_sim=4,
stiffness=80,
damping=4,
),
"arms": ImplicitActuatorCfg(
joint_names_expr=["left_arm_joint.*", "right_arm_joint.*"],
effort_limit_sim=None,
velocity_limit_sim=None,
stiffness=None,
damping=None,
# --- Arm shoulder (joints 1–2, ±180 N·m) ---
# Left/right values are symmetrised (averaged) and rounded to integers.
"arm_shoulder": ImplicitActuatorCfg(
joint_names_expr=["left_arm_joint[12]", "right_arm_joint[12]"],
effort_limit_sim=180,
velocity_limit_sim=3.141593,
stiffness={
"left_arm_joint1": 3500,
"left_arm_joint2": 3400,
"right_arm_joint1": 3500,
"right_arm_joint2": 3400,
},
damping={
"left_arm_joint1": 100,
"left_arm_joint2": 96,
"right_arm_joint1": 100,
"right_arm_joint2": 96,
},
),
# --- Arm elbow (joints 3–4, ±90 N·m) ---
"arm_elbow": ImplicitActuatorCfg(
joint_names_expr=["left_arm_joint[34]", "right_arm_joint[34]"],
effort_limit_sim=90,
velocity_limit_sim=3.926991,
stiffness={
"left_arm_joint3": 1145,
"left_arm_joint4": 1143,
"right_arm_joint3": 1145,
"right_arm_joint4": 1143,
},
damping=32,
),
# --- Arm wrist (joints 5–7, ±30 N·m) ---
"arm_wrist": ImplicitActuatorCfg(
joint_names_expr=["left_arm_joint[5-7]", "right_arm_joint[5-7]"],
effort_limit_sim=30,
velocity_limit_sim=3.926991,
stiffness={
"left_arm_joint5": 286,
"left_arm_joint6": 284,
"left_arm_joint7": 284,
"right_arm_joint5": 286,
"right_arm_joint6": 284,
"right_arm_joint7": 284,
},
damping=8,
),
# --- DESC grippers (±1.5 N·m hardware rating) ---
"grippers": ImplicitActuatorCfg(
joint_names_expr=["left_gripper_joint", "right_gripper_joint"],
effort_limit_sim=1.0,
velocity_limit_sim=3.5,
stiffness=40.0,
damping=5.0,
effort_limit_sim=1.5,
stiffness=77,
damping=4,
),
# --- Holonomic wheels: preserve USD-authored drive properties ---
"wheels": ImplicitActuatorCfg(
joint_names_expr=WHEEL_JOINTS,
effort_limit_sim=None,
Expand Down
45 changes: 45 additions & 0 deletions tests/test_galbot_configs.py
Original file line number Diff line number Diff line change
Expand Up @@ -167,3 +167,48 @@ def __init__(self):
assert tuple(asset.init_state.pos) == pytest.approx((0.5, 0.0, 0.0))
assert tuple(asset.init_state.rot) == pytest.approx((0.0, 0.0, 0.0, 1.0))
assert table_fixture_asset(None, _FakeRobotCfg) is None


def test_gravity_compensation_is_enabled():
"""disable_gravity must be True to simulate controller-side gravity compensation."""
robot = GalbotGolfFixedBaseCfg().robot
assert robot.spawn.rigid_props.disable_gravity is True


def test_actuator_gains_match_sim2real_profile():
"""Actuator stiffness, damping and effort limits must match galbot-one-golf-sim2real-v1.

Left/right arm values are symmetrised; grippers use the hardware effort rating.
"""
robot = GalbotGolfFixedBaseCfg().robot
actuators = robot.actuators

# Shoulder (joints 1–2): highest-torque arm section, ±180 N·m.
shoulder = actuators["arm_shoulder"]
assert shoulder.effort_limit_sim == pytest.approx(180)
assert shoulder.velocity_limit_sim == pytest.approx(3.141593)
assert shoulder.stiffness["left_arm_joint1"] == pytest.approx(3500)
assert shoulder.stiffness["right_arm_joint1"] == pytest.approx(3500)
assert shoulder.stiffness["left_arm_joint2"] == pytest.approx(3400)
assert shoulder.damping["left_arm_joint1"] == pytest.approx(100)
assert shoulder.damping["right_arm_joint1"] == pytest.approx(100)

# Elbow (joints 3–4): ±90 N·m, uniform damping.
elbow = actuators["arm_elbow"]
assert elbow.effort_limit_sim == pytest.approx(90)
assert elbow.stiffness["left_arm_joint3"] == pytest.approx(1145)
assert elbow.stiffness["right_arm_joint3"] == pytest.approx(1145)
assert elbow.damping == pytest.approx(32)

# Wrist (joints 5–7): ±30 N·m, uniform damping.
wrist = actuators["arm_wrist"]
assert wrist.effort_limit_sim == pytest.approx(30)
assert wrist.stiffness["left_arm_joint5"] == pytest.approx(286)
assert wrist.stiffness["right_arm_joint5"] == pytest.approx(286)
assert wrist.damping == pytest.approx(8)

# Grippers: hardware-rated effort limit.
grippers = actuators["grippers"]
assert grippers.effort_limit_sim == pytest.approx(1.5)
assert grippers.stiffness == pytest.approx(77)
assert grippers.damping == pytest.approx(4)