Inspect Robots adapters for Unitree G1 arms and Isaac-GR00T policy servers.
Project description
inspect-robots-unitree-g1
Inspect Robots adapters for a standing Unitree G1 with 7-DoF arms and an
Isaac-GR00T PolicyServer. The package registers the g1_arms embodiment and
the gr00t policy. Both declare one absolute 16-D joint-position contract.
The locomotion controller remains responsible for balance, legs, and waist.
This adapter publishes arm targets to rt/arm_sdk and blends them into the
running controller through the weight joint.
Install
Install the package on the G1 adapter machine:
pip install inspect-robots-unitree-g1
pip install "unitree_sdk2py @ git+https://github.com/unitreerobotics/unitree_sdk2_python"
pip install pyzmq msgpack msgpack-numpy opencv-python-headless
A known-good SDK combination is Python 3.12, unitree_sdk2py 1.0.1, and
cyclonedds 0.10.2. If the CycloneDDS wheel is unavailable, build CycloneDDS
from source, set CYCLONEDDS_HOME, then reinstall the Python package.
The adapter machine must be PC2 or a tethered Linux host with layer-2 access
to 192.168.123.0/24. Run a compatible raw-JPEG ZMQ image server for the head
D435i on PC2. The builtin reader uses a conflated SUB socket. Inject
camera_reader when your image server uses another protocol.
Run Isaac-GR00T on the GPU machine with its PolicyServer and the G1 full-body modality checkpoint. At the pinned API seam, this command loads the checkpoint and listens on port 5555:
export GR00T_CHECKPOINT=/path/to/your/g1-checkpoint
export GR00T_EMBODIMENT_TAG=your_checkpoint_g1_tag
python - <<'PY'
import os
from gr00t.policy.gr00t_policy import Gr00tPolicy
from gr00t.policy.server_client import PolicyServer
policy = Gr00tPolicy(
embodiment_tag=os.environ["GR00T_EMBODIMENT_TAG"],
model_path=os.environ["GR00T_CHECKPOINT"],
device="cuda:0",
)
PolicyServer.start_server(policy, port=5555)
PY
Use the embodiment tag advertised by that checkpoint. This package intentionally does not depend on Isaac-GR00T itself.
Preflight
Preflight checks declarations without connecting to hardware or a server:
inspect-robots-unitree-g1-preflight --dry-run
inspect-robots-unitree-g1-preflight --task cubepick-reach --json --dry-run
The JSON form includes dry_run. A green result proves dimensions, semantics,
cameras, state keys, and optional scene realizability. It cannot prove action
relativity, hand polarity, network reachability, or safe physical clearance.
Run on hardware
Example config.ini:
[policy]
name = gr00t
[policy.args]
host = 192.168.123.10
port = 5555
actions_are_relative = false
[embodiment]
name = g1_arms
[embodiment.args]
iface = eth0
hand_type = dex3
cam_server_address = tcp://192.168.123.164:5556
unattended = false
Then use the normal Inspect Robots run or eval command for your task. The policy server defaults to port 5555. The camera defaults to port 5556 so the two services do not collide.
Safety
Warning: A G1 arm-sdk target and actual-pose mismatch during an abrupt weight change can snap the arms at high speed. Never replace the measured-pose weight ramp with a direct weight flip.
On the first reset, the adapter reads the observed arm pose, seeds every commanded target from it, ramps arm-sdk weight from 0 to 1 while holding that pose, then streams to the zero home pose. Later resets read and reseed from the fresh pose before streaming home, with no weight change.
Close first opens both hands. It then streams the arms to rest_pose, or to
the pose observed at close start when no rest pose is configured. Finally it
ramps weight from 1 to 0 and disconnects. Disconnect is attempted even when a
publish or ramp fails.
Warning: No public arm-sdk firmware watchdog is documented. If a process dies while weight is 1, the controller can keep holding its last target. The adapter registers both an
atexithook and a SIGTERM handler. SIGKILL cannot be intercepted. Keep an operator holding the remote within reach for every run.
Remote L1+A enters damping mode. The robot goes limp and physically sinks,
so the operator must also be ready to support the robot and protect nearby
people and objects.
Warning: Stock Isaac-GR00T at the pinned N1.7 seam decodes relative arm outputs to absolute physical units on the server. Keep
actions_are_relative=falsefor that server. Set it to true only for an older or custom server that returns offsets. A mismatch cannot be detected by compatibility checks and can cause runaway targets. Staff the stop control and slow-jog every new server build.
When relative conversion is enabled, every chunk row is added independently to the same observed arm anchor. It is never cumulatively summed, and the hand slots are never modified.
Warning:
control_hzmust match the checkpoint data frame rate. A compatible shape does not prove compatible timing. Verify the dataset rate before motion.
Before the first grasp, bench-verify Dex1 polarity at low speed. The cited xr_teleoperate source maps 0 rad to closed and 5.4 rad to open, so this package maps normalized 1 to 5.4 rad. Hardware revisions and calibration can differ.
Always run preflight, clear the workspace, verify camera orientation, inspect the measured pose, and perform a slow single-joint jog before policy control.
Configuration
G1 embodiment
| Field | Default | Meaning |
|---|---|---|
iface |
eth0 |
DDS network interface, or None for default routing |
hand_type |
dex3 |
dex1 gripper or dex3 three-finger hand |
control_hz |
10 |
Framework action rate |
stream_hz |
50 |
Synchronous arm publish rate |
max_joint_speed |
3.0 |
Per-joint hard speed cap in rad/s |
weight_ramp_s |
2.0 |
Blend-up and blend-down duration |
kp_arm, kd_arm |
60, 1.5 |
Shoulder and elbow gains |
kp_wrist, kd_wrist |
40, 1.5 |
Conservative package wrist gains |
home_pose |
zero arms, open hands | Reset target |
rest_pose |
None |
Close target, or measured close-start pose |
dex1_stroke |
5.4 |
Full open motor stroke in radians |
dex1_max_speed |
2.7 |
Dex1 motor speed limit in rad/s |
hand_deadband |
0.05 |
Normalized on-change publish gate |
dex3_thumb_swing |
0.0 |
Closed-reference thumb0 swing |
cam_server_address |
tcp://192.168.123.164:5556 |
JPEG SUB endpoint |
cam_timeout_s |
5.0 |
Camera receive timeout |
unattended |
false |
Skip readiness and scoring prompts |
The arm limits come from the official 29-DOF G1 URDF, pulled 0.05 radians inward. The official 50 Hz arm example supplies the arm gains. The lower wrist gain is this package's bench-tuned conservative choice.
Dex1 defaults use kp 5.0 and kd 0.05. Dex3 defaults use kp 1.5 and kd 0.2. Dex3 motor ordering differs by side, as required by the Unitree driver. The open pose is zero. Closed reference poses are conservative interior values derived from the left and right dex3_1 URDF limits because xr_teleoperate does not publish fixed grasp poses.
GR00T policy
| Field | Default | Meaning |
|---|---|---|
host |
127.0.0.1 |
PolicyServer host |
port |
5555 |
PolicyServer port |
timeout_s |
15 |
REQ send and receive timeout |
actions_are_relative |
false |
Enable legacy anchor-add conversion |
action_horizon |
16 |
Maximum returned prefix |
replan_interval |
8 |
Inspect Robots chunk metadata |
image_key |
video.ego_view |
Dotted wire template key |
state_keys |
G1 N1.7 mapping | Dotted state source templates |
action_keys |
G1 N1.7 mapping | Returned action assembly templates |
The SourceSpec DSL supports ("packed", start, stop), ("hand", side),
("state", field_key), and ("const", dim, value). Dotted config keys are
split at the first dot. Wire inner keys are unprefixed. Returned actions may
use either unprefixed names or action.-prefixed names. Unknown returned keys,
including locomotion outputs, are ignored.
The 16-D contract
| Slots | Values | Units |
|---|---|---|
| 0 to 6 | left shoulder pitch/roll/yaw, elbow, wrist roll/pitch/yaw | rad |
| 7 | left hand | normalized, 1 open |
| 8 to 14 | right shoulder pitch/roll/yaw, elbow, wrist roll/pitch/yaw | rad |
| 15 | right hand | normalized, 1 open |
The scalar hand contract is a deliberate v1 simplification. Dex3 expands the scalar along a fixed power-grasp path. Per-joint hand actions, locomotion, waist and neck control, 23-DOF G1 arms, GR00T-SONIC, simulation, UnifoLM-VLA, and lerobot-served policy backends are future work.
Development
uv venv
uv pip install -e ".[dev]"
uv run ruff check .
uv run ruff format --check .
uv run mypy
uv run pytest --cov --cov-report=term-missing
Hardware, camera, ZMQ, and server behavior are fully injectable. Package import requires only Inspect Robots and NumPy.
Citation
See CITATION.cff.
License
MIT. See LICENSE.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file inspect_robots_unitree_g1-0.1.0.tar.gz.
File metadata
- Download URL: inspect_robots_unitree_g1-0.1.0.tar.gz
- Upload date:
- Size: 111.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
58032a1bceeaf596893ba3c275946e61f22f06f98eb54efac62a71a03f8d2bed
|
|
| MD5 |
ac7b78fc90f4ba0d50e08c6b8425edb9
|
|
| BLAKE2b-256 |
8ad0e879f6da33225ad2497bc3a936242bf0a95513bb70d6eae61e59bfdcc333
|
Provenance
The following attestation bundles were made for inspect_robots_unitree_g1-0.1.0.tar.gz:
Publisher:
release.yml on robocurve/inspect-robots-unitree-g1
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
inspect_robots_unitree_g1-0.1.0.tar.gz -
Subject digest:
58032a1bceeaf596893ba3c275946e61f22f06f98eb54efac62a71a03f8d2bed - Sigstore transparency entry: 2195587905
- Sigstore integration time:
-
Permalink:
robocurve/inspect-robots-unitree-g1@97db925b8ef2140508af1f698066535b4a0be722 -
Branch / Tag:
refs/heads/main - Owner: https://github.com/robocurve
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@97db925b8ef2140508af1f698066535b4a0be722 -
Trigger Event:
workflow_dispatch
-
Statement type:
File details
Details for the file inspect_robots_unitree_g1-0.1.0-py3-none-any.whl.
File metadata
- Download URL: inspect_robots_unitree_g1-0.1.0-py3-none-any.whl
- Upload date:
- Size: 29.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
50d07cc75206ff06e4a8ae68f18422211320e94a4cde95fafc3fe4719dc68da1
|
|
| MD5 |
83d8dae5ddc3ee8f9023c1c9e0bd651a
|
|
| BLAKE2b-256 |
03ed9ddb34bd777f709b2acc5cf0f8d9b31e0e6d1ad4e6438927248b9e959094
|
Provenance
The following attestation bundles were made for inspect_robots_unitree_g1-0.1.0-py3-none-any.whl:
Publisher:
release.yml on robocurve/inspect-robots-unitree-g1
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
inspect_robots_unitree_g1-0.1.0-py3-none-any.whl -
Subject digest:
50d07cc75206ff06e4a8ae68f18422211320e94a4cde95fafc3fe4719dc68da1 - Sigstore transparency entry: 2195587922
- Sigstore integration time:
-
Permalink:
robocurve/inspect-robots-unitree-g1@97db925b8ef2140508af1f698066535b4a0be722 -
Branch / Tag:
refs/heads/main - Owner: https://github.com/robocurve
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@97db925b8ef2140508af1f698066535b4a0be722 -
Trigger Event:
workflow_dispatch
-
Statement type: