thanhnc19 commited on
Commit
15b8951
·
verified ·
1 Parent(s): d9fc053

Upload folder using huggingface_hub

Browse files
This view is limited to 50 files because it contains too many changes.   See raw diff
Files changed (50) hide show
  1. .dockerignore +30 -0
  2. .gitattributes +3 -0
  3. .gitignore +32 -0
  4. .gitmodules +4 -0
  5. .vscode/browse.vc.db +3 -0
  6. .vscode/c_cpp_properties.json +22 -0
  7. .vscode/settings.json +35 -0
  8. LICENSE +24 -0
  9. README.md +243 -3
  10. docker/Dockerfile +63 -0
  11. docker/docker-compose.yml +37 -0
  12. docker/entrypoint.sh +9 -0
  13. go2_control/go2_control/__init__.py +0 -0
  14. go2_control/go2_control/keyboard_teleop.py +150 -0
  15. go2_control/package.xml +21 -0
  16. go2_control/resource/go2_control +0 -0
  17. go2_control/setup.cfg +4 -0
  18. go2_control/setup.py +25 -0
  19. go2_interfaces/CMakeLists.txt +61 -0
  20. go2_interfaces/msg/AudioData.msg +2 -0
  21. go2_interfaces/msg/BmsCmd.msg +2 -0
  22. go2_interfaces/msg/BmsState.msg +9 -0
  23. go2_interfaces/msg/Error.msg +2 -0
  24. go2_interfaces/msg/Go2Cmd.msg +1 -0
  25. go2_interfaces/msg/Go2FrontVideoData.msg +8 -0
  26. go2_interfaces/msg/Go2Move.msg +3 -0
  27. go2_interfaces/msg/Go2RpyCmd.msg +3 -0
  28. go2_interfaces/msg/Go2State.msg +12 -0
  29. go2_interfaces/msg/HeightMap.msg +15 -0
  30. go2_interfaces/msg/IMU.msg +5 -0
  31. go2_interfaces/msg/InterfaceConfig.msg +3 -0
  32. go2_interfaces/msg/LidarState.msg +17 -0
  33. go2_interfaces/msg/LowCmd.msg +15 -0
  34. go2_interfaces/msg/LowState.msg +22 -0
  35. go2_interfaces/msg/MotorCmd.msg +7 -0
  36. go2_interfaces/msg/MotorCmds.msg +1 -0
  37. go2_interfaces/msg/MotorState.msg +11 -0
  38. go2_interfaces/msg/MotorStates.msg +1 -0
  39. go2_interfaces/msg/PathPoint.msg +7 -0
  40. go2_interfaces/msg/Req.msg +2 -0
  41. go2_interfaces/msg/Res.msg +3 -0
  42. go2_interfaces/msg/SportModeCmd.msg +13 -0
  43. go2_interfaces/msg/SportModeState.msg +17 -0
  44. go2_interfaces/msg/TimeSpec.msg +5 -0
  45. go2_interfaces/msg/UwbState.msg +19 -0
  46. go2_interfaces/msg/UwbSwitch.msg +1 -0
  47. go2_interfaces/msg/VoxelHeightMapState.msg +14 -0
  48. go2_interfaces/msg/VoxelMapCompressed.msg +21 -0
  49. go2_interfaces/msg/WebRtcReq.msg +10 -0
  50. go2_interfaces/msg/WirelessController.msg +5 -0
.dockerignore ADDED
@@ -0,0 +1,30 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # colcon workspace artifacts (rebuilt inside the image)
2
+ build/
3
+ install/
4
+ log/
5
+
6
+ # git
7
+ .git/
8
+ .gitignore
9
+
10
+ # python
11
+ **/__pycache__/
12
+ *.py[cod]
13
+ *.egg-info/
14
+ .pytest_cache/
15
+
16
+ # runtime output, not source
17
+ vla_logs/
18
+ navila/result/
19
+
20
+ # heavy weights (fetched separately, not committed) — small in-repo YOLO
21
+ # weights under vlm/ are intentionally NOT excluded here, they ship with the image.
22
+ navila-ckpt/
23
+ *.safetensors
24
+ *.pth
25
+
26
+ # editor / misc
27
+ .vscode/
28
+ .DS_Store
29
+ .superpowers/
30
+ docs/
.gitattributes CHANGED
@@ -33,3 +33,6 @@ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
33
  *.zip filter=lfs diff=lfs merge=lfs -text
34
  *.zst filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
 
 
 
 
33
  *.zip filter=lfs diff=lfs merge=lfs -text
34
  *.zst filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
36
+ .vscode/browse.vc.db filter=lfs diff=lfs merge=lfs -text
37
+ go2_robot_sdk/dae/base.dae filter=lfs diff=lfs merge=lfs -text
38
+ go2_robot_sdk/meshes/base.STL filter=lfs diff=lfs merge=lfs -text
.gitignore ADDED
@@ -0,0 +1,32 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Python
2
+ __pycache__/
3
+ *.py[cod]
4
+ *.egg-info/
5
+ .pytest_cache/
6
+ *.so
7
+
8
+ # ROS build/install artifacts
9
+ build
10
+ log
11
+ install
12
+ .vscode
13
+ .env
14
+ .DS_Store
15
+ go2_robot_sdk/.coverage
16
+ go2_robot_sdk/coverage.xml
17
+
18
+ # Runtime logs / dữ liệu sinh ra
19
+ vla_logs/
20
+ navila/result/
21
+ *.log
22
+ *.ply
23
+ *.pgm
24
+ *.pcd
25
+
26
+ # Checkpoint / trọng số lớn (tải lại bằng script; KHÔNG đẩy lên git)
27
+ navila-ckpt/
28
+ *.safetensors
29
+ *.pth
30
+
31
+ .superpowers/
32
+ docs/
.gitmodules ADDED
@@ -0,0 +1,4 @@
 
 
 
 
 
