This repository contains a complete MuJoCo model of the Solo-12 quadruped, including high fidelity visuals:
The model has been optimized for loading time and rendering performance by:
- Removing duplicate geometry and reusing meshes as much as possible
- Simplifying large meshes
- Manually filtering and removing internal components
๐ค Please feel free to submit improvements to the model by opening a pull request!
- Install requirements:
pip3 install -r requirements.txt
- Generate the Solo-12 model:
python3 ./generate_model.py
- This will write an
.xml
file with the geometry of the four legs imported and correctly oriented
- This will write an
- Start MuJoCo:
python3 -m mujoco.viewer
- Drag-and-drop
scene.xml
to the MuJoCo viewer to load the scene
โน๏ธ This section contains details about how the model was created, for reference. โน๏ธ
-
The robot's URDF and SRDF were obtained from the robot_properties_solo repository.
-
MuJoCo compilation directives were added to the URDF:
<mujoco> <compiler meshdir="meshes/" discardvisual="true" fusestatic="false"/> </mujoco>
These ensure MuJoCo doesn't optimize links away by assuming the base is fixed.
-
MuJoCo's
compile.cc
converted the URDF to an.xml
which was manually cleaned up and annotated.The compiler re-expresses link moment of inertia along the principal axes, so original values are not preserved. The two representations are equivalent.
-
SRDF
<disable_collisions>
elements are manually converted to<contact>/<exclude>
tags.
MuJoCo calculates collisions by replacing concave meshes with their convex hull. This means that despite the contact exclusions, the upper leg can sometimes collide with the convex hull of the body.
We therefore convex decompose the collision meshes:
-
The
.stl
meshes referenced by the URDF were converted to.obj
. -
The
obj2mjcf
tool was ran on the meshes (source). This uses VHACD approximate convex decomposition:- For the leg meshes we used 6 convex hulls:
obj2mjcf --obj-dir .\ --save-mjcf --compile-model --verbose --vhacd-args.enable --vhacd-args.max-output-convex-hulls 6 --vhacd-args.max-hull-vert-count 256 --vhacd-args.split-hull --vhacd-args.voxel-resolution 5000000 --vhacd-args.volume-error-percent 0.1
- For the body mesh we used 12, as it's a more complicated shape:
obj2mjcf --obj-dir .\ --save-mjcf --compile-model --verbose --vhacd-args.enable --vhacd-args.max-output-convex-hulls 12 --vhacd-args.max-hull-vert-count 256 --vhacd-args.split-hull --vhacd-args.voxel-resolution 1000000 --vhacd-args.volume-error-percent 0.01 --overwrite --obj-filter "solo_12_base.obj"
Before VHACD After VHACD
-
The robot was loaded in Solidworks and coloured according to the PLA colours I have at home ๐ (source).
-
For each collision mesh, the appropriate visual mesh was exported in
.ply
format.-
A Python script was added to import and orient
<geom>
elements multiple times (generate_model.py
). This is so that duplicated geometry (eg. actuator modules) is not saved and loaded from disk more than once.โ ๏ธ MuJoCo's<include>
element cannot import the same file more than once.
-
-
The
.ply
meshes were converted to.obj
with Meshlab.โ ๏ธ Meshlab creates .obj meshes with materials. Other software might assign colours on each vertex which won't be processed byobj2mjcf
. -
For each mesh, Solidworks was used to figure out the correct orientation and offset from the export origin. Visuals were oriented to match collision meshes using Meshlab.
-
MuJoCo doesn't support multimaterial / composite meshes. The
obj2mjcf
tool was run to split the meshes into groups with the same material:obj2mjcf --obj-dir ./ --save-mjcf --compile-model --verbose
-
For each submesh group, the following simplification steps were performed to reduce loading times and improve rendering performance:
- Internal geometry was removed
- Mesh decimation was performed using Meshlab's
Simplification: Quadric Edge Collapse Decimation
filter - Materials used across meshes were merged and reused
-
The hip adapter components were exported and manually added to the FR and HL legs.
-
The materials were finally roughly adjusted for reflectivity and colour.
-
The collision model
<geoms>
were merged with visuals and saved in separate files. Both are imported for each link using the custom<import_with_attrs>
component (seegenerate_model.py
). -
A
<joint type="free">
was added so the robot's base is free floating. -
Joint position actuators were added for each joint with test
Kp
values. -
A skybox, floor and lights were added (see this scene from the MuJoCo Menagerie).