Skip to content

G1 + Brainco Revo2 hands: setup guide, CycloneDDS fix, LeRobot dataset conversion, DGX Spark support#47

Open
brownwa wants to merge 13 commits into
unitreerobotics:mainfrom
brownwa:unifolm-wbt-dataset
Open

G1 + Brainco Revo2 hands: setup guide, CycloneDDS fix, LeRobot dataset conversion, DGX Spark support#47
brownwa wants to merge 13 commits into
unitreerobotics:mainfrom
brownwa:unifolm-wbt-dataset

Conversation

@brownwa

@brownwa brownwa commented Apr 6, 2026

Copy link
Copy Markdown

Summary

This PR consolidates all work from brownwa/unifolm-world-model-action branches docs/brainco-setup-guide, docs/cyclonedds-install-fix, and fix/lerobot-dataset-conversion (previously submitted as PRs #43 and #45) into a single clean branch.

What's included

Unitree G1 + Brainco Revo2 Five-Finger Hands support (extends §2.1 of unitree_deploy/README.md):

  • Architecture overview: ROS2 stark_nodebrainco_bridge.py TCP bridge ↔ unitree_deploy client
  • Step-by-step setup for g1_brainco robot type (new ros2_stark_ws, g1brainco conda env)
  • Documents G1-specific hardware: 5 real arm DOFs per arm (no wrist pitch/yaw), Brainco hand DOF layout, USB port mapping
  • Fix: Terminal 1 ros2 command corrected to ros2 launch ros2_stark_controller stark_launch.py
  • Fix: Python version constraint in pyproject.toml (==3.10.18>=3.10) for robot-side install
  • Fix: libgomp preload workaround for pinocchio on aarch64

g1_brainco robot client fixes (unitree_deploy/scripts/robot_client.py):

  • ZERO_ACTION dim corrected 26→12 (matches 12-dim ee_action the model was trained on)
  • _g1_brainco_qpos_to_ee_state: maps 26-DOF robot qpos → 12-dim ee_state for model conditioning
  • _g1_brainco_ee_action_to_qpos: maps 12-dim predicted ee_action → 26-DOF qpos for robot execution
  • G1_29_ArmController startup fixes: q_target initialised from init_pose (not zeros) to stop startup jerk; INIT_POSE aligned to G1 Ready Mode arm position

CycloneDDS install fix (unitree_deploy/README.md Troubleshooting section):

  • Documents CYCLONEDDS_HOME export needed before pip install -e . on Unitree G1

LeRobot v3 → unifolm-wma dataset conversion (scripts/prepare_lerobot_dataset.py):

  • HuggingFace datasets from unitreerobotics are published in LeRobot v3.0 parquet format; WMAData expects a different layout (CSV + H5 transitions + per-episode videos)
  • One-time conversion script produces the exact directory layout DataModuleFromConfig.setup() requires
  • Supports --camera_key, --action_key, --state_key, --instruction flags for any dataset

NVIDIA DGX Spark / Blackwell GPU support (SPARK_SETUP.md, real_eval_server.py, model code):

  • SDPA fallback for xformers on Blackwell architecture
  • Replaced deprecated torchvision video I/O with imageio
  • Added SPARK_SETUP.md with full DGX Spark environment setup

Test plan

  • Follow unitree_deploy/README.md §2.1 on a G1 + Brainco Revo2 — confirm stark_node connects via ros2 launch ros2_stark_controller stark_launch.py
  • Run python scripts/prepare_lerobot_dataset.py --dataset_dir ~/.cache/.../G1_WBT_Brainco_Pickup_Pillow/snapshots/<hash> --dataset_name G1_WBT_Brainco_Pickup_Pillow — confirm WMAData loads 300 samples
  • Start real_eval_server.py on DGX Spark — confirm server starts and serves on NVIDIA B200

Related issues

Closes #46 (partial — the domain-gap / inference quality issues are upstream model limitations, not setup issues)

🤖 Generated with Claude Code

brownwa and others added 12 commits March 22, 2026 23:58
Brings fix/lerobot-dataset-conversion's prepare_lerobot_dataset.py onto
the spark-dgx-fixes branch so DGX Spark users have it available.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
On systems where CycloneDDS is installed but not on the default system
path (e.g. Unitree G1 which ships it in ~/cyclonedds_ws), pip fails to
build the cyclonedds Python wheel with "Could not locate cyclonedds".

Add a Troubleshooting entry explaining how to set CYCLONEDDS_HOME to
the install prefix so the build can find the library.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Adds end-to-end support for the Brainco Revo2 five-finger dextrous
hands on a G1 23-DOF robot (no wrist pitch/yaw, 1 waist DOF) as an
alternative to the Dex_1 gripper.

Architecture: the stark_node (ROS2, g1brainco env) owns hardware I/O;
a new brainco_bridge.py TCP server bridges it to unitree_deploy
(Python 3.10, no ROS2) via newline-delimited JSON on localhost:9877.

Changes:
- scripts/brainco_bridge.py: ROS2 bridge node (run in g1brainco env)
- endeffector/brainco_hand.py: Brainco_DualHand_Controller (12 DOFs)
- endeffector/configs.py: BrancoDualHandConfig dataclass
- endeffector/utils.py: wire brainco_dual type into factory
- robot/robot_configs.py: g1_brainco RobotConfig + factories
- scripts/robot_client.py: INIT_POSE / ZERO_ACTION / CAM_KEY entries

USB port mapping (params_v2_double.yaml): left=/dev/ttyUSB1, right=/dev/ttyUSB2
Action space: 14 arm DOFs + 12 hand DOFs = 26 total

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
real_eval_server.py defaulted to 127.0.0.1, blocking connections from
the robot on the same LAN. Changed default to 0.0.0.0 and added
--host/--port CLI args.

robot_client.py HOST is now read from INFERENCE_SERVER_HOST env var
(defaults to 127.0.0.1 for local use).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
All-zeros caused violent elbow extension (~56° to 0°) on startup.
Values read from robot's reported state in Ready Mode.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
go_start() (called from connect()) and env.step() were competing:
go_start() drove arms to np.zeros(14) while env.step() tried to hold
Ready Mode position, causing violent oscillation on startup.

Fix: set G1ArmConfig.init_pose in brainco_dual_arm_default_factory to
the observed G1 Ready Mode position (elbow ~56°, shoulder ~0.29 rad),
matching INIT_POSE['g1_brainco'] exactly so both targets agree.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
self.q_target was hardcoded to np.zeros(14), so after go_start() drove
the arms to init_pose the main control loop immediately scheduled
waypoints back to zero — causing constant motor whirring when init_pose
is non-zero (e.g. g1_brainco Ready Mode position).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Documents the full setup process for running the Unitree G1 23-DOF robot
with Brainco Revo2 dexterous hands, including:
- TCP bridge architecture (ROS2 stark_node ↔ unitree_deploy via localhost:9877)
- Three-terminal startup sequence (stark_node, brainco_bridge, robot_client)
- INFERENCE_SERVER_HOST env var for remote inference server
- LD_PRELOAD fix for pinocchio libgomp.so.1 on aarch64
- g1_brainco robot type: 26-DOF action space (14 arm + 12 hand)
- Troubleshooting: bridge connection, arm whirring, normalizer mismatch

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…brainco robot_client

- configs/inference/world_model_decision_making.yaml: revert data_dir and
  dataset_and_weights back to upstream-main placeholder values
- scripts/run_real_eval_server.sh: revert model_name/ckpt/res_dir/datasets
  back to upstream-main placeholders; keep python3 -u for unbuffered output
- unitree_deploy/README.md: fix Terminal 1 ros2 command from
  'ros2 launch stark_bringup brainco_launch.py' to
  'ros2 launch ros2_stark_controller stark_launch.py' (correct package name)
- unitree_deploy/scripts/robot_client.py: fix g1_brainco ZERO_ACTION dim
  (26→12 to match ee_action training dim); add _g1_brainco_qpos_to_ee_state
  and _g1_brainco_ee_action_to_qpos helpers so the client correctly maps
  between the 26-DOF robot qpos and the 12-dim ee_state/ee_action the model
  was trained on
- .gitignore: exclude waheed_datasets/ directory

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Ready Mode (Locked Standing) causes competing control signals between
the G1's built-in motion controller and unitree_deploy, producing
startup jerks and whirring. Switching to Development Mode gives
unitree_deploy exclusive joint control and stops the oscillation.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

G1 + Brainco Revo2 five-finger hands: setup guide and fixes

1 participant