--- id: deployment-operations title: "Deployment & Field Operations" status: established source_sections: "reference/sources/official-quick-start.md, reference/sources/official-user-manual.md, reference/sources/community-robonomics-experience.md" related_topics: [safety-limits, power-system, networking-comms] key_equations: [] key_terms: [ota_update, development_computer, locomotion_computer] images: [] examples: [] open_questions: - "Field transport case specifications" - "Multi-robot coordination capabilities" - "Firmware update procedure (OTA details)" - "Exact firmware version on our robot (V1.0.2 vs V1.0.4+) — test L2+B vs L1+A to determine" --- # Deployment & Field Operations Real-world setup, operation procedures, and field deployment of the G1. ## 1. Initial Setup Procedure Based on official quick start guide and community experience: [T0/T1] ### Unboxing & First Boot 1. Unpack robot and charger from shipping container 2. Install battery (quick-release smart battery connector) 3. Verify battery charge level 4. Power on the robot (short press, then hold 2+ seconds) 5. Wait for system boot (~1 minute for locomotion + development computers) 6. Robot enters **Zero Torque** state (limp) — NOT standing ### R3 Controller: Startup Sequence (Power-On → Regular Mode) [T1] The robot enforces a mandatory state machine. You CANNOT skip steps — each mode transition must happen in order. Button combos differ by firmware version. **State machine:** `Zero Torque (boot) → Damping → Locked Standing → Regular Mode` #### Firmware V1.0.4+ (Newer — L2-based combos) | Step | Button Combo | Result | |------|-------------|--------| | 1 | *(robot boots)* | Zero Torque — all joints limp | | 2 | **Hold L2 + press B** | **Damping** — joints resist movement passively | | 3 | **Hold L2 + press D-pad UP** | **Locked Standing** — robot stands up. **Hold its shoulder for support!** | | 4 | **R2 + A** | **Regular Mode** — locomotion active, ready for teleop | #### Firmware V1.0.2 (Older — L1-based combos) | Step | Button Combo | Result | |------|-------------|--------| | 2 | **Hold L1 + press A** | **Damping** | | 3 | **Hold L1 + press D-pad UP** | **Locked Standing** | | 4 | **R1 + X** | **Regular Mode** | **How to tell which firmware:** Try L2+B first. If it works (joints become stiff), you're on V1.0.4+. If nothing happens, try L1+A (V1.0.2). #### Full Posture Mode Table — Firmware V1.0.4+ [T1] | Mode | Button Combo | Notes | |------|-------------|-------| | Zero Torque | Hold L2 + Y | All joints limp — robot will collapse if standing | | Damping | Hold L2 + B | Passive resistance, safe descent | | Locked Standing | Hold L2 + D-pad UP | Robot stands up autonomously | | Seated | Hold L2 + D-pad LEFT | | | Lying/Standing toggle | Hold L2 + X | | | Squat | Hold L2 + A | | | Debug Mode | Hold L2 + click R2 | For low-level SDK control (robot must be suspended!) | #### Full Posture Mode Table — Firmware V1.0.2 [T1] | Mode | Button Combo | Notes | |------|-------------|-------| | Zero Torque | Hold L1 + B | All joints limp | | Damping | Hold L1 + A | Passive resistance | | Locked Standing | Hold L1 + D-pad UP | Robot stands up | | Seated | Hold L1 + D-pad LEFT | | | Lying/Standing toggle | Hold L1 + X | | | Squat | Hold L1 + D-pad DOWN | | | Debug Mode | Hold L2 + R2 | Same across firmware versions | #### Controls in Regular Mode [T1] | Function | Control | |----------|---------| | Walk forward/backward | Left joystick up/down | | Turn left/right | Right joystick left/right | | Stand/Walk toggle | START | | Step in place | Double-click START | | Low speed mode | Double-click L2 | | High speed mode | Double-click L1 | | Emergency stop (damping) | L2+B (V1.0.4) or L1+A (V1.0.2) | #### Common Mistake: Haptic Rejection Pulses If you press R1+X or R2+A and get haptic pulses, the robot is rejecting the command because you haven't gone through the required intermediate states. Go back to step 2 (Damping) and work forward. ### Network Setup 1. Connect to the robot's WiFi network from your development machine 2. Configure your machine's IP to 192.168.123.x (avoid .161, .164, .20) 3. Verify connectivity by pinging 192.168.123.164 (dev computer) 4. Install CycloneDDS 0.10.2 and unitree_sdk2 on your dev machine 5. Test: Subscribe to `rt/lowstate` to verify DDS data flow ### Software Environment - Install unitree_sdk2 (C++) or unitree_sdk2_python - CycloneDDS 0.10.2 (exact version required) - For ROS2: Install unitree_ros2 package - For simulation: Install unitree_mujoco ## 2. Pre-Operation Checklist Recommended checks before each operation session: [T2 — Best practice from community] - [ ] Battery charge level > 30% - [ ] All joints move freely (no mechanical binding) - [ ] WiFi/Ethernet connectivity confirmed - [ ] DDS communication verified (rt/lowstate receiving data) - [ ] Operating area clear (minimum 2m clearance around robot) - [ ] Safety spotter present with wireless remote / e-stop access - [ ] Recording system active (data logging enabled) - [ ] Emergency procedures reviewed with all personnel present ## 3. Debug Mode (Low-Level Control Access) To gain full low-level joint control (bypassing the stock locomotion controller): [T1 — Weston Robot guide] 1. **Suspend the robot** on a stand or safety harness (it WILL fall without support) 2. Put the robot into **damping state** (Hold L2+B on V1.0.4, or L1+A on V1.0.2) 3. Press **Hold L2 + click R2** on the wireless remote 4. The stock locomotion controller is now disabled 5. You have full control via `rt/lowcmd` for all joints 6. To exit debug mode: power cycle the robot **WARNING:** In debug mode, the robot has ZERO balance. The legs will go limp. This is for development with the robot safely suspended — never activate debug mode while the robot is standing on the ground. ## 4. Operating Procedures ### Standard Workflow 1. Power on and wait for boot completion 2. Verify robot state via `rt/lowstate` 3. Command standing mode via high-level API 4. Execute planned tasks (locomotion, manipulation, etc.) 5. Return to standing mode 6. Command sit/lie down 7. Power off ### Remote Operation via WiFi - Connect to robot WiFi (WiFi 6, 802.11ax) - Use SDK from any machine on 192.168.123.0/24 - Monitor robot state continuously - **Caution:** WiFi latency varies — not recommended for safety-critical real-time control [T2] ### Development on Jetson - SSH into 192.168.123.164 (development computer) - Develop and test code directly on the Jetson Orin NX - Lower latency than WiFi for real-time control - Recommended for production deployments [T1] ## 5. Troubleshooting Common issues and resolutions from community experience: [T2 — Robonomics report + community] | Issue | Likely Cause | Resolution | |-------------------------------|----------------------------------------|-----------------------------------| | No DDS data received | CycloneDDS version mismatch | Install exactly v0.10.2 | | Robot won't stand | Low battery or boot not complete | Charge battery, wait for full boot | | Jerky movements | Control loop rate too low | Ensure publishing at 500 Hz | | WiFi disconnects | Range or interference | Use wired Ethernet connection | | SDK examples fail | Network interface not specified | Add interface param (e.g., enp2s0) | | Motion state topic issues | Known SDK quirk | Check Robonomics blog for details | | Python SDK install fails | CycloneDDS not compiled from source | Build CycloneDDS separately, set CYCLONEDDS_HOME | ## 6. Maintenance ### Firmware Updates - **Method:** OTA (Over-The-Air) update system [T0] - **Current version:** v3.2+ (as of early 2025) - **Notable updates:** - v1.4.5: Training Mode for custom motion capture via Unitree Explore App - v3.2+: Improved walking stability, faster gait transitions, preliminary LLM integration (EDU) ### Hardware Inspection - Inspect joints for unusual noise or binding (regular interval TBD) - Check cable routing through hollow motor shafts - Verify encoder readings match expected ranges - Inspect Dex3-1 hand fingers and tactile sensors (if equipped) - Check battery connector and quick-release mechanism ## 7. Transport & Storage - **Folded dimensions:** 0.69m height when folded for transport [T0] - **Weight:** ~35 kg — requires two people or a wheeled cart for transport [T0] - **Storage:** Remove battery for long-term storage. Store in dry, temperature-controlled environment. [T3 — Best practice] - **Battery storage:** Store LiPo batteries at ~50% charge for long-term storage. Do not store fully charged or fully depleted. [T3 — Standard LiPo practice] ## 8. Useful Resources | Resource | URL / Location | |-----------------------------|-----------------------------------------------------| | Official developer guide | support.unitree.com/home/en/G1_developer | | Quick start guide | support.unitree.com/home/en/G1_developer/quick_start | | Robonomics experience report | reference/sources/community-robonomics-experience.md | | RoboStore startup guide | robostore.com/blogs/news/unitree-g1-startup-guide | | Weston Robot dev guide | docs.westonrobot.com/tutorial/unitree/g1_dev_guide/ | ## 9. GR00T-WBC Deployment on Real G1 (Verified 2026-02-15) [T1] ### Architecture - **GB10** (10.0.0.68) runs GR00T-WBC, sends DDS commands to robot via 192.168.123.100 - **Robot Jetson** (192.168.123.164) runs web control panel (`server.py:8080`) and audio driver — NO stock locomotion controller - **Locomotion MCU** (192.168.123.161) receives `rt/lowcmd`, publishes `rt/lowstate` — no SSH access - SSH to Jetson: `sshpass -p '123' ssh unitree@192.168.123.164` - SSH to GB10: `ssh mitchaiet@10.0.0.68` (password: `Strat3*gb10`) ### Confirmed Hardware Parameters (This Robot) - **mode_machine = 5** (g1_29dof_rev_1_0) — confirmed via 63 DDS samples - **No ai_sport service running** — Jetson only runs server.py and audio driver - When policy deactivates, last PD gains remain active (motors hold position, do NOT actively balance) ### Launch Procedure 1. Start Xvfb: `Xvfb :99 -screen 0 1024x768x24 &` (GLFW needs a display) 2. Launch script `/tmp/launch_groot.sh` in tmux: ```bash cd ~/GR00T-WholeBodyControl && source .venv/bin/activate export LD_LIBRARY_PATH=/opt/ros/jazzy/lib:$LD_LIBRARY_PATH export DISPLAY=:99 export CYCLONEDDS_URI=' ' python3 -u gr00t_wbc/control/main/teleop/run_g1_control_loop.py --no-with-hands --interface real ``` 3. Activate policy: `]` key in tmux 4. Deactivate policy: `o` key in tmux 5. Keyboard: `1/2` height, `5/6` pitch, `w/s/a/d` locomotion, `9/0` IMU offset ±1° ### Known Issues & Fixes Applied | Issue | Root Cause | Fix | |-------|-----------|-----| | GLFW crash on headless GB10 | `simulator_factory.py` eagerly imports mujoco | Made BaseSimulator import lazy + Xvfb :99 | | DDS selects loopback | No CYCLONEDDS_URI set | Set explicit URI with address=192.168.123.100 | | Negative KD bug | `configs.py` line: `MOTOR_KD[14] -= 10` → KD = -5 | Commented out the line | | ONNX actions exceed [-1,1] | Normal RSL-RL behavior — do NOT clip | No clipping needed (NVIDIA reference has none) | | Backward lean bias | **IMU mounting offset** — physical IMU in pelvis is pitched ~6° from sim assumption | Apply quaternion pitch rotation before gravity computation (see IMU Offset section) | | Action clipping wrong | Added np.clip(action,-1,1) based on Isaac Lab issue — caused policy saturation | Removed clipping — NVIDIA reference code does not clip, policy needs full range | | mode_machine hardcoded | GR00T-WBC hardcodes mode_machine=5, should read from robot | Applied PR #11: dynamic detection from rt/lowstate | ### IMU Pitch Offset Calibration [T1 — Verified on this robot] The real G1's pelvis IMU has a physical mounting offset vs what simulation assumes. GR00T-WBC reads raw IMU data via DDS (bypassing the stock controller's calibration), so the policy's reference frame for "upright" is wrong. This causes persistent backward lean that cannot be fixed by PD gain tuning or pitch commands (the balance loop fights back). **Fix:** Rotate the IMU quaternion by a pitch offset before computing gravity orientation in `g1_gear_wbc_policy.py`: ```python # In compute_observation(), before get_gravity_orientation(quat): half = self.imu_pitch_offset / 2.0 pitch_quat = np.array([np.cos(half), 0.0, np.sin(half), 0.0]) # w,x,y,z quat = quat_multiply(pitch_quat, quat) ``` - **Current calibrated value: -6.0° (np.deg2rad(-6.0))** — negative = forward correction - Keys `9`/`0` adjust by ±1° live without relaunching - This is NOT a hack — it's an IMU calibration parameter that GR00T-WBC is missing - Multiple GitHub users (Issues #21, #22, #23) report the same backward lean — likely the same root cause ### PD Gain Tuning History The ONNX policy was trained in sim with gains: `kps: [150,150,150,200,40,40, ...]` Best results achieved with Unitree teleop gains + IMU offset: | Source | Hip pitch | Hip roll | Hip yaw | Knee | Ankle pitch | Ankle roll | Waist | |--------|:-:|:-:|:-:|:-:|:-:|:-:|:-:| | GR00T-WBC sim (trained) | 150 | 150 | 150 | 200 | 40 | 40 | 250 | | Unitree SDK example | 60 | 60 | 60 | 100 | 40 | 40 | 60/40/40 | | Unitree xr_teleoperate | 300 | 300 | 300 | 300 | 80 | 80 | 300 | | **Current best (teleop + IMU offset)** | **300** | **300** | **300** | **300** | **80** | **80** | **300** | ## Key Relationships - Governed by: [[safety-limits]] (operational constraints, pre-op checks) - Constrained by: [[power-system]] (battery runtime limits deployment duration) - Requires: [[networking-comms]] (WiFi/Ethernet for remote operation) - Uses: [[sdk-programming]] (SDK for all robot interaction)