1
+ [submodule "go2_robot_sdk/external_lib/aioice"]
2
+ path = go2_robot_sdk/external_lib/aioice
3
+ url = https://github.com/legion1581/aioice.git
4
+ branch = go2
.vscode/browse.vc.db ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:356be10c121d584a032686b7ddb2b0916ede175104aa86b128b274e4e089b032
3
+ size 1325277184
.vscode/c_cpp_properties.json ADDED
@@ -0,0 +1,22 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "configurations": [
3
+ {
4
+ "browse": {
5
+ "databaseFilename": "${workspaceFolder}/.vscode/browse.vc.db",
6
+ "limitSymbolsToIncludedHeaders": false
7
+ },
8
+ "includePath": [
9
+ "/home/thanhnc/unige_ws/install/spot_sar_msgs/include/**",
10
+ "/opt/ros/jazzy/include/**",
11
+ "/home/thanhnc/Go2-Nav_System/go2_navigation/include/**",
12
+ "/usr/include/**"
13
+ ],
14
+ "name": "ros2",
15
+ "intelliSenseMode": "gcc-x64",
16
+ "compilerPath": "/usr/bin/gcc",
17
+ "cStandard": "gnu11",
18
+ "cppStandard": "c++17"
19
+ }
20
+ ],
21
+ "version": 4
22
+ }
.vscode/settings.json ADDED
@@ -0,0 +1,35 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "ROS2.distro": "jazzy",
3
+ "python.autoComplete.extraPaths": [
4
+ "/home/thanhnc/unige_ws/build/spot_sar_sim",
5
+ "/home/thanhnc/unige_ws/install/spot_sar_sim/lib/python3.12/site-packages",
6
+ "/home/thanhnc/unige_ws/build/spot_sar_executive",
7
+ "/home/thanhnc/unige_ws/install/spot_sar_executive/lib/python3.12/site-packages",
8
+ "/home/thanhnc/unige_ws/build/spot_sar_planning",
9
+ "/home/thanhnc/unige_ws/install/spot_sar_planning/lib/python3.12/site-packages",
10
+ "/home/thanhnc/unige_ws/build/spot_sar_perception",
11
+ "/home/thanhnc/unige_ws/install/spot_sar_perception/lib/python3.12/site-packages",
12
+ "/home/thanhnc/unige_ws/build/spot_sar_nav",
13
+ "/home/thanhnc/unige_ws/install/spot_sar_nav/lib/python3.12/site-packages",
14
+ "/home/thanhnc/unige_ws/install/spot_sar_msgs/lib/python3.12/site-packages",
15
+ "/home/thanhnc/unige_ws/build/spot_sar_bringup",
16
+ "/home/thanhnc/unige_ws/install/spot_sar_bringup/lib/python3.12/site-packages",
17
+ "/opt/ros/jazzy/lib/python3.12/site-packages"
18
+ ],
19
+ "python.analysis.extraPaths": [
20
+ "/home/thanhnc/unige_ws/build/spot_sar_sim",
21
+ "/home/thanhnc/unige_ws/install/spot_sar_sim/lib/python3.12/site-packages",
22
+ "/home/thanhnc/unige_ws/build/spot_sar_executive",
23
+ "/home/thanhnc/unige_ws/install/spot_sar_executive/lib/python3.12/site-packages",
24
+ "/home/thanhnc/unige_ws/build/spot_sar_planning",
25
+ "/home/thanhnc/unige_ws/install/spot_sar_planning/lib/python3.12/site-packages",
26
+ "/home/thanhnc/unige_ws/build/spot_sar_perception",
27
+ "/home/thanhnc/unige_ws/install/spot_sar_perception/lib/python3.12/site-packages",
28
+ "/home/thanhnc/unige_ws/build/spot_sar_nav",
29
+ "/home/thanhnc/unige_ws/install/spot_sar_nav/lib/python3.12/site-packages",
30
+ "/home/thanhnc/unige_ws/install/spot_sar_msgs/lib/python3.12/site-packages",
31
+ "/home/thanhnc/unige_ws/build/spot_sar_bringup",
32
+ "/home/thanhnc/unige_ws/install/spot_sar_bringup/lib/python3.12/site-packages",
33
+ "/opt/ros/jazzy/lib/python3.12/site-packages"
34
+ ]
35
+ }
LICENSE ADDED
@@ -0,0 +1,24 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ BSD 2-Clause License
2
+
3
+ Copyright (c) 2024, RoboVerse community
4
+
5
+ Redistribution and use in source and binary forms, with or without
6
+ modification, are permitted provided that the following conditions are met:
7
+
8
+ 1. Redistributions of source code must retain the above copyright notice, this
9
+ list of conditions and the following disclaimer.
10
+
11
+ 2. Redistributions in binary form must reproduce the above copyright notice,
12
+ this list of conditions and the following disclaimer in the documentation
13
+ and/or other materials provided with the distribution.
14
+
15
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
16
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
19
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
21
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
22
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
23
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
README.md CHANGED
@@ -1,3 +1,243 @@
1
- ---
2
- license: bsd-2-clause
3
- ---
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Unitree Go2 — ROS 2 Navigation, Mapping and Low-level Control & Basic Vision-Language-Action
2
+
3
+ A ROS 2 workspace for the Unitree Go2 quadruped that pairs a classic navigation
4
+ stack (SLAM Toolbox mapping + Nav2) with a **Vision-Language-Action (VLA)** layer:
5
+ the robot can be driven by typing a natural-language instruction instead of a
6
+ joystick or a Nav2 goal. Two interchangeable VLA brains are included — a local
7
+ **Qwen2.5-VL** reasoning loop and **NaVILA** (VILA-8B), a model purpose-trained
8
+ for language-guided navigation.
9
+
10
+ |Systems|ROS2 distro|Build status|
11
+ |--|--|--|
12
+ |Ubuntu 24.04|jazzy|![ROS2 CI](https://github.com/abizovnuralem/go2_ros2_sdk/actions/workflows/ros_build.yaml/badge.svg)|
13
+
14
+
15
+ ## Repository map
16
+
17
+ | Path | Role |
18
+ |---|---|
19
+ | [`go2_robot_sdk/`](go2_robot_sdk) | WebRTC/LAN driver — camera, odom, lidar, URDF |
20
+ | [`go2_navigation/`](go2_navigation) | Bringup, mapping, Nav2, C++ lidar filtering pipeline |
21
+ | [`go2_control/`](go2_control) | Keyboard teleop node |
22
+ | [`go2_interfaces/`](go2_interfaces) | Shared ROS 2 message definitions |
23
+ | [`vlm/`](vlm) | Local VLA stack: Qwen2.5-VL engine, YOLO-assisted servoing, web console |
24
+ | [`navila/`](navila) | NaVILA (VILA-8B) inference server + setup/eval tooling (bare metal, not containerized) |
25
+ | [`docker/`](docker) | Containerized driver + navigation + local VLA bringup |
26
+
27
+ ## Installation
28
+
29
+ ```shell
30
+ mkdir -p ros2_ws
31
+ cd ros2_ws
32
+ git clone --recurse-submodules https://github.com/StrikeRobot/Go2-Nav_System src
33
+ sudo apt install ros-$ROS_DISTRO-image-tools ros-$ROS_DISTRO-vision-msgs
34
+ sudo apt install python3-pip clang portaudio19-dev
35
+ cd src
36
+ pip install -r requirements.txt
37
+ cd ..
38
+ source /opt/ros/$ROS_DISTRO/setup.bash
39
+ rosdep install --from-paths src --ignore-src -r -y
40
+ colcon build
41
+ ```
42
+
43
+ ## Docker
44
+
45
+ ```shell
46
+ cd docker
47
+ cp .env.example .env # if you keep one locally; otherwise export ROBOT_IP inline
48
+ ROBOT_IP=<go2-lan-ip> docker compose up go2 # driver + Nav2 stack
49
+ ROBOT_IP=<go2-lan-ip> docker compose --profile vla up vlm # + local VLA web console (GPU)
50
+ ```
51
+ The image builds on `ros:jazzy-ros-base`, matching the distro this project is
52
+ developed against. `network_mode: host` is required for ROS 2 DDS discovery and
53
+ for the driver's WebRTC session with the robot on the LAN. The `vlm` service
54
+ requests a GPU via the [NVIDIA Container Toolkit](https://github.com/NVIDIA/nvidia-container-toolkit) —
55
+ install that on the host first. **NaVILA is not containerized**: it needs its
56
+ own conda environment, a hand-patched `transformers` build for Blackwell GPUs,
57
+ and a ~16 GB checkpoint pulled at setup time, so it's run on bare metal via
58
+ [`navila/setup_navila_blackwell.sh`](navila/setup_navila_blackwell.sh) — see the
59
+ [NaVILA section](#brain-2--navila-vila-8b) below.
60
+
61
+ Never bake a real `ROBOT_IP`/`ROBOT_TOKEN` into the image or into
62
+ `go2_navigation/config/robot.yaml` — pass them as environment variables at run
63
+ time instead.
64
+
65
+ ## Usage
66
+
67
+ Put the Go2 in Wi-Fi/STA mode and note its LAN IP (mobile app → Device → Data →
68
+ Automatic Machine Inspection → STA Network: `wlan0`). Set it once in
69
+ [`go2_navigation/config/robot.yaml`](go2_navigation/config/robot.yaml) or pass
70
+ `ROBOT_IP=<ip>` on any launch command (env always wins).
71
+
72
+ ```shell
73
+ source install/setup.bash
74
+ ```
75
+
76
+ ### Mapping
77
+
78
+ ```shell
79
+ ros2 launch go2_navigation mapping.launch.py
80
+ ```
81
+ Mark a dock rectangle with tape as a fixed starting point. In the SlamToolbox
82
+ panel in `rviz`, select **Start At Dock**, drive the robot around with a
83
+ controller to build the map, then **Save Map** / **Serialize Map**.
84
+
85
+ ### Autonomous navigation (Nav2)
86
+
87
+ ```shell
88
+ ros2 launch go2_navigation navigation.launch.py
89
+ ```
90
+ Loads a saved map and drives the robot with Nav2's standard global/local
91
+ planner stack + AMCL localization — set goals from `rviz` as usual.
92
+
93
+ ### Manual teleop
94
+
95
+ ```shell
96
+ ros2 run go2_control keyboard_teleop
97
+ ```
98
+ Arrows = move, `q`/`e` = rotate, space = stop, `x` = quit. Releasing all keys
99
+ for >0.4 s triggers a dead-man stop.
100
+
101
+ ## VLA navigation
102
+
103
+ Instead of a Nav2 goal, type an instruction and let a vision-language model
104
+ decide the motion step by step from the live camera feed. **No RL or learned
105
+ locomotion is involved anywhere in this stack** — every brain below only ever
106
+ emits a discrete motion command (`move forward 25 cm`, `turn left 30°`,
107
+ `stop`); the Go2's own built-in gait and this repo's closed-loop
108
+ `MotionController` (odom + lidar + E-Stop) execute it.
109
+
110
+ ### Brain 1 — local Qwen2.5-VL (`vlm` package, "Demo1")
111
+
112
+ ```shell
113
+ ros2 launch go2_navigation bringup.launch.py teleop:=true
114
+ ```
115
+ ```shell
116
+ cd ros2_ws/src
117
+ ./vlm/scripts/run_demo1.sh
118
+ ```
119
+ Open `http://localhost:8001`, type a goal in natural language (e.g. *"go to
120
+ the water bottle, turn right, stop at the chair"*) or a manual command (`move
121
+ forward 75 cm`, `turn left 90 deg`). Each step: camera frame → Qwen2.5-VL
122
+ prompt (with live odom/lidar/bbox metrics injected as state) → JSON
123
+ `{action, value, unit, is_finished, ...}` → `MotionController` executes →
124
+ repeat until `is_finished` or **Stop/E-Stop**.
125
+
126
+ Two control modes (`VLA_CONTROL`):
127
+ - `vlm` (default) — the model reasons over injected state and returns the next action.
128
+ - `servo` — continuous closed-loop visual servoing driven by YOLO detections,
129
+ bypassing the LLM once a target is locked on.
130
+
131
+ Swap in a stronger model instead of the local 3B:
132
+ ```shell
133
+ VLA_BRAIN=api VLA_API_URL=<endpoint> VLA_API_KEY=<key> VLA_MODEL=qwen2.5-vl-7b-instruct \
134
+ ./vlm/scripts/run_demo1.sh
135
+ ```
136
+
137
+ <details>
138
+ <summary>Configuration reference — local VLM brain</summary>
139
+
140
+ | Env | Default | Meaning |
141
+ |---|---|---|
142
+ | `VLA_BRAIN` | `local` | `local` (Qwen2.5-VL-3B) \| `api` (OpenAI-compatible endpoint) \| `navila` |
143
+ | `VLA_CONTROL` | `servo` | `servo` (visual servo, YOLO-driven) \| `vlm` (JSON reasoning loop) |
144
+ | `USE_YOLO` | `1` | `0` disables the YOLO detector |
145
+ | `VLA_MAX_STEPS` | `20` | max steps per instruction |
146
+ | `VLA_MAX_TURN_DEG` | `10` | hard cap on turn angle per step (all brains) |
147
+ | `VLA_SEARCH_MAX_DEG` | `360` | give up searching after this much cumulative scan rotation |
148
+ | `VLA_HFOV_DEG` | `90` | camera horizontal FOV, used to convert pixel offset → angle |
149
+ | `VLA_CENTER_TOL_DEG` | `5` | (servo) angular tolerance considered "centered" |
150
+ | `VLA_SERVO_HZ` / `VLA_SERVO_VX` / `VLA_SERVO_WZ_MAX` / `VLA_SERVO_KP` | `20` / `0.25` / `0.175` / `1.5` | servo loop rate, forward speed, max turn rate, turn gain |
151
+ | `VLA_STOP_BOTTOM_PX` | `20` | stop once the target bbox bottom is within this many px of the frame edge |
152
+ | `MOTION_LIN_SPEED` / `MOTION_ANG_SPEED` / `MOTION_ANG_MAX_DEG` | `0.3` / `0.35` / `10` | discrete move/turn command speeds and turn-rate ceiling |
153
+ | `MOTION_FRONT_STOP` | `0.30` | lidar obstacle distance (m) that halts forward motion |
154
+ | `MOTION_TURN_SIGN` | `1` | set to `-1` if the robot turns opposite to the commanded direction |
155
+ | `VLA_YOLO_WEIGHTS` / `VLA_YOLO_MIN_CONF` / `VLA_YOLO_IMGSZ` | `yolo11n.pt` / `0.3` / `960` | detector weights, confidence threshold, inference resolution |
156
+ | `VLA_LOG_DIR` | `vla_logs` | per-step JSONL log directory |
157
+ | `DEMO_MOCK` / `VLM_SKIP_MODEL` | — | run the UI without a robot / without loading the model |
158
+
159
+ Full source of truth for these lives in [`vlm/webconsole/demo1/navloop.py`](vlm/webconsole/demo1/navloop.py)
160
+ and [`vlm/webconsole/demo1/motion.py`](vlm/webconsole/demo1/motion.py).
161
+ </details>
162
+
163
+ ### Brain 2 — NaVILA (VILA-8B)
164
+
165
+ [NaVILA](https://github.com/AnjieCheng/NaVILA) is an 8B vision-language-action
166
+ model trained specifically for language-guided navigation. It's integrated as a
167
+ **System-2 / System-1 split brain**:
168
+
169
+ ```
170
+ camera → 8-frame sliding buffer → HTTP → NaVILA (VILA-8B, System-2, GPU)
171
+ → mid-level action text → parser → MotionCmd
172
+ → MotionController → twist_mux → go2_driver → Go2 built-in gait (System-1)
173
+ ```
174
+
175
+ - **System-2** (`navila_server.py`, its own conda env, port `8100`) loads the
176
+ 8B checkpoint once and turns 8 camera frames + the instruction into an
177
+ action sentence (`"The next action is move forward 25 cm."`) — a pure
178
+ action policy, no chain-of-thought.
179
+ - **System-1** is the same odom/lidar-closed-loop `MotionController` used
180
+ above; NaVILA never touches locomotion or gait, only high-level intent.
181
+
182
+ First-time setup (downloads the code repo + checkpoint, patches `transformers`
183
+ for Blackwell GPUs):
184
+ ```shell
185
+ bash navila/setup_navila_blackwell.sh
186
+ ```
187
+
188
+ One-command run (driver + NaVILA server + web console):
189
+ ```shell
190
+ cd ros2_ws/src/navila
191
+ ./scripts/run.sh
192
+ ```
193
+ Open `http://localhost:8001` and type an instruction **in English** (NaVILA is
194
+ trained on English R2R-style instructions), e.g. *"Walk forward down the
195
+ hallway and stop near the chair."* The reasoning panel shows the raw NaVILA
196
+ output, per-token confidence, and a link to the exact 8 frames the model
197
+ received.
198
+
199
+ <details>
200
+ <summary>Configuration reference — NaVILA brain</summary>
201
+
202
+ | Env / arg | Default | Meaning |
203
+ |---|---|---|
204
+ | `VLA_BRAIN=navila` | — | routes control to the NaVILA server |
205
+ | `VLA_NAVILA_URL` | `http://127.0.0.1:8100` | NaVILA server address |
206
+ | `VLA_NAVILA_FRAMES` | `8` | frames sent per request (must match server `--num-frames`) |
207
+ | `VLA_NAVILA_HISTORY_MAX` | `64` | raw history frames kept per instruction; uniformly resampled down to `VLA_NAVILA_FRAMES`, always including the first and current frame (matches the paper's sampling scheme) |
208
+ | `NAVILA_FALLBACK` | `stop` | behavior when the model output fails to parse: `stop` \| `scan` |
209
+ | `NAVILA_PREPROC` | `pad` | frame preprocessing: `fov` (undistort + forward crop, closest to training distribution) \| `pad` (full fisheye) \| `resize` \| `crop` |
210
+ | server `--model-path` | — | path to the downloaded checkpoint |
211
+ | server `--port` | `8100` | HTTP port |
212
+ | server `--num-frames` | `8` | frames processed per request |
213
+
214
+ Full parameter tables, the three Blackwell inference fixes (8-bit + eager
215
+ attention + 4D causal mask — see [`navila/setup_navila_blackwell.sh`](navila/setup_navila_blackwell.sh)),
216
+ and eval/debug tooling (`navila/tools/`) are documented inline in that script
217
+ and in [`navila/scripts/`](navila/scripts).
218
+ </details>
219
+
220
+ ## Acknowledgements & citations
221
+
222
+ - Built on [abizovnuralem/go2_ros2_sdk](https://github.com/abizovnuralem/go2_ros2_sdk)
223
+ (RoboVerse community) — see [`LICENSE`](LICENSE).
224
+ - **NaVILA** — An-Chieh Cheng et al., *"NaVILA: Legged Robot Vision-Language-Action
225
+ Model for Navigation"*, 2024. Code: [AnjieCheng/NaVILA](https://github.com/AnjieCheng/NaVILA),
226
+ checkpoint: `a8cheng/navila-llama3-8b-8f` on Hugging Face. See the official
227
+ repository for the paper and up-to-date citation.
228
+ - **Qwen2.5-VL** — Alibaba Qwen team, model `Qwen/Qwen2.5-VL-3B-Instruct`.
229
+ - **Ultralytics YOLO11** — [ultralytics/ultralytics](https://github.com/ultralytics/ultralytics).
230
+ - **Nav2** and **slam_toolbox** — the ROS 2 Navigation Working Group /
231
+ [ros-navigation](https://github.com/ros-navigation) and
232
+ [SteveMacenski/slam_toolbox](https://github.com/SteveMacenski/slam_toolbox).
233
+ - **Point Cloud Library (PCL)** — used for the SOR/ROR filtering pipeline in `go2_navigation`.
234
+ - **twist_mux** — [ros-teleop/twist_mux](https://github.com/ros-teleop/twist_mux),
235
+ used to arbitrate teleop/VLA vs. Nav2 velocity commands.
236
+ - **aiortc** — vendored WebRTC implementation used by the Go2 driver.
237
+
238
+ ## License
239
+
240
+ BSD 2-Clause — see [`LICENSE`](LICENSE). Note: some vendored/derived source
241
+ files under `go2_navigation/` carry a BSD-3-Clause header inherited from
242
+ upstream; if you plan to redistribute, reconcile this with project counsel
243
+ before publishing rather than assuming one license governs the whole tree.
docker/Dockerfile ADDED
@@ -0,0 +1,63 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Go2 ROS 2 workspace image: driver + navigation (Nav2/SLAM) + local VLA stack (vlm).
2
+ #
3
+ # Targets the same distro this project is developed/tested against (see README).
4
+ # GPU-backed inference (local Qwen2.5-VL brain, YOLO) needs the NVIDIA Container
5
+ # Toolkit on the host and a GPU reservation at `docker run`/`docker compose` time —
6
+ # no CUDA base image is required since the pip wheels ship their own CUDA runtime.
7
+ #
8
+ # NaVILA is intentionally NOT part of this image: it needs its own conda env,
9
+ # hand-patched transformers build, and a ~16GB checkpoint pulled at setup time —
10
+ # see navila/setup_navila_blackwell.sh and run it on bare metal.
11
+ FROM ros:jazzy-ros-base
12
+
13
+ ENV DEBIAN_FRONTEND=noninteractive
14
+
15
+ # --- System packages (stable layer, only invalidated by this list changing) ---
16
+ RUN apt-get update && apt-get install -y --no-install-recommends \
17
+ curl \
18
+ gnupg2 \
19
+ lsb-release \
20
+ software-properties-common \
21
+ python3-pip \
22
+ clang \
23
+ portaudio19-dev \
24
+ mesa-utils \
25
+ libgl1-mesa-dev \
26
+ ffmpeg \
27
+ ros-${ROS_DISTRO}-rviz2 \
28
+ ros-${ROS_DISTRO}-rmw-cyclonedds-cpp \
29
+ ros-${ROS_DISTRO}-image-tools \
30
+ ros-${ROS_DISTRO}-vision-msgs \
31
+ && rm -rf /var/lib/apt/lists/*
32
+
33
+ WORKDIR /ros2_ws
34
+
35
+ # --- Python deps in their own layer: only rebuilt when requirements.txt changes ---
36
+ COPY requirements.txt src/requirements.txt
37
+ # Ubuntu 24.04 marks the system interpreter "externally managed" (PEP 668); this
38
+ # image is disposable so overriding that guard is the pragmatic choice here.
39
+ RUN pip install --no-cache-dir --break-system-packages 'numpy<2.0.0' && \
40
+ pip install --no-cache-dir --break-system-packages -r src/requirements.txt
41
+
42
+ # --- Workspace source + ROS deps + build ---
43
+ COPY . src/
44
+ RUN . /opt/ros/${ROS_DISTRO}/setup.sh && \
45
+ rosdep update && \
46
+ rosdep install --from-paths src --ignore-src -r -y && \
47
+ colcon build --symlink-install
48
+
49
+ RUN echo "source /opt/ros/${ROS_DISTRO}/setup.bash" >> /root/.bashrc && \
50
+ echo "source /ros2_ws/install/setup.bash" >> /root/.bashrc && \
51
+ sed --in-place --expression \
52
+ '$isource "/ros2_ws/install/setup.bash"' \
53
+ /ros_entrypoint.sh
54
+
55
+ # Connection defaults — override at `docker run -e` / compose `environment:`,
56
+ # never bake real robot IPs or tokens into the image.
57
+ ENV ROBOT_IP=""
58
+ ENV ROBOT_TOKEN=""
59
+ ENV CONN_TYPE="webrtc"
60
+ ENV WEBRTC_SERVER_HOST="0.0.0.0"
61
+ ENV WEBRTC_SERVER_PORT="9991"
62
+
63
+ CMD ["ros2", "launch", "go2_navigation", "bringup.launch.py"]
docker/docker-compose.yml ADDED
@@ -0,0 +1,37 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ services:
2
+ # Driver + navigation (Nav2/SLAM). Default profile — `docker compose up go2`.
3
+ go2:
4
+ build:
5
+ context: ..
6
+ dockerfile: docker/Dockerfile
7
+ image: go2-nav-vla:latest
8
+ environment:
9
+ - ROBOT_IP=${ROBOT_IP:?set ROBOT_IP to your Go2's LAN address}
10
+ - ROBOT_TOKEN=${ROBOT_TOKEN:-}
11
+ - CONN_TYPE=${CONN_TYPE:-webrtc}
12
+ - DISPLAY=${DISPLAY:-}
13
+ volumes:
14
+ - /tmp/.X11-unix:/tmp/.X11-unix:ro # X11 forwarding, e.g. for rviz2
15
+ - ${HOME}/.Xauthority:/root/.Xauthority:rw
16
+ network_mode: host # required: ROS 2 DDS discovery + Go2 WebRTC live on the LAN
17
+ privileged: true # required: joystick/input device access
18
+ devices:
19
+ - /dev/input:/dev/input
20
+ restart: unless-stopped
21
+ command: ["ros2", "launch", "go2_navigation", "bringup.launch.py"]
22
+
23
+ # Local VLA brain (Qwen2.5-VL) + web console, port 8001. Opt-in:
24
+ # docker compose --profile vla up vlm
25
+ # Requires the NVIDIA Container Toolkit on the host for GPU access.
26
+ vlm:
27
+ extends: go2
28
+ profiles: ["vla"]
29
+ working_dir: /ros2_ws/src
30
+ deploy:
31
+ resources:
32
+ reservations:
33
+ devices:
34
+ - driver: nvidia
35
+ count: all
36
+ capabilities: [gpu]
37
+ command: ["./vlm/scripts/run_demo1.sh"]
docker/entrypoint.sh ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
 
1
+ #!/bin/bash
2
+ set -e
3
+
4
+ # Source ROS2 environment
5
+ source /opt/ros/${ROS_DISTRO}/setup.bash
6
+ source /ros2_ws/install/setup.bash
7
+
8
+ # Execute the command passed to docker run
9
+ exec "$@"
go2_control/go2_control/__init__.py ADDED
File without changes
go2_control/go2_control/keyboard_teleop.py ADDED
@@ -0,0 +1,150 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Điều khiển Go2 bằng bàn phím (giữ phím = đi, buông = dừng).
2
+
3
+ Bắn TwistStamped vào /cmd_vel_joy (qua twist_mux, priority cao -> đè Nav2).
4
+
5
+ Phím (KHÔNG cần Enter):
6
+ ↑ / ↓ tiến / lùi (vx)
7
+ ← / → đi ngang trái/phải (vy) — Go2 hỗ trợ
8
+ q / e xoay trái / phải (yaw)
9
+ space dừng ngay
10
+ x / Ctrl-C thoát
11
+
12
+ Cơ chế: terminal ở chế độ raw nên nhận phím tức thời. GIỮ phím -> hệ điều hành
13
+ tự lặp phím liên tục -> vận tốc được giữ. BUÔNG phím -> hết lặp -> sau
14
+ `hold_timeout` giây robot tự dừng (dead-man). Bấm phím ngược chiều -> đảo vận
15
+ tốc ngay (hãm/lùi lại). Tốc độ chỉnh qua ROS param.
16
+ """
17
+ import os
18
+ import sys
19
+ import select
20
+ import termios
21
+ import tty
22
+ import time
23
+
24
+ import rclpy
25
+ from rclpy.node import Node
26
+ from geometry_msgs.msg import TwistStamped
27
+
28
+ HELP = __doc__
29
+
30
+
31
+ class KeyboardTeleop(Node):
32
+ def __init__(self):
33
+ super().__init__("go2_keyboard_teleop")
34
+
35
+ self.declare_parameter("cmd_topic", "/cmd_vel_joy")
36
+ self.declare_parameter("frame_id", "base_link")
37
+ self.declare_parameter("lin_speed", 0.4) # m/s tiến/lùi
38
+ self.declare_parameter("lat_speed", 0.3) # m/s đi ngang
39
+ self.declare_parameter("ang_speed", 0.8) # rad/s xoay
40
+ self.declare_parameter("hold_timeout", 0.3) # s không thấy phím -> dừng
41
+ self.declare_parameter("publish_rate", 50.0) # Hz
42
+
43
+ gp = self.get_parameter
44
+ self.topic = gp("cmd_topic").get_parameter_value().string_value
45
+ self.frame_id = gp("frame_id").get_parameter_value().string_value
46
+ self.lin = gp("lin_speed").get_parameter_value().double_value
47
+ self.lat = gp("lat_speed").get_parameter_value().double_value
48
+ self.ang = gp("ang_speed").get_parameter_value().double_value
49
+ self.hold = gp("hold_timeout").get_parameter_value().double_value
50
+ self.dt = 1.0 / max(gp("publish_rate").get_parameter_value().double_value, 1.0)
51
+
52
+ self.pub = self.create_publisher(TwistStamped, self.topic, 10)
53
+ self._vx = self._vy = self._wz = 0.0
54
+ self._last_key = 0.0
55
+
56
+ self.get_logger().info(
57
+ f"Keyboard teleop -> {self.topic} "
58
+ f"(lin={self.lin} lat={self.lat} ang={self.ang}, dead-man={self.hold}s)")
59
+
60
+ def _apply(self, vx, vy, wz):
61
+ self._vx, self._vy, self._wz = vx, vy, wz
62
+ self._last_key = time.monotonic()
63
+
64
+ def _handle(self, keys):
65
+ """keys: chuỗi byte đã đọc trong tick này (đã drain hết)."""
66
+ i, n = 0, len(keys)
67
+ while i < n:
68
+ c = keys[i]
69
+ if c == "\x1b" and i + 2 < n + 1 and keys[i + 1:i + 2] == "[":
70
+ seq = keys[i + 2:i + 3]
71
+ if seq == "A":
72
+ self._apply(self.lin, 0.0, 0.0)
73
+ elif seq == "B":
74
+ self._apply(-self.lin, 0.0, 0.0)
75
+ elif seq == "D":
76
+ self._apply(0.0, self.lat, 0.0)
77
+ elif seq == "C":
78
+ self._apply(0.0, -self.lat, 0.0)
79
+ i += 3
80
+ continue
81
+ if c in ("q", "Q"):
82
+ self._apply(0.0, 0.0, self.ang)
83
+ elif c in ("e", "E"):
84
+ self._apply(0.0, 0.0, -self.ang)
85
+ elif c == " ":
86
+ self._apply(0.0, 0.0, 0.0)
87
+ elif c in ("x", "X", "\x03"):
88
+ raise KeyboardInterrupt
89
+ i += 1
90
+
91
+ def _publish(self):
92
+ # dead-man: quá lâu không thấy phím -> dừng (buông phím = dừng)
93
+ if time.monotonic() - self._last_key > self.hold:
94
+ self._vx = self._vy = self._wz = 0.0
95
+ msg = TwistStamped()
96
+ msg.header.stamp = self.get_clock().now().to_msg()
97
+ msg.header.frame_id = self.frame_id
98
+ msg.twist.linear.x = self._vx
99
+ msg.twist.linear.y = self._vy
100
+ msg.twist.angular.z = self._wz
101
+ self.pub.publish(msg)
102
+
103
+ def run(self):
104
+ if not sys.stdin.isatty():
105
+ self.get_logger().error(
106
+ "stdin không phải terminal -> không đọc được phím. "
107
+ "Chạy trực tiếp `ros2 run go2_control keyboard_teleop` trong terminal.")
108
+ return
109
+ print(HELP)
110
+ fd = sys.stdin.fileno()
111
+ old = termios.tcgetattr(fd)
112
+ try:
113
+ tty.setcbreak(fd) # tức thời, không cần Enter
114
+ while rclpy.ok():
115
+ # drain mọi byte đang chờ trong tick này
116
+ buf = ""
117
+ while select.select([fd], [], [], 0)[0]:
118
+ ch = os.read(fd, 1).decode(errors="ignore")
119
+ if not ch:
120
+ break
121
+ buf += ch
122
+ if buf:
123
+ self._handle(buf)
124
+ self._publish()
125
+ rclpy.spin_once(self, timeout_sec=0)
126
+ time.sleep(self.dt)
127
+ except KeyboardInterrupt:
128
+ pass
129
+ finally:
130
+ termios.tcsetattr(fd, termios.TCSADRAIN, old)
131
+ # gửi vài lệnh dừng cho chắc
132
+ for _ in range(3):
133
+ self._apply(0.0, 0.0, 0.0)
134
+ self._publish()
135
+ time.sleep(0.01)
136
+
137
+
138
+ def main(args=None):
139
+ rclpy.init(args=args)
140
+ node = KeyboardTeleop()
141
+ try:
142
+ node.run()
143
+ finally:
144
+ if rclpy.ok():
145
+ node.destroy_node()
146
+ rclpy.shutdown()
147
+
148
+
149
+ if __name__ == "__main__":
150
+ main()
go2_control/package.xml ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0"?>
2
+ <?xml-model href="http://download.ros.org/schema/package_format3.xsd" schematypens="http://www.w3.org/2001/XMLSchema"?>
3
+ <package format="3">
4
+ <name>go2_control</name>
5
+ <version>0.0.0</version>
6
+ <description>Keyboard teleop for Unitree Go2 (arrows = move, q/e = rotate) publishing TwistStamped to /cmd_vel_joy</description>
7
+ <maintainer email="dsclabs.contact@gmail.com">dsc-labs</maintainer>
8
+ <license>BSD-3-Clause</license>
9
+
10
+ <exec_depend>rclpy</exec_depend>
11
+ <exec_depend>geometry_msgs</exec_depend>
12
+
13
+ <test_depend>ament_copyright</test_depend>
14
+ <test_depend>ament_flake8</test_depend>
15
+ <test_depend>ament_pep257</test_depend>
16
+ <test_depend>python3-pytest</test_depend>
17
+
18
+ <export>
19
+ <build_type>ament_python</build_type>
20
+ </export>
21
+ </package>
go2_control/resource/go2_control ADDED
File without changes
go2_control/setup.cfg ADDED
@@ -0,0 +1,4 @@
 
 
 
 
 
1
+ [develop]
2
+ script_dir=$base/lib/go2_control
3
+ [install]
4
+ install_scripts=$base/lib/go2_control
go2_control/setup.py ADDED
@@ -0,0 +1,25 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from setuptools import find_packages, setup
2
+
3
+ package_name = 'go2_control'
4
+
5
+ setup(
6
+ name=package_name,
7
+ version='0.0.0',
8
+ packages=find_packages(exclude=['test']),
9
+ data_files=[
10
+ ('share/ament_index/resource_index/packages',
11
+ ['resource/' + package_name]),
12
+ ('share/' + package_name, ['package.xml']),
13
+ ],
14
+ install_requires=['setuptools'],
15
+ zip_safe=True,
16
+ maintainer='dsc-labs',
17
+ maintainer_email='dsclabs.contact@gmail.com',
18
+ description='Keyboard teleop for Unitree Go2 (publishes TwistStamped to /cmd_vel_joy)',
19
+ license='BSD-3-Clause',
20
+ entry_points={
21
+ 'console_scripts': [
22
+ 'keyboard_teleop = go2_control.keyboard_teleop:main',
23
+ ],
24
+ },
25
+ )
go2_interfaces/CMakeLists.txt ADDED
@@ -0,0 +1,61 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ cmake_minimum_required(VERSION 3.8)
2
+ project(go2_interfaces)
3
+
4
+ # Fix for CMake policy CMP0148 warning
5
+ if(POLICY CMP0148)
6
+ cmake_policy(SET CMP0148 OLD)
7
+ endif()
8
+
9
+ if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang")
10
+ add_compile_options(-Wall -Wextra -Wpedantic)
11
+ endif()
12
+
13
+ # find dependencies
14
+ find_package(ament_cmake REQUIRED)
15
+ find_package(geometry_msgs REQUIRED)
16
+ find_package(rosidl_default_generators REQUIRED)
17
+ # uncomment the following section in order to fill in
18
+ # further dependencies manually.
19
+
20
+
21
+ rosidl_generate_interfaces(${PROJECT_NAME}
22
+ # Original go2_interfaces messages
23
+ "msg/Go2Cmd.msg"
24
+ "msg/Go2State.msg"
25
+ "msg/Go2Move.msg"
26
+ "msg/Go2RpyCmd.msg"
27
+ "msg/IMU.msg"
28
+
29
+ # Merged from unitree_go
30
+ "msg/AudioData.msg"
31
+ "msg/BmsCmd.msg"
32
+ "msg/BmsState.msg"
33
+ "msg/Error.msg"
34
+ "msg/Go2FrontVideoData.msg"
35
+ "msg/HeightMap.msg"
36
+ "msg/InterfaceConfig.msg"
37
+ "msg/LidarState.msg"
38
+ "msg/LowCmd.msg"
39
+ "msg/LowState.msg"
40
+ "msg/MotorCmd.msg"
41
+ "msg/MotorCmds.msg"
42
+ "msg/MotorState.msg"
43
+ "msg/MotorStates.msg"
44
+ "msg/PathPoint.msg"
45
+ "msg/Req.msg"
46
+ "msg/Res.msg"
47
+ "msg/SportModeCmd.msg"
48
+ "msg/SportModeState.msg"
49
+ "msg/TimeSpec.msg"
50
+ "msg/UwbState.msg"
51
+ "msg/UwbSwitch.msg"
52
+ "msg/VoxelMapCompressed.msg"
53
+ "msg/VoxelHeightMapState.msg"
54
+ "msg/WebRtcReq.msg"
55
+ "msg/WirelessController.msg"
56
+
57
+ DEPENDENCIES geometry_msgs # Add packages that above messages depend on
58
+ )
59
+
60
+
61
+ ament_package()
go2_interfaces/msg/AudioData.msg ADDED
@@ -0,0 +1,2 @@
 
 
 
1
+ uint64 time_frame
2
+ uint8[] data
go2_interfaces/msg/BmsCmd.msg ADDED
@@ -0,0 +1,2 @@
 
 
 
1
+ uint8 off
2
+ uint8[3] reserve
go2_interfaces/msg/BmsState.msg ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
 
1
+ uint8 version_high
2
+ uint8 version_low
3
+ uint8 status
4
+ uint8 soc
5
+ int32 current
6
+ uint16 cycle
7
+ int8[2] bq_ntc
8
+ int8[2] mcu_ntc
9
+ uint16[15] cell_vol
go2_interfaces/msg/Error.msg ADDED
@@ -0,0 +1,2 @@
 
 
 
1
+ uint32 source
2
+ uint32 state
go2_interfaces/msg/Go2Cmd.msg ADDED
@@ -0,0 +1 @@
 
 
1
+ uint16 cmd
go2_interfaces/msg/Go2FrontVideoData.msg ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
 
1
+ # Time frame as a 64-bit unsigned integer
2
+ uint64 time_frame
3
+
4
+ # Resolution as a 16-bit signed integer
5
+ int16 resolution
6
+
7
+ # Data as a sequence of bytes (octets)
8
+ uint8[] data
go2_interfaces/msg/Go2Move.msg ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ float32 x
2
+ float32 y
3
+ float32 z
go2_interfaces/msg/Go2RpyCmd.msg ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ float32 roll
2
+ float32 pitch
3
+ float32 yaw
go2_interfaces/msg/Go2State.msg ADDED
@@ -0,0 +1,12 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ uint8 mode
2
+ int32 progress
3
+ uint8 gait_type
4
+ float32 foot_raise_height
5
+ float32[3] position
6
+ float32 body_height
7
+ float32[3] velocity
8
+ float32[4] range_obstacle
9
+ int16[4] foot_force
10
+ float32[12] foot_position_body
11
+ float32[12] foot_speed_body
12
+
go2_interfaces/msg/HeightMap.msg ADDED
@@ -0,0 +1,15 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Header
2
+ float64 stamp # timestamp
3
+ string frame_id # world frame id
4
+
5
+ # Map info
6
+ float32 resolution # The map resolution [m/cell]
7
+ uint32 width # Map width along x-axis [cells]
8
+ uint32 height # Map height alonge y-axis [cells]
9
+ float32[2] origin # Map frame origin xy-position [m], the xyz-axis direction of map frame is aligned with the world frame
10
+
11
+ # Map data, in x-major order, starting with [0,0], ending with [width, height]
12
+ # For a cell whose 2d-array-index is [ix, iy],
13
+ # its position in world frame is: [ix * resolution + origin[0], iy * resolution + origin[1]]
14
+ # its cell value is: data[width * iy + ix]
15
+ float32[] data
go2_interfaces/msg/IMU.msg ADDED
@@ -0,0 +1,5 @@
 
 
 
 
 
 
1
+ float32[4] quaternion
2
+ float32[3] gyroscope
3
+ float32[3] accelerometer
4
+ float32[3] rpy
5
+ int8 temperature
go2_interfaces/msg/InterfaceConfig.msg ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ uint8 mode
2
+ uint8 value
3
+ uint8[2] reserve
go2_interfaces/msg/LidarState.msg ADDED
@@ -0,0 +1,17 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ float64 stamp
2
+ string firmware_version
3
+ string software_version
4
+ string sdk_version
5
+ float32 sys_rotation_speed
6
+ float32 com_rotation_speed
7
+ uint8 error_state
8
+ float32 cloud_frequency
9
+ float32 cloud_packet_loss_rate
10
+ uint32 cloud_size
11
+ uint32 cloud_scan_num
12
+ float32 imu_frequency
13
+ float32 imu_packet_loss_rate
14
+ float32[3] imu_rpy
15
+ float64 serial_recv_stamp
16
+ uint32 serial_buffer_size
17
+ uint32 serial_buffer_read
go2_interfaces/msg/LowCmd.msg ADDED
@@ -0,0 +1,15 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ uint8[2] head
2
+ uint8 level_flag
3
+ uint8 frame_reserve
4
+ uint32[2] sn
5
+ uint32[2] version
6
+ uint16 bandwidth
7
+ MotorCmd[20] motor_cmd
8
+ BmsCmd bms_cmd
9
+ uint8[40] wireless_remote
10
+ uint8[12] led
11
+ uint8[2] fan
12
+ uint8 gpio
13
+ uint32 reserve
14
+ uint32 crc
15
+
go2_interfaces/msg/LowState.msg ADDED
@@ -0,0 +1,22 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ uint8[2] head
2
+ uint8 level_flag
3
+ uint8 frame_reserve
4
+ uint32[2] sn
5
+ uint32[2] version
6
+ uint16 bandwidth
7
+ IMU imu_state
8
+ MotorState[20] motor_state
9
+ BmsState bms_state
10
+ int16[4] foot_force
11
+ int16[4] foot_force_est
12
+ uint32 tick
13
+ uint8[40] wireless_remote
14
+ uint8 bit_flag
15
+ float32 adc_reel
16
+ int8 temperature_ntc1
17
+ int8 temperature_ntc2
18
+ float32 power_v
19
+ float32 power_a
20
+ uint16[4] fan_frequency
21
+ uint32 reserve
22
+ uint32 crc
go2_interfaces/msg/MotorCmd.msg ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
 
1
+ uint8 mode
2
+ float32 q
3
+ float32 dq
4
+ float32 tau
5
+ float32 kp
6
+ float32 kd
7
+ uint32[3] reserve
go2_interfaces/msg/MotorCmds.msg ADDED
@@ -0,0 +1 @@
 
 
1
+ MotorCmd[] cmds
go2_interfaces/msg/MotorState.msg ADDED
@@ -0,0 +1,11 @@
 
 
 
 
 
 
 
 
 
 
 
 
1
+ uint8 mode
2
+ float32 q
3
+ float32 dq
4
+ float32 ddq
5
+ float32 tau_est
6
+ float32 q_raw
7
+ float32 dq_raw
8
+ float32 ddq_raw
9
+ int8 temperature
10
+ uint32 lost
11
+ uint32[2] reserve
go2_interfaces/msg/MotorStates.msg ADDED
@@ -0,0 +1 @@
 
 
1
+ MotorState[] states
go2_interfaces/msg/PathPoint.msg ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
 
1
+ float32 t_from_start
2
+ float32 x
3
+ float32 y
4
+ float32 yaw
5
+ float32 vx
6
+ float32 vy
7
+ float32 vyaw
go2_interfaces/msg/Req.msg ADDED
@@ -0,0 +1,2 @@
 
 
 
1
+ string uuid
2
+ string body
go2_interfaces/msg/Res.msg ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ string uuid
2
+ uint8[] data
3
+ string body
go2_interfaces/msg/SportModeCmd.msg ADDED
@@ -0,0 +1,13 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ uint8 mode
2
+ uint8 gait_type
3
+ uint8 speed_level
4
+ float32 foot_raise_height
5
+ float32 body_height
6
+ float32[2] position
7
+ float32[3] euler
8
+ float32[2] velocity
9
+ float32 yaw_speed
10
+ BmsCmd bms_cmd
11
+ PathPoint[30] path_point
12
+
13
+
go2_interfaces/msg/SportModeState.msg ADDED
@@ -0,0 +1,17 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ TimeSpec stamp
2
+ uint32 error_code
3
+ IMU imu_state
4
+ uint8 mode
5
+ float32 progress
6
+ uint8 gait_type
7
+ float32 foot_raise_height
8
+ float32[3] position
9
+ float32 body_height
10
+ float32[3] velocity
11
+ float32 yaw_speed
12
+ float32[4] range_obstacle
13
+ int16[4] foot_force
14
+ float32[12] foot_position_body
15
+ float32[12] foot_speed_body
16
+
17
+
go2_interfaces/msg/TimeSpec.msg ADDED
@@ -0,0 +1,5 @@
 
 
 
 
 
 
1
+ # Time indicates a specific point in time, relative to a clock's 0 point.
2
+ # The seconds component, valid over all int32 values.
3
+ int32 sec
4
+ # The nanoseconds component, valid in the range [0, 10e9).
5
+ uint32 nanosec
go2_interfaces/msg/UwbState.msg ADDED
@@ -0,0 +1,19 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ uint8[2] version
2
+ uint8 channel
3
+ uint8 joy_mode
4
+ float32 orientation_est
5
+ float32 pitch_est
6
+ float32 distance_est
7
+ float32 yaw_est
8
+ float32 tag_roll
9
+ float32 tag_pitch
10
+ float32 tag_yaw
11
+ float32 base_roll
12
+ float32 base_pitch
13
+ float32 base_yaw
14
+ float32[2] joystick
15
+ uint8 error_state
16
+ uint8 buttons
17
+ uint8 enabled_from_app
18
+
19
+
go2_interfaces/msg/UwbSwitch.msg ADDED
@@ -0,0 +1 @@
 
 
1
+ uint8 enabled
go2_interfaces/msg/VoxelHeightMapState.msg ADDED
@@ -0,0 +1,14 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Timestamp (in seconds since epoch)
2
+ float64 stamp
3
+
4
+ # Timestamp for the point cloud (in seconds)
5
+ float64 stamp_cloud
6
+
7
+ # Timestamp for odometry (in seconds)
8
+ float64 stamp_odom
9
+
10
+ # Size of the height map
11
+ uint32 height_map_size
12
+
13
+ # Size of the voxel map
14
+ uint32 voxel_map_size
go2_interfaces/msg/VoxelMapCompressed.msg ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Timestamp (in seconds since epoch)
2
+ float64 stamp
3
+
4
+ # Frame ID for the coordinate frame
5
+ string frame_id
6
+
7
+ # Resolution of the voxel map
8
+ float64 resolution
9
+
10
+ # Origin of the voxel map (x, y, z)
11
+ float64[3] origin
12
+
13
+ # Width of the voxel map in each dimension (x, y, z)
14
+ int16[3] width
15
+
16
+ # Source size of the compressed data
17
+ uint64 src_size
18
+
19
+ # Compressed voxel data
20
+ uint8[] data
21
+
go2_interfaces/msg/WebRtcReq.msg ADDED
@@ -0,0 +1,10 @@
 
 
 
 
 
 
 
 
 
 
 
1
+ # message header id. if 0, it will be assigned automatically
2
+ int64 id
3
+ # topic name on dog's side including rt/ prefix
4
+ string topic
5
+ # api_id, see https://wiki.theroboverse.com/en/unitree-go2-app-console-commands#sending-commands-to-go2
6
+ int64 api_id
7
+ # payload for specific api_id
8
+ string parameter
9
+ # priority of the message. 0 non-priority, 1 priority
10
+ uint8 priority
go2_interfaces/msg/WirelessController.msg ADDED
@@ -0,0 +1,5 @@
 
 
 
 
 
 
1
+ float32 lx
2
+ float32 ly
3
+ float32 rx
4
+ float32 ry
5
+ uint16 keys