Instructions to use k-valentin/unitree-g1-mujoco with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- LeRobot
How to use k-valentin/unitree-g1-mujoco with LeRobot:
# No code snippets available yet for this library. # To use this model, check the repository files and the library's documentation. # Want to help? PRs adding snippets are welcome at: # https://github.com/huggingface/huggingface.js
- Notebooks
- Google Colab
- Kaggle
Commit History
11 days ago
-
feat: configurable yaw jitter of world objects (WORLD_RANDOMIZE_YAW)
d0e4913 -
feat(d455): use the lab unit's factory calibration for the head camera
Fx/Fy/PPX/PPY from the D455's own calibration (S/N 244622300576) replace the datasheet values. MuJoCo's principalpixel is 320 - PPX, 240 - PPY, the opposite sign to the image offset; the d435i comment and the test now say so.b31bea8
18 days ago
-
refactor!: move the worlds and the scripted grasp out to the worlds repo
assets/worlds/pick_cylinder, tools/grasp_diag.py and tools/thumb_map.py now live in unitree-g1-mujoco-worlds, which this repo only resolves by WORLD spec. The world tests become generic mechanism tests against a robot-agnostic fixture world (tabletop) and cover resolution, name clashes, several objects, relative asset paths and the hand collision bit. The README describes the world contract and what the robot adds.5978dab -
refactor: resolve worlds by name, path or repo with a world.yaml
Worlds are moving to their own repo. sim/worlds.py resolves a WORLD spec (folder, world.xml, name via UNITREE_G1_MUJOCO_WORLDS_ROOT or WORLDS_REPO, owner/repo[@rev]:name) and validates the optional world.yaml. Cameras are discovered from the world file, the jitter support geom and the default jitter come from world.yaml, and compose.py takes the resolved world.xml path and makes its relative file paths absolute.d14801e -
fix(env): hydrate the Hub snapshot unless it is complete
The XR teleop downloads the same snapshot with allow_patterns for sim/mjcf/*.py and assets/*.xml. That leaves assets/scene.xml in place, so the old check skipped the full download and importing sim.simulator_factory failed. Check sentinels that no such partial pattern matches instead.7b6c963
25 days ago
-
fix: mirror the optional pad axis of the left thumb
The left distal frames are mirrored about the palm plane (checked on the composed model: mapping the right pad axes through the mirror gives the same finger axis and a sign-flipped thumb z), so build(pads=True) now gives the left thumb pad 0 -0.97 0.23. ToolsTests checks both sides.3dd7b95 -
feat: optional soft fingertip pads in the AmazingHand generator
build(pads=True) puts each distal body's collision geoms on a slide joint (0-5 mm, 500 N/m, 2 Ns/m) along the closed-grasp contact normal. At the dynamic-arm grasp cell pads (300-800 N/m) and softer finger loops (solref 0.003-0.008) did not change the outcome (rigid 25/25, pad 500 + loop 0.005 25/25, pad 500 21/25), so the committed parts file stays rigid.3fdbb79 -
feat: attach-on-close kinematic grasp for the pick_cylinder world (WORLD_GRASP)
A weld per hand is composed in for WORLD_GRASP=attach (default) and activated at the current relative pose when the AmazingHand's fingers 1-3 close past 0.6 with the object in the grasp zone; it releases at 0.4.43d0244 -
feat: pick_cylinder world (table + free cylinder) selectable with WORLD
WORLD merges assets/worlds/<name>.xml into the composed scene; pick_cylinder adds a table, a free-jointed cylinder and a fixed table_view camera that is published next to the end effector's cameras. The cylinder is put back at its spawn pose on every reset, jittered by WORLD_RANDOMIZE (xy metres, +-15 deg yaw).601e2cb
-
feat: {side}_tcp site in every end effector for XR arm IK
The point that follows the operator's tracked wrist, in the mount frame. Placeholder until CAD: xr_teleoperate's G1_29 IK end effector (wrist_yaw_link +0.05 m).e83e679 -
fix: compose from the Hugging Face cache, whose files are symlinks
compose.py resolved __file__ and mesh paths, which in the Hub cache follows each symlink into blobs/: ROOT became the cache root (assets not found) and mesh paths lost their extension. Paths are now made absolute without following symlinks. HubCacheLayoutTests composes a model through a symlinked copy of the repo laid out like the cache.d547669 -
feat: datasheet camera intrinsics for the D435i and D455 head sensors
The head cameras carry pinhole intrinsics for the recorded 640x480 color mode (resolution, focalpixel, principalpixel, sensorsize) instead of a field of view, derived from the Intel D400-series datasheet until each unit's calibration can be read: native focal lengths from the datasheet H and V FOVs are averaged (square pixels) and scaled to the 640x480 mode, with the principal point at the image centre. - d435i: 1920x1080, 69x42 deg -> f = 623.01 px (54.4 x 42.1 deg) - d455: 1280x800, 90x65 deg -> f = 380.36 px (80.1 x 64.5 deg) Each sensor file documents the derivation and how to replace it with rs-enumerate-devices -c values; a test checks the compiled intrinsics.9a8db34 -
feat: independent head mount and head sensor; stock D435i sensor
HEAD is replaced by HEAD_MOUNT (fixed | pan_tilt) and HEAD_SENSOR (d435i | d455), chosen independently (UNITREE_G1_MUJOCO_HEAD_MOUNT / _HEAD_SENSOR). The bodies' built-in head_camera becomes a head_sensor_mount at the same pose, oriented so a sensor looks along its +x with +z up; pan_tilt replaces it with its own. sensors/d435i.xml is the stock G1 head camera (fovy 42, the D435i color vertical FOV; it was MuJoCo's default 45). Every option now comes from the argument, else config.yaml, else the default. Composed model names follow LeRobot's g1-<body>-<end_effector>-<head_mount>-<head_sensor>. All 20 previous combinations keep their joints, actuators, masses and camera poses (old none = fixed + d435i, d455_pan_tilt = pan_tilt + d455).c19bad2 -
refactor: drop the grippers/hands end effector aliases; dex1 and dex3 are the only names
8f0a59a -
refactor: drop the dummy end effector alias; rubber_hand is the only name
dd0f1dc -
refactor: split the head into a pan/tilt mount and a D455 sensor
heads/d455_pan_tilt.xml becomes heads/pan_tilt.xml, the mechanism (servos, joints, actuators, tilt bracket) with a head_sensor_mount at the bracket tip, and sensors/d455.xml, the head_camera and its optics in that mount's frame. compose.py's HEADS pairs them: d455_pan_tilt = (pan_tilt, d455), so another camera on the same mount is a new sensors file and one HEADS entry, while the HEAD names LeRobot uses stay. The tilt bracket is head_tilt_link (was d455_link), with its lab mesh renamed to match. All 20 composed models keep their camera poses, joints, actuators and masses. The docs no longer claim the head meshes are not shipped.3b31532 -
refactor: extract bodies and end effectors into reusable parts files
Every model is now one bare body plus parts files, so each end effector and head is defined once and reused on either body: - assets/g1_29dof.xml, assets/g1_23dof.xml: Unitree's bodies without hands and with the bare wrist inertia (the 23dof wrist-roll link is now wrist_roll_link, like on 29dof) - assets/end_effectors/{rubber_hand,dex1,dex3,amazing_hand}.xml: each a left/right_ee_mount body in the 29dof wrist_yaw_link frame with the assets, defaults, actuators, sensors and equality constraints it uses - assets/heads/d455_pan_tilt.xml: the pan/tilt head in the 23dof torso frame rubber_hand, dex3 and the bodies are extracted once from Unitree's full models (named in each file; the originals are in history at 1801640); dex1 and amazing_hand are generated by tools/build_dex1_model.py and tools/build_amazing_hand.py, and ToolsTests checks they are up to date. sim/mjcf/compose.py only attaches parts. The full Dex1/Dex3/rubber-hand models and URDFs, the fused 23dof wrist meshes, p…739c738 -
refactor: group model composition in sim/mjcf; test the asset generators
sim/model_builder.py, sim/amazing_hand.py and sim/pan_tilt_head.py only build MJCF, unlike the rest of sim/ (the simulator, DDS bridge, head/hand device), so they move to sim/mjcf/ as compose.py, amazing_hand.py and pan_tilt_head.py. tools/build_dex1_model.py takes an output directory, and ToolsTests checks that both tools reproduce the committed assets (the forearm meshes test skips while the meshes are git-lfs pointers).5fb894a -
refactor: name models by body and end effector; move builders into sim/ and tools/
Assets are named g1_<body>_<end_effector>: g1_{29,23}dof_rubber_hand.xml (were *_no_hand, though they carry the rubber hands), g1_29dof_dex1.xml /.urdf (were with_grippers / with_dex1_1), g1_29dof_dex3.xml/.urdf (were with_hand / g1_body29_hand14), and one scene.xml template (was scene_hands_cameras.xml). The composer builds every scene, so the fixed scene_{23,29,33,43}dof.xml, scene_23dof_ah_d455.xml, g1_23dof_ah_d455.xml and g1_29dof_with_hand_cameras.xml are removed; it adds Dex1's wrist cameras to Dex3 itself. build_g1_ah_model.py is split into sim/pan_tilt_head.py and sim/amazing_hand.py (runtime parts, absolute mesh paths) and tools/build_forearm_meshes.py; build_gripper_model.py becomes tools/build_dex1_model.py and only writes the Dex1 MJCF/URDF. Both tools reproduce the committed files (only the model names changed), and the composed models are unchanged.5896a2a -
feat: compose any body / end effector / head at load time
sim/model_builder.py builds the scene from the bare 29dof/23dof body, an end effector and the head, so every end effector fits either body: rubber_hand (stock passive hand, the base model as is), none (bare wrist), dex1, dex3 (parts of the validated gripper/hand models) and amazing_hand (build_g1_ah_model's graft). Each is defined in the 29dof wrist-yaw frame and mounted there on 29dof, and at the wrist pitch+yaw offsets (+0.084 m) on the 23dof wrist-roll link. Without the rubber hand the wrist gets the bare inertia; the pan/tilt head is shifted into the 29dof torso frame when needed. DDS actuators keep the Hub's interleaved order for motor_effort_limit_list. model_config accepts any combination (dummy is now an alias of rubber_hand; none means a bare wrist) and SimHeadHandDevice serves only the head/hand motors the model has. build_g1_ah_model reads the AmazingHand MJCF from assets/amazing_hand/.6964f84 -
refactor: import the head/hand bridge from lerobot.robots.unitree_g1
cea1831
-
Name the head and hand joints in the G1 MJCF style, matching lerobot's Unitree-style motor names
Head joints/actuators: xl330_joint -> head_yaw_joint, d455_joint -> head_pitch_joint. Hand joints/actuators are named by Feetech servo ID: {side}_hand_finger{i}_motor{j} -> left_hand_motor11_joint..left_hand_motor18_joint and right_hand_motor1_joint..right_hand_motor8_joint. SimHeadHandDevice maps lerobot's kHeadYaw / kLeftHandMotor11 names onto them (mjcf_joint_name). Link names keep the lab URDF's part names. The model is regenerated with build_g1_ah_model.py --head-meshes: the unchanged generator reproduces the previous XML byte for byte, and the new one differs only by the renamed joints/actuators. Requires the matching lerobot (feat/g1_ah_d455, head/hand rename).ad37865
-
Add the 23dof + D455 pan/tilt head + AmazingHand variant (default) with the sim head/hand ZMQ bridge
Verified signature2abbee4 -
Add DualShock 4 joystick mapping, JOYSTICK_* env overrides, LICENSE and third-party notices
Verified signature8af04ad -
Allow make_env options via UNITREE_G1_MUJOCO_* environment variables
Verified signature0cddf57 -
Hydrate the snapshot from the repo env.py was fetched from
Verified signature0fed215 -
Import lerobot/unitree-g1-mujoco@68459ed6 + 23dof (rev_1_0) body variant, defaults BODY=23dof END_EFFECTOR=dummy
Verified signature257dded