Initial commit

This commit is contained in:
2026-11-02 17:10:39 +08:00
commit 102fdbaf47
79 changed files with 56509 additions and 0 deletions
+28
View File
@@ -0,0 +1,28 @@
BSD 3-Clause License
Copyright (c) 2025, DEEPRoboticsLab
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+1
View File
@@ -0,0 +1 @@
"""Deep Robotics S10 model."""
+115
View File
@@ -0,0 +1,115 @@
"""S10 asset adapter: twelve position-controlled legs and four velocity wheels.
The MJCF and default pose come from the Deep Robotics S10 deployment SDK
(``S10_description/s10_mjcf``). The copied XML has its torque-motor block
removed, so mjlab can add native position/velocity actuators. v4 keeps
the SDK/IsaacLab leg gains (kp=80, kd=2, effort=50 N·m); v7 uses a softer
kp=20 for deployment safety. Wheels use velocity damping 0.8, effort=14 N·m.
"""
import math
from pathlib import Path
import mujoco
from mjlab.actuator import (
BuiltinPositionActuatorCfg,
BuiltinVelocityActuatorCfg,
)
from mjlab.entity import EntityArticulationInfoCfg, EntityCfg
from mjlab.utils.spec_config import CollisionCfg
S10_XML = Path(__file__).parent / "model" / "s10.xml"
LEGS = ("fl", "fr", "hl", "hr")
LEG_JOINT_NAMES = tuple(
f"{leg}_{joint}_joint" for leg in LEGS for joint in ("hipx", "hipy", "knee")
)
WHEEL_JOINT_NAMES = tuple(f"{leg}_wheel_joint" for leg in LEGS)
WHEEL_BODY_NAMES = tuple(f"{leg}_wheel" for leg in LEGS)
WHEEL_GEOM_NAMES = tuple(f"{leg}_wheel_collision" for leg in LEGS)
# Knee-joint housing, shin link and knee hub; v7 excludes these from the
# non-wheel contact termination so stair shin/knee grazing does not end runs.
KNEE_GEOM_NAMES = tuple(
f"{leg}_{part}_collision" for leg in LEGS
for part in ("knee_joint", "shin", "knee_hub"))
# v4 keeps the SDK neutral pose. v7 uses a more crouched, stair-friendly
# pose closer to the gait it needs (hipx 0.05, hipy ±25°, knee 1.0) and a
# softer leg actuator (kp=20) for safer deployment. Knee 1.0 keeps the wheel
# centres outside the body projection even with the ±25° splay.
DEFAULT_HIPY = 0.35
V7_HIPX = 0.05
V7_HIPY = math.radians(25.0)
V7_KNEE = 1.0
V7_LEG_KP = 20.0
def get_spec() -> mujoco.MjSpec:
spec = mujoco.MjSpec.from_file(str(S10_XML))
spec.modelname = "s10"
# Scene solver options are owned by the task, not the attached robot.
spec.option.cone = mujoco.mjtCone.mjCONE_PYRAMIDAL
spec.option.impratio = 1.0
# Name every collision so domain randomisation can select actual contacts.
for i, geom in enumerate(spec.geoms):
if geom.contype or geom.conaffinity:
# Warp MULTICCD cannot handle nonzero margins on these cylinder/box pairs.
geom.margin = 0.0
if not geom.name:
geom.name = f"body_{i}_collision"
return spec
def get_s10_robot_cfg(hipy: float | None = None, hipx: float | None = None,
knee: float | None = None, leg_kp: float = 80.0,
leg_kd: float = 2.0) -> EntityCfg:
"""Return a fresh S10 config with mjlab native position/velocity actuators.
``hipx``, ``hipy`` and ``knee`` are absolute default joint angles. Omit them
for the legacy v4 pose; v7 passes its crouched stair pose. ``leg_kp``/``kd``
let v7 use a softer actuator without changing v4 checkpoints. The joint
action offset and posture penalty both read ``default_joint_pos``, so these
values move the action target and the penalised posture together.
"""
hipx = 0.1 if hipx is None else float(hipx)
hipy = DEFAULT_HIPY if hipy is None else float(hipy)
knee = 0.65 if knee is None else float(knee)
return EntityCfg(
spec_fn=get_spec,
init_state=EntityCfg.InitialStateCfg(
# Default leg pose puts the wheel bottom at ~0.434 m; 0.44 m gives a
# small margin before the reset z offset is applied.
pos=(0.0, 0.0, 0.44),
joint_pos={
"fl_hipx_joint": hipx, "hl_hipx_joint": hipx,
"fr_hipx_joint": -hipx, "hr_hipx_joint": -hipx,
"fl_hipy_joint": -hipy, "fr_hipy_joint": -hipy,
"hl_hipy_joint": hipy, "hr_hipy_joint": hipy,
"fl_knee_joint": knee, "fr_knee_joint": knee,
"hl_knee_joint": -knee, "hr_knee_joint": -knee,
".*_wheel_joint": 0.0,
},
joint_vel={".*": 0.0},
),
collisions=(CollisionCfg(
geom_names_expr=(".*_collision",), contype=1, conaffinity=1,
condim={".*_wheel_collision": 3, "body_.*_collision": 1, ".*": 1},
priority={".*_wheel_collision": 1, "body_.*_collision": 0, ".*": 0},
),),
articulation=EntityArticulationInfoCfg(
actuators=(
# TODO(s10): the SDK/IsaacLab S10 config also randomizes actuator delay
# (0-5 physics steps) and PD gains. v7 uses a softer kp=20 for safe
# deployment; v4 keeps the SDK kp=80 recipe.
BuiltinPositionActuatorCfg(
target_names_expr=LEG_JOINT_NAMES,
stiffness=float(leg_kp), damping=float(leg_kd), effort_limit=50.0,
),
BuiltinVelocityActuatorCfg(
target_names_expr=WHEEL_JOINT_NAMES,
damping=0.8, effort_limit=14.0, armature=0.0005,
),
),
soft_joint_pos_limit_factor=0.9,
),
)
+29
View File
@@ -0,0 +1,29 @@
S10 model adapted from the Deep Robotics deployment SDK
(`S10_description/s10_mjcf/S10.xml`). Only the 17 mesh files referenced by
`s10.xml` are included. The source XML is BSD-3-Clause, see `../LICENSE_s10`.
Local changes:
- Removed the world floor and light so mjlab can attach the robot to its own
terrain.
- Removed the torque `<motor>` actuator block; mjlab adds native position
actuators for the 12 leg joints and native velocity actuators for the 4
wheels.
- Added names to the four wheel collision cylinders
(`fl/fr/hl/hr_wheel_collision`) so wheel friction randomisation and contact
sensors can address them.
- Removed the `<sensor>` block. The SDK XML has unnamed `accelerometer` and
`gyro` elements, which mjlab tries to wrap as a sensor with an empty name and
fails with `KeyError: Invalid name ''` during scene initialization. The
training actor/world model read MuJoCo data directly and do not use these XML
sensors.
- `robot/config.py` names remaining unnamed collision geoms, clears collision
margins for Warp MULTICCD compatibility, and delegates solver options to the
task.
- `meshdir` changed from `../meshes/` to `meshes/`.
Default pose, joint limits, link geometry and inertial values are unchanged
from the SDK model. Actuator gains follow the SDK/IsaacLab S10 configuration:
legs kp=80, kd=2, effort=50 N·m; wheels damping=0.8, effort=14 N·m.
These values are taken from the provided deployment/training projects and are
not independently hardware-calibrated here.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+176
View File
@@ -0,0 +1,176 @@
<?xml version='1.0' encoding='utf-8'?>
<mujoco model="S10">
<default>
<default class="robot">
<default class="motor">
<joint />
<motor />
</default>
<default class="visual">
<geom material="default_material" contype="0" conaffinity="0" group="2" />
</default>
<default class="collision">
<geom material="collision_material" condim="3" contype="1" conaffinity="1" solref="0.005 1" friction="1 0.01 0.001" density="0" group="1" />
</default>
</default>
</default>
<compiler angle="radian" meshdir="meshes/" />
<compiler autolimits="true" />
<asset>
<material name="default_material" rgba="0.7 0.7 0.7 1" />
<material name="collision_material" rgba="0.0 0.4 0.8 0.2" />
<mesh name="base_link" file="base_link.STL" />
<mesh name="fl_hipx" file="fl_hipx.STL" />
<mesh name="fl_hipy" file="fl_hipy.STL" />
<mesh name="fl_knee" file="fl_knee.STL" />
<mesh name="fl_wheel" file="fl_wheel.STL" />
<mesh name="fr_hipx" file="fr_hipx.STL" />
<mesh name="fr_hipy" file="fr_hipy.STL" />
<mesh name="fr_knee" file="fr_knee.STL" />
<mesh name="fr_wheel" file="fr_wheel.STL" />
<mesh name="hl_hipx" file="hl_hipx.STL" />
<mesh name="hl_hipy" file="hl_hipy.STL" />
<mesh name="hl_knee" file="hl_knee.STL" />
<mesh name="hl_wheel" file="hl_wheel.STL" />
<mesh name="hr_hipx" file="hr_hipx.STL" />
<mesh name="hr_hipy" file="hr_hipy.STL" />
<mesh name="hr_knee" file="hr_knee.STL" />
<mesh name="hr_wheel" file="hr_wheel.STL" />
<texture name="texplane" type="2d" builtin="checker" rgb1=".2 .3 .4" rgb2=".1 0.15 0.2" width="512" height="512" />
<material name="MatPlane" reflectance="0.3" texture="texplane" texrepeat="1 1" texuniform="true" />
</asset>
<worldbody>
<body name="base_link" pos="0 0.0 0.5" quat="1 0 0 0" childclass="robot">
<freejoint name="floating_base" />
<inertial pos="-0.000512 0.057317 0.001182" quat="1 0 0 0" mass="8.023087" diaginertia="0.115559 0.171329 0.262028" />
<site name="imu_site" pos="0.0075 -0.0373 0.0556" size="0.005" rgba="1 0 0 1" />
<site name="base_site" pos="0 0 0" quat="1 0 0 0" />
<geom type="mesh" class="visual" mesh="base_link" />
<geom size="0.08 0.3" pos="0 0.024 0" quat="0.707107 0 0.707107 0" type="cylinder" class="collision" />
<geom size="0.08 0.3" pos="0 -0.024 0" quat="0.707107 0 0.707107 0" type="cylinder" class="collision" />
<geom size="0.08 0.024 0.3" quat="0.707107 0 0.707107 0" type="box" class="collision" />
<body name="fl_hipx" pos="0.2277 0.0574 0">
<inertial pos="-0.005034 0.023524 4.6e-05" quat="0.25609 0.665262 -0.228203 0.663151" mass="0.627405" diaginertia="0.000415056 0.000391723 0.000223221" />
<joint name="fl_hipx_joint" pos="0 0 0" axis="-1 0 0" range="-0.6109 0.6109" actuatorfrcrange="-50 50" />
<geom type="mesh" class="visual" mesh="fl_hipx" />
<geom size="0.04 0.05" pos="0 0.054 0" quat="0.707107 0.707107 0 0" type="cylinder" class="collision" />
<body name="fl_hipy" pos="0 0.0779 0">
<inertial pos="7.4e-05 0.018439 -0.129675" quat="0.701304 -0.0510428 0.0516391 0.709155" mass="0.885874" diaginertia="0.00454086 0.00445199 0.00030515" />
<joint name="fl_hipy_joint" pos="0 0 0" axis="0 -1 0" range="-2.5307 2.5307" actuatorfrcrange="-50 50" />
<geom type="mesh" class="visual" mesh="fl_hipy" />
<geom size="0.032 0.012 0.09" pos="0 0.012 -0.09" type="box" class="collision" />
<geom size="0.04 0.04" pos="0 0.018 -0.18" quat="0.707107 0.707107 0 0" type="cylinder" class="collision" name="fl_knee_joint_collision" />
<body name="fl_knee" pos="0 0 -0.18">
<inertial pos="-3.2e-05 0.013504 -0.156308" quat="0.703786 -0.068447 0.068447 0.703786" mass="0.640283" diaginertia="0.0022296 0.002221 0.000193398" />
<joint name="fl_knee_joint" pos="0 0 0" axis="0 -1 0" range="-2.7227 2.7227" actuatorfrcrange="-50 50" />
<geom type="mesh" class="visual" mesh="fl_knee" />
<geom size="0.029 0.01 0.09" pos="0 -0.012 -0.09" type="box" class="collision" name="fl_shin_collision" />
<geom size="0.04 0.025" pos="0 0.002 -0.18" quat="0.707107 0.707107 0 0" type="cylinder" class="collision" name="fl_knee_hub_collision" />
<body name="fl_wheel" pos="0 0.045891 -0.18">
<inertial pos="-8e-06 0.001694 -5e-06" quat="0.707107 0 0 0.707107" mass="0.587952" diaginertia="0.002003 0.001059 0.001059" />
<joint name="fl_wheel_joint" pos="0 0 0" axis="0 -1 0" actuatorfrcrange="-14 14" />
<geom type="mesh" class="visual" mesh="fl_wheel" />
<geom size="0.081 0.0185" quat="0.707107 0.707107 0 0" type="cylinder" class="collision" name="fl_wheel_collision" />
</body>
</body>
</body>
</body>
<body name="fr_hipx" pos="0.2277 -0.0574 0">
<inertial pos="-0.004831 -0.02349 0.000169" quat="-0.278522 0.675499 0.205833 0.650968" mass="0.626546" diaginertia="0.000415238 0.000395047 0.000218715" />
<joint name="fr_hipx_joint" pos="0 0 0" axis="-1 0 0" range="-0.6109 0.6109" actuatorfrcrange="-50 50" />
<geom type="mesh" class="visual" mesh="fr_hipx" />
<geom size="0.04 0.05" pos="0 -0.054 0" quat="0.707107 0.707107 0 0" type="cylinder" class="collision" />
<body name="fr_hipy" pos="0 -0.0779 0">
<inertial pos="-7.4e-05 -0.018439 -0.129675" quat="0.701304 0.0510428 -0.0516391 0.709155" mass="0.885874" diaginertia="0.00454086 0.00445199 0.00030515" />
<joint name="fr_hipy_joint" pos="0 0 0" axis="0 -1 0" range="-2.5307 2.5307" actuatorfrcrange="-50 50" />
<geom type="mesh" class="visual" mesh="fr_hipy" />
<geom size="0.032 0.012 0.09" pos="0 -0.012 -0.09" type="box" class="collision" />
<geom size="0.04 0.04" pos="0 -0.018 -0.18" quat="0.707107 0.707107 0 0" type="cylinder" class="collision" name="fr_knee_joint_collision" />
<body name="fr_knee" pos="0 0 -0.18">
<inertial pos="3.2e-05 -0.013504 -0.156308" quat="0.703786 0.068447 -0.068447 0.703786" mass="0.640283" diaginertia="0.0022296 0.002221 0.000193398" />
<joint name="fr_knee_joint" pos="0 0 0" axis="0 -1 0" range="-2.7227 2.7227" actuatorfrcrange="-50 50" />
<geom type="mesh" class="visual" mesh="fr_knee" />
<geom size="0.029 0.01 0.09" pos="0 0.012 -0.09" type="box" class="collision" name="fr_shin_collision" />
<geom size="0.04 0.025" pos="0 -0.002 -0.18" quat="0.707107 0.707107 0 0" type="cylinder" class="collision" name="fr_knee_hub_collision" />
<body name="fr_wheel" pos="0 -0.045891 -0.18">
<inertial pos="8e-06 -0.001694 5e-06" quat="0.707107 0 0 0.707107" mass="0.587952" diaginertia="0.002003 0.001059 0.001059" />
<joint name="fr_wheel_joint" pos="0 0 0" axis="0 -1 0" actuatorfrcrange="-14 14" />
<geom type="mesh" class="visual" mesh="fr_wheel" />
<geom size="0.081 0.0185" quat="0.707107 0.707107 0 0" type="cylinder" class="collision" name="fr_wheel_collision" />
</body>
</body>
</body>
</body>
<body name="hl_hipx" pos="-0.2277 0.0574 0">
<inertial pos="0.004831 0.02349 0.000169" quat="-0.205833 0.650968 0.278522 0.675499" mass="0.626546" diaginertia="0.000415238 0.000395047 0.000218715" />
<joint name="hl_hipx_joint" pos="0 0 0" axis="-1 0 0" range="-0.6109 0.6109" actuatorfrcrange="-50 50" />
<geom type="mesh" class="visual" mesh="hl_hipx" />
<geom size="0.04 0.05" pos="0 0.054 0" quat="0.707107 0.707107 0 0" type="cylinder" class="collision" />
<body name="hl_hipy" pos="0 0.0779 0">
<inertial pos="7.4e-05 0.018439 -0.129675" quat="0.701304 -0.0510428 0.0516391 0.709155" mass="0.885874" diaginertia="0.00454086 0.00445199 0.00030515" />
<joint name="hl_hipy_joint" pos="0 0 0" axis="0 -1 0" range="-2.5307 2.5307" actuatorfrcrange="-50 50" />
<geom type="mesh" class="visual" mesh="hl_hipy" />
<geom size="0.032 0.012 0.09" pos="0 0.012 -0.09" type="box" class="collision" />
<geom size="0.04 0.04" pos="0 0.018 -0.18" quat="0.707107 0.707107 0 0" type="cylinder" class="collision" name="hl_knee_joint_collision" />
<body name="hl_knee" pos="0 0 -0.18">
<inertial pos="-3.2e-05 0.013504 -0.156308" quat="0.703786 -0.068447 0.068447 0.703786" mass="0.640283" diaginertia="0.0022296 0.002221 0.000193398" />
<joint name="hl_knee_joint" pos="0 0 0" axis="0 -1 0" range="-2.7227 2.7227" actuatorfrcrange="-50 50" />
<geom type="mesh" class="visual" mesh="hl_knee" />
<geom size="0.029 0.01 0.09" pos="0 -0.012 -0.09" type="box" class="collision" name="hl_shin_collision" />
<geom size="0.04 0.025" pos="0 0.002 -0.18" quat="0.707107 0.707107 0 0" type="cylinder" class="collision" name="hl_knee_hub_collision" />
<body name="hl_wheel" pos="0 0.045891 -0.18">
<inertial pos="-8e-06 0.001694 -5e-06" quat="0.707107 0 0 0.707107" mass="0.587952" diaginertia="0.002003 0.001059 0.001059" />
<joint name="hl_wheel_joint" pos="0 0 0" axis="0 -1 0" actuatorfrcrange="-14 14" />
<geom type="mesh" class="visual" mesh="hl_wheel" />
<geom size="0.081 0.0185" quat="0.707107 0.707107 0 0" type="cylinder" class="collision" name="hl_wheel_collision" />
</body>
</body>
</body>
</body>
<body name="hr_hipx" pos="-0.2277 -0.0574 0">
<inertial pos="0.005034 -0.023524 4.6e-05" quat="0.228203 0.663151 -0.25609 0.665262" mass="0.627405" diaginertia="0.000415056 0.000391723 0.000223221" />
<joint name="hr_hipx_joint" pos="0 0 0" axis="-1 0 0" range="-0.6109 0.6109" actuatorfrcrange="-50 50" />
<geom type="mesh" class="visual" mesh="hr_hipx" />
<geom size="0.04 0.05" pos="0 -0.054 0" quat="0.707107 0.707107 0 0" type="cylinder" class="collision" />
<body name="hr_hipy" pos="0 -0.0779 0">
<inertial pos="-7.4e-05 -0.018439 -0.129675" quat="0.701304 0.0510428 -0.0516391 0.709155" mass="0.885874" diaginertia="0.00454086 0.00445199 0.00030515" />
<joint name="hr_hipy_joint" pos="0 0 0" axis="0 -1 0" range="-2.5307 2.5307" actuatorfrcrange="-50 50" />
<geom type="mesh" class="visual" mesh="hr_hipy" />
<geom size="0.032 0.012 0.09" pos="0 -0.012 -0.09" type="box" class="collision" />
<geom size="0.04 0.04" pos="0 -0.018 -0.18" quat="0.707107 0.707107 0 0" type="cylinder" class="collision" name="hr_knee_joint_collision" />
<body name="hr_knee" pos="0 0 -0.18">
<inertial pos="3.2e-05 -0.013504 -0.156308" quat="0.703786 0.068447 -0.068447 0.703786" mass="0.640283" diaginertia="0.0022296 0.002221 0.000193398" />
<joint name="hr_knee_joint" pos="0 0 0" axis="0 -1 0" range="-2.7227 2.7227" actuatorfrcrange="-50 50" />
<geom type="mesh" class="visual" mesh="hr_knee" />
<geom size="0.029 0.01 0.09" pos="0 0.012 -0.09" type="box" class="collision" name="hr_shin_collision" />
<geom size="0.04 0.025" pos="0 -0.002 -0.18" quat="0.707107 0.707107 0 0" type="cylinder" class="collision" name="hr_knee_hub_collision" />
<body name="hr_wheel" pos="0 -0.045891 -0.18">
<inertial pos="8e-06 -0.001694 5e-06" quat="0.707107 0 0 0.707107" mass="0.587952" diaginertia="0.002003 0.001059 0.001059" />
<joint name="hr_wheel_joint" pos="0 0 0" axis="0 -1 0" actuatorfrcrange="-14 14" />
<geom type="mesh" class="visual" mesh="hr_wheel" />
<geom size="0.081 0.0185" quat="0.707107 0.707107 0 0" type="cylinder" class="collision" name="hr_wheel_collision" />
</body>
</body>
</body>
</body>
</body>
</worldbody>
<contact>
<exclude body1="base_link" body2="fl_hipx" />
<exclude body1="fl_hipx" body2="fl_hipy" />
<exclude body1="fl_hipy" body2="fl_knee" />
<exclude body1="fl_knee" body2="fl_wheel" />
<exclude body1="base_link" body2="fr_hipx" />
<exclude body1="fr_hipx" body2="fr_hipy" />
<exclude body1="fr_hipy" body2="fr_knee" />
<exclude body1="fr_knee" body2="fr_wheel" />
<exclude body1="base_link" body2="hl_hipx" />
<exclude body1="hl_hipx" body2="hl_hipy" />
<exclude body1="hl_hipy" body2="hl_knee" />
<exclude body1="hl_knee" body2="hl_wheel" />
<exclude body1="base_link" body2="hr_hipx" />
<exclude body1="hr_hipx" body2="hr_hipy" />
<exclude body1="hr_hipy" body2="hr_knee" />
<exclude body1="hr_knee" body2="hr_wheel" />
</contact>
</mujoco>