Deploy the HuMI Policy on G1

April 21, 2026 ยท View on GitHub

System Overview

  • High-Level Policy Server runs inference for the high-level policy. It takes the current observation as input and outputs action chunks. Its code is in humi_high_level_policy/run_g1_policy_server.py.
  • High-Level Policy Client formats observations from low-level proprioception and wrist cameras, sends them to the high-level policy server, receives action chunks, interpolates them into per-step actions, and forwards those actions to the low-level controller. Its code is in humi_deploy_high_level/scripts/run_g1_policy_client.py.
  • Low-Level Controller runs on G1's onboard computer. It takes per-step actions from the high-level policy client together with proprioceptive data from the robot SDK and outputs joint position commands to the robot. Its code is in humi_deploy_low_level/main.py.
  • HTC Tracker Interface runs on a Windows PC. It receives HTC tracker data and sends keypoint poses to the low-level controller. Its code is in humi_data_collection/packages/htc_interface/src/htc_scripts/send_pose.py.

Deployment Instructions

1. Set Up the HTC Tracker Interface

Install the HTC tracker interface on a Windows PC by following the instructions in humi_data_collection/README.md.

Then update humi_data_collection/packages/htc_interface/src/tracker_config_ground.json so that two trackers are assigned the roles root and ground:

  • The root tracker is attached to the robot's pelvis.
  • The ground tracker is placed on the floor.

After the trackers are connected, run send-pose to publish tracker poses to the low-level controller:

send-pose
  --port 1234
  --frequency 120
  --roles-to-send root
  --config-path .\src\tracker_config_ground.json
  --offset-ground

Important arguments:

  • --config-path: Path to the tracker-role configuration JSON. For deployment, this file should define at least root and ground.
  • --roles-to-send: Tracker roles to publish over ZMQ. For the current deployment setup, send root.
  • --offset-ground: When enabled, the script uses the tracker labeled ground to offset poses so the published root pose is expressed relative to the floor. Keep this enabled for normal deployment.
  • --port: ZMQ publish port. The low-level controller must subscribe to the same port.
  • --frequency: Pose publish rate in Hz. The default is 120.

2. Launch the High-Level Policy Server and Client

Launch both the high-level policy server and the high-level policy client on the Linux workstation.

Choose the policy server host and ports once, then derive the endpoints from those values. Use the same values for both the server and the client:

<policy_server_host> = 127.0.0.1
<policy_obs_port> = 5555
<policy_action_port> = 5556
<policy_obs_endpoint> = tcp://<policy_server_host>:<policy_obs_port>
<policy_action_endpoint> = tcp://<policy_server_host>:<policy_action_port>
<robot_ip> = 192.168.1.107
<robot_port> = 4321

First, launch the high-level policy server in one terminal:

cd humi_high_level_policy
uv run run_g1_policy_server.py \
  --checkpoint <path-to-checkpoint-or-run-dir> \
  --obs-endpoint <policy_obs_endpoint> \
  --action-endpoint <policy_action_endpoint>

See humi_high_level_policy/README.md for more details on the policy server.

Common policy server communication options:

  • --obs-endpoint: ZeroMQ endpoint used by the server to receive observations. This is typically built from <policy_server_host> and <policy_obs_port>.
  • --action-endpoint: ZeroMQ endpoint used by the server to publish actions. This is typically built from <policy_server_host> and <policy_action_port>.

Then launch the high-level policy client in a second terminal:

cd humi_deploy_high_level
uv run scripts/run_g1_policy_client.py humi-squat \
  --policy-config.obs-endpoint <policy_obs_endpoint> \
  --policy-config.action-endpoint <policy_action_endpoint> \
  --robot-config.robot-ip <robot_ip> \
  --robot-config.robot-port <robot_port> \
  --output-dir data/g1_policy_client/custom_run

Common low-level controller communication options:

  • --robot-config.robot-ip: IP address of the low-level controller's ZMQ server.
  • --robot-config.robot-port: Port used by the low-level controller's ZMQ server.

Important alignment requirements:

  • The client and server communication settings must match exactly. --policy-config.obs-endpoint must be the same as the server's --obs-endpoint, and --policy-config.action-endpoint must be the same as the server's --action-endpoint.
  • If you change <policy_server_host>, <policy_obs_port>, or <policy_action_port> on one side, update the other side so both resolve to the same endpoint values.
  • --robot-config.robot-ip and --robot-config.robot-port must point to the same low-level controller instance used by the rest of the deployment.

Once the client starts, it waits for connections from both the policy server and the low-level controller. After the connections are established, you can view camera observations in OpenCV windows and inspect high-level policy outputs in viser.

The client does not send policy actions to the robot until you press c to start an episode. After that, the client forwards high-level policy actions to the low-level controller, which then sends commands to the robot. Press s to stop the episode and save the data, or press q to quit the program.

See humi_deploy_high_level/README.md for more details on the high-level policy client.

3. Launch the Low-Level Controller

Finally, on G1's onboard computer, launch the low-level controller from humi_deploy_low_level with:

python main.py \
  --reference highlevel \
  --onnx_path model/<LOW_LEVEL_POLICY>.onnx \
  --odometry_ip <WINDOWS_HTC_PC_IP:1234> \
  --highlevel_ip <LINUX_WORKSTATION_IP:1234> \
  --proprio_port 4321

Important arguments:

  • --onnx_path: Path to the exported low-level ONNX policy on the onboard computer.
  • --odometry_ip: ZMQ endpoint from the HTC tracker interface in Step 1, including both IP and port, e.g. <WINDOWS_HTC_PC_IP>:1234.
  • --highlevel_ip: ZMQ endpoint from the high-level client in Step 2, including both IP and port, e.g. <LINUX_WORKSTATION_IP>:1234.
  • --proprio_port: Local port used by the low-level controller to publish proprioceptive keypoints and DoFs back to the high-level client. 4321 is the default value and should match --robot-config.robot-port in the high-level client.

Runtime flow:

  1. Start the HTC tracker interface, the high-level server, and the high-level client first.
  2. Start main.py on the onboard computer; the robot will move to the initial pose.
  3. Press X on the handheld controller to enter policy control.
  4. Press c in the high-level client to start rollout.
  5. Press B on the handheld controller for emergency stop.

See humi_deploy_low_level/README.md for more details on the low-level controller.