PICO VR Whole-body Teleop#
Full whole-body teleoperation using PICO VR headset and controllers. To teleop, use the option --input-type zmq_manager during deployment. The zmq_manager input type switches between a planner mode (locomotion commands via ZMQ) and a streamed motion mode (full-body SMPL poses from PICO).
Safety Warning
Whole-body teleoperation involves fast, agile motions. Always maintain a clear safety zone and keep a safety operator at the keyboard ready to trigger an emergency stop (O in the C++ terminal, or A+B+X+Y on the PICO controllers).
You must wear tight-fitting pants or leggings to guarantee line-of-sight for the foot trackers — loose or baggy clothing can make tracking fail unpredictably and may result in dangerous motion.
Video: End-to-end teleoperation walkthrough — PICO calibration, policy engagement, and the robot balancing independently. See the Teleoperation Guide for detailed best practices.
Prerequisites#
Completed the Quick Start — you can run the sim2sim loop.
Completed the VR Teleop Setup — PICO hardware is installed, calibrated, connected, and
.venv_teleopis ready.
Step-by-Step: Teleop in SIM#
Run three terminals to teleoperate the simulated robot.
Terminal 1 — Launch virtual robot in MuJoCo Simulator#
From the repo root:
# bash install_scripts/install_pico.sh
source .venv_teleop/bin/activate
python gear_sonic/scripts/run_sim_loop.py
Terminal 2 — C++ Deployment#
From gear_sonic_deploy/:
cd gear_sonic_deploy
source scripts/setup_env.sh
./deploy.sh sim --input-type zmq_manager
# Wait until you see "Init done"
Note
The --zmq-host flag defaults to localhost, which is correct when both C++ deployment scripts and teleop scripts (Terminal 3) run on the same machine. If the teleop script runs on a different machine, pass --zmq-host <IP-of-teleop-machine>.
Terminal 3 — PICO Teleop Streamer#
From the repo root:
source .venv_teleop/bin/activate
# With full visualization (recommended for first run):
python gear_sonic/scripts/pico_manager_thread_server.py --manager \
--vis_vr3pt --vis_smpl
# Without visualization (for headless / onboard practice):
# python gear_sonic/scripts/pico_manager_thread_server.py --manager
When you turn on the visualization, wait for a window to pop up showing a Unitree G1 mesh with all joints at the default angles. If no window shows up, double-check the PICO’s XRoboToolKit IP configuration in the VR Teleop Setup. If no window shows up and the script says “Waiting for body tracking data” and you have trackers on, then recalibrate your pico trackers.
Your First Teleop Session#
Assume the calibration pose — stand upright, feet together, upper arms at your sides, forearms bent 90° forward (L-shape at each elbow), palms inward. See Calibration Pose for details.
Press A + B + X + Y simultaneously to engage the control policy and run the initial full calibration (
CALIB_FULL).Align your arms with the robot’s current pose, then press A + X to enter full-body SMPL teleop (POSE mode). Move your arms and legs — the robot follows.
Press A + X again to fall back to PLANNER (idle) mode.
Press A + B + X + Y again to stop the robot.
Complete PICO Controls#
Modes & Calibration#
The system has 4 operating modes and 2 calibration types.
Modes:
Mode |
Encoder |
Description |
|---|---|---|
OFF |
– |
Policy not running. Stand in calibration pose, then press A+B+X+Y to start policy. |
POSE |
SMPL |
Whole-body teleop — streaming the SMPL pose from PICO to the C++ deployment side. Your motion will directly map to the robot . |
PLANNER |
G1 |
Locomotion planner active; upper body controller by planner. Joysticks control direction and heading in walking and running modes. |
PLANNER_FROZEN_UPPER |
G1 |
Planner locomotion; upper body frozen at last POSE snapshot. |
VR_3PT |
TELEOP |
Planner locomotion; upper body follows VR 3-point tracking (head + 2 hands). Depends on non-IK-based VR 3-point calibration. |
Calibration types (non-IK workflow for minimal latency):
Type |
What Is Calibrated |
When Triggered |
|---|---|---|
CALIB_FULL |
Head + both wrists against all-zero reference pose. |
Once on first A+B+X+Y (startup). |
CALIB |
Both wrists only against the current robot pose. |
Each switch into VR_3PT via Left Stick Click. |
State Machine#
There are 4 modes and 2 control chains. Each chain forms a triangle: A+X (or B+Y) returns to POSE from both the planner node and its VR_3PT sub-mode.
┌──────────────────────────────────────┐
│ A+B+X+Y (any mode) ──► OFF │
└──────────────────────────────────────┘
Startup:
OFF ──(A+B+X+Y)──► PLANNER ──(A+X)──► POSE
CALIB_FULL
Chain 1 — G1 encoder listens to planner-generated full-body motion: PLANNER
PLANNER ─── L-Stick (+CALIB) ──► VR_3PT
▲ │ ◄─────── L-Stick ───────── │
│ │ │
│A+X │A+X A+X │
│ ▼ ▼
└─ POSE ◄──────────────────────────┘
Chain 2 — G1 encoder listens to planner-generated lower-body motion: PLANNER_FROZEN_UPPER
PLANNER_FROZEN_UPPER ── L-Stick (+CALIB) ──► VR_3PT
▲ │ ◄──────── L-Stick ────────── │
│ │ │
│B+Y │B+Y B+Y │
│ ▼ ▼
└── POSE ◄───────────────────────────────┘
DANGER — Mode-Switching Safety
Before switching into POSE or VR_3PT, always align your body with the robot’s current pose first!!
POSE: The robot instantly snaps to your physical pose. A large mismatch causes sudden, aggressive motion.
VR_3PT: A misaligned calibration produces erratic, dangerous motion as soon as you move your arms. Check more info at section per-switch-calib
VR_3PT Calibration Hint#
The VR_3PT mode depends on accurate calibration. Two calibration events occur:
One-time CALIB_FULL (head + wrists)#
Before pressing A + B + X + Y for the first time, you must stand in the robot’s all-zero reference pose. The system captures your PICO body-tracking frame as the zero-reference for all subsequent motion mapping.
The reference pose:
Stand upright, feet together, looking straight forward.
Upper arms hang straight down, close to your torso.
Forearms bent 90° forward (L-shape at each elbow), palms facing inward.
Tip
Launch the teleop script with --vis_vr3pt to see the robot’s reference pose in a visualization window. Match your body to it before pressing the start combo.
Per-switch CALIB (wrists only)#
Each time you enter VR_3PT via Left Stick Click, the system re-calibrates both wrists against the robot’s current pose. Always align your arms with the robot before clicking.
Below is an example of bad calibration practice — transitioning into VR_3PT without aligning your arms to the robot’s current pose. The robot may not jump immediately, but will exhibit erratic and dangerous motion as soon as you move.
DANGER — Mode-Switching Safety
Before switching into POSE or VR_3PT, always align your body with the robot’s current pose first.
Recovery from bad VR_3PT calibration:
Freeze the upper body — switch back via Left Stick Click.
Re-align your arms with the robot’s current (possibly distorted) pose.
Switch to POSE mode (A+X) to reset.
Below is the recovery procedure — if you accidentally enter a badly calibrated VR_3PT state, freeze the upper body (Left Stick Click back), then switch to POSE mode (A+X) to reset safely.
Quick-Start Cheatsheet#
Action |
Button |
Notes |
|---|---|---|
Start / Stop policy |
A+B+X+Y |
First press: engage + CALIB_FULL. Again: emergency stop → OFF. |
Toggle POSE |
A+X |
Switches between PLANNER ↔ POSE. OR from VR_3PT (entered via PLANNER) → POSE. |
Toggle PLANNER_FROZEN_UPPER |
B+Y |
Switches between POSE ↔ PLANNER_FROZEN_UPPER. OR from VR_3PT (entered via PLANNER_FROZEN_UPPER) → POSE. |
Toggle VR_3PT |
Left Stick Click |
From any Planner mode → VR_3PT (triggers CALIB). Click again to return. |
Hand grasp |
Trigger (per hand) |
Controls the corresponding hand’s grasp. |
Joystick Controls (Planner Modes)#
Active in PLANNER, PLANNER_FROZEN_UPPER, and VR_3PT:
Input |
Function |
|---|---|
Left Stick |
Move direction (forward / backward / strafe) |
Right Stick (horizontal) |
Yaw / heading (continuous accumulation) |
A + B |
Next locomotion mode |
X + Y |
Previous locomotion mode |
Locomotion modes (cycled via A+B / X+Y):
ID |
Mode |
|---|---|
0 |
Idle [DEFAULT] |
1 |
Slow Walk |
2 |
Walk |
3 |
Run |
4 |
Squat |
5 |
Kneel (two legs) |
6 |
Kneel |
7 |
Lying face-down |
8 |
Crawling |
9–16 |
Boxing variants (idle, walk, punches, hooks) |
17 |
Forward Jump |
18 |
Stealth Walk |
19 |
Injured Walk |
Emergency Stop#
Method |
Action |
|---|---|
PICO controllers |
Press A+B+X+Y simultaneously → OFF |
Keyboard (C++ terminal) |
Press |
Step-by-Step: Teleop on Real Robot#
Safety Warning
Only proceed once you can smoothly control the robot in simulation and are comfortable with emergency stops. Terminate any running run_sim_loop.py process first — simultaneous sim and real instances will conflict.
The real-robot workflow uses two terminals (no MuJoCo simulator).
Terminal 1 — C++ Deployment (Real Robot)#
From gear_sonic_deploy/:
cd gear_sonic_deploy
source scripts/setup_env.sh
# 'real' auto-detects the robot network interface (192.168.123.x).
# If auto-detection fails, pass the G1's IP directly:
# ./deploy.sh --input-type zmq_manager <G1-IP>
./deploy.sh real --input-type zmq_manager
# Wait until you see "Init done"
Note
If the teleop script (Terminal 2) runs on a different machine, add --zmq-host <IP-of-teleop-machine> so the C++ side knows where the ZMQ publisher is.
Terminal 2 — PICO Teleop Streamer#
From the repo root:
source .venv_teleop/bin/activate
python gear_sonic/scripts/pico_manager_thread_server.py --manager
# If running offboard with a display, add visualization:
# --vis_vr3pt --vis_smpl
Note
Update the IP in the PICO’s XRoboToolKit app to match this machine before starting.
Follow the same start sequence: calibration pose → A+B+X+Y → A+X for POSE mode. See Complete PICO Controls for all available commands.