diff --git a/dimos/mapping/utils/cli/map.py b/dimos/mapping/utils/cli/map.py index 5565075ab8..cae3e04114 100644 --- a/dimos/mapping/utils/cli/map.py +++ b/dimos/mapping/utils/cli/map.py @@ -97,16 +97,16 @@ def _accumulate( block_count: int, device: str, graph: PoseGraph | None = None, - world_frame: bool = False, + world_frame: bool = True, carve_columns: bool = False, progress_cb: Callable[[Observation[Any]], None] | None = None, ) -> PointCloud2 | None: """Accumulate a voxel map from `obs_iter`, optionally PGO-correcting each frame. - By default each frame's per-frame pose is applied to register the (sensor/body - frame) cloud into the world. Set ``world_frame=True`` (the ``--go2`` path) when - the clouds are already world-registered (e.g. fastlio) — then only the PGO - correction is applied, if any. + By default the clouds are assumed already world-registered (the go2/fastlio + path) — only the PGO correction is applied, if any. Set ``world_frame=False`` + (the ``--use-tf`` path) when each frame's cloud is in the sensor/body frame + and must be registered into the world via its per-frame pose. Returns the final ``PointCloud2`` (or ``None`` if the input was empty). Disposal of the underlying ``VoxelGrid`` is handled by ``VoxelMapTransformer``. @@ -133,7 +133,7 @@ def prepared() -> Iterable[Observation[PointCloud2]]: if len(obs.data) == 0: continue # body->world via the per-frame pose, unless the clouds are already - # world-registered (--go2). graph adds the PGO correction on top + # world-registered (go2 default). graph adds the PGO correction on top # (correction ∘ pose), applied after the pose. tf: Transform | None = None if not world_frame: @@ -328,11 +328,11 @@ def main( None, "--out", help="Output .rrd path (default: ./.rrd)" ), no_gui: bool = typer.Option(False, "--no-gui", help="Write the .rrd but don't launch rerun"), - go2: bool = typer.Option( + use_tf: bool = typer.Option( False, - "--go2", - help="Clouds are already world-registered (e.g. fastlio); skip applying the " - "per-frame pose. Default registers each (body-frame) cloud by its pose.", + "--use-tf", + help="Clouds are in the sensor/body frame; register each by its per-frame pose. " + "By default clouds are assumed already world-registered (e.g. go2/fastlio).", ), carve: bool = typer.Option( False, @@ -470,7 +470,7 @@ def main( block_count=block_count, device=device, graph=graph, - world_frame=go2, + world_frame=not use_tf, carve_columns=carve, progress_cb=progress(n_kept, "pgo pass 2 (rebuilding)"), ) @@ -484,7 +484,7 @@ def main( block_count=block_count, device=device, graph=graph, - world_frame=go2, + world_frame=not use_tf, carve_columns=carve, progress_cb=progress(total, "full pgo (rebuilding)"), ) @@ -495,7 +495,7 @@ def main( voxel=voxel, block_count=block_count, device=device, - world_frame=go2, + world_frame=not use_tf, carve_columns=carve, progress_cb=progress(n_kept, "reconstructing global map"), ) diff --git a/dimos/robot/unitree/go2/blueprints/smart/unitree_go2.py b/dimos/robot/unitree/go2/blueprints/smart/unitree_go2.py index d1162270d2..9993e541c4 100644 --- a/dimos/robot/unitree/go2/blueprints/smart/unitree_go2.py +++ b/dimos/robot/unitree/go2/blueprints/smart/unitree_go2.py @@ -21,7 +21,8 @@ from dimos.mapping.costmapper import CostMapper from dimos.mapping.relocalization.module import RelocalizationModule from dimos.mapping.voxels import VoxelGridMapper -from dimos.memory2.module import Recorder, RecorderConfig +from dimos.memory2.module import Recorder, RecorderConfig, pose_setter_for +from dimos.msgs.geometry_msgs.Pose import Pose from dimos.msgs.geometry_msgs.PoseStamped import PoseStamped from dimos.msgs.sensor_msgs.Image import Image from dimos.msgs.sensor_msgs.PointCloud2 import PointCloud2 @@ -58,6 +59,17 @@ class Go2Memory(Recorder): odom: In[PoseStamped] config: Go2MemoryConfig + _last_odom_pose: Pose | None = None + + @pose_setter_for("odom") + def _odom_pose(self, msg: PoseStamped) -> Pose | None: + self._last_odom_pose = msg + return self._last_odom_pose + + @pose_setter_for("lidar") + def _lidar_pose(self, msg: PointCloud2) -> Pose | None: + return self._last_odom_pose # should always exist (odom alwyas wins the race) + unitree_go2_markers = ( autoconnect( diff --git a/docs/docs.json b/docs/docs.json index 59142b59c0..462a0064fa 100644 --- a/docs/docs.json +++ b/docs/docs.json @@ -136,7 +136,15 @@ { "group": "Quadruped", "pages": [ - "platforms/quadruped/go2/index" + { + "group": "Unitree Go2", + "pages": [ + "platforms/quadruped/go2/index", + "platforms/quadruped/go2/setup", + "platforms/quadruped/go2/simulation", + "platforms/quadruped/go2/premap" + ] + } ] }, { diff --git a/docs/capabilities/mapping/assets/reloc_and_nav_to.webp b/docs/platforms/quadruped/go2/assets/reloc_and_nav_to.webp similarity index 100% rename from docs/capabilities/mapping/assets/reloc_and_nav_to.webp rename to docs/platforms/quadruped/go2/assets/reloc_and_nav_to.webp diff --git a/docs/platforms/quadruped/go2/index.md b/docs/platforms/quadruped/go2/index.md index 4e392f06ca..49067376b6 100644 --- a/docs/platforms/quadruped/go2/index.md +++ b/docs/platforms/quadruped/go2/index.md @@ -1,150 +1,19 @@ -# Unitree Go2 — Getting Started +# Unitree Go2 Quick Start -The Unitree Go2 is DimOS's primary reference platform. Full autonomous navigation, mapping, and agentic control — no ROS required. - -## Requirements - -- Unitree Go2 Pro or Air (stock firmware 1.1.7+, no jailbreak needed) -- Ubuntu 22.04/24.04 with CUDA GPU (recommended), or macOS (experimental) -- Python 3.12 - -## Install - -First, install system dependencies for your platform: -- [Ubuntu](/docs/installation/ubuntu.md) -- [macOS](/docs/installation/osx.md) -- [Nix](/docs/installation/nix.md) - -Then install DimOS: - -```bash -uv venv --python "3.12" -source .venv/bin/activate -uv pip install 'dimos[base,unitree]' -``` - -## Try It — No Hardware Needed - -```bash -# Replay a recorded Go2 navigation session -# First run downloads ~2.4 GB of LiDAR/video data from LFS -dimos --replay run unitree-go2 -``` - -Opens the command center at [localhost:7779](http://localhost:7779) with Rerun 3D visualization — watch the Go2 map and navigate an office in real time. - -## Run on Your Go2 - -### First-time setup, connecting to wifi, finding robot IP - -Use `dimos go2tool` to provision wifi and find the robot's IP. Skip if the robot is already on your network and you know its IP. - -1. Power on the Go2 — it advertises over BLE immediately. - -2. Provision wifi (one-time per network): - -optionally use discover to make sure robot is detected - -```bash -dimos go2tool discover -``` - -configure wifi - -```bash -dimos go2tool connect-wifi --ssid --password -``` - -Scans BLE and connects to the only robot it finds, or prompts you to pick if there are several. - -3. Find the robot's IP: - -```bash -dimos go2tool discover -``` - -Prints `SOURCE NAME IP MAC SERIAL` for every robot it sees over BLE and LAN. Export the IP: - -```bash -export ROBOT_IP= -``` - -### Pre-flight checks - -1. Robot is reachable and low latency `<10ms`, 0% packet loss -```bash -ping $ROBOT_IP -``` - -2. Built-in obstacle avoidance is on. (DimOS handles path planning, but the onboard obstacle avoidance provides an extra safety layer around tight spots) - -### Ready to run DimOS - -```bash -export ROBOT_IP= -dimos run unitree-go2 -``` - -That's it. DimOS connects via WebRTC (no jailbreak required), starts the full navigation stack, and opens the command center in your browser. - -### What's Running - -| Module | What It Does | -|--------|-------------| -| **GO2Connection** | WebRTC connection to the robot — streams LiDAR, video, odometry | -| **VoxelGridMapper** | Builds a 3D voxel map using column-carving (CUDA accelerated) | -| **CostMapper** | Converts 3D map → 2D costmap via terrain slope analysis | -| **ReplanningAStarPlanner** | Continuous A* path planning with dynamic replanning | -| **WavefrontFrontierExplorer** | Autonomous exploration of unmapped areas | -| **RerunBridge** | 3D visualization in browser | -| **WebsocketVis** | Command center at localhost:7779 | - -### Send Goals - -From the command center ([localhost:7779](http://localhost:7779)): -- Click on the map to set navigation goals -- Toggle autonomous exploration -- Monitor robot pose, costmap, and planned path - -## MuJoCo Simulation - -```bash -uv pip install 'dimos[base,unitree,sim]' -dimos --simulation run unitree-go2 -``` - -Full navigation stack in MuJoCo — same code, simulated robot. - -## Agentic Control - -Natural language control with an LLM agent that understands physical space: - -```bash -export OPENAI_API_KEY= -export ROBOT_IP= -dimos run unitree-go2-agentic -``` - -Then use the human CLI to talk to the agent: - -```bash -humancli -> explore the space -``` - -The agent subscribes to camera, LiDAR, and spatial memory streams — it sees what the robot sees. +- [Setup your Dog](/docs/platforms/quadruped/go2/setup.md) — requirements, install, connecting to your Go2, and agentic control +- [Simulation](/docs/platforms/quadruped/go2/simulation.md) — try it with no hardware via replay or MuJoCo +- [Record & Load Maps](/docs/platforms/quadruped/go2/premap.md) — record a run, export a premap, and relocalize on replay or a live Go2 ## Available Blueprints | Blueprint | Description | |-----------|-------------| -| `unitree-go2-basic` | Connection + visualization (no navigation) | -| `unitree-go2` | Full navigation stack | -| `unitree-go2-agentic` | Navigation + LLM agent + MCP tool access | -| `unitree-go2-agentic-ollama` | Agent with local Ollama models | -| `unitree-go2-spatial` | Navigation + spatial memory | -| `unitree-go2-detection` | Navigation + object detection | -| `unitree-go2-ros` | ROS 2 bridge mode | +| `dimos run unitree-go2-basic` | Connection + visualization (no navigation) | +| `dimos run unitree-go2` | Full navigation stack | +| `dimos run unitree-go2-agentic` | Navigation + LLM agent + MCP tool access | +| `dimos run unitree-go2-agentic-ollama` | Agent with local Ollama models | +| `dimos run unitree-go2-spatial` | Navigation + spatial memory | +| `dimos run unitree-go2-detection` | Navigation + object detection | ## Deep Dive diff --git a/docs/capabilities/mapping/relocalization.md b/docs/platforms/quadruped/go2/premap.md similarity index 86% rename from docs/capabilities/mapping/relocalization.md rename to docs/platforms/quadruped/go2/premap.md index a7fef58ccd..714f0c3044 100644 --- a/docs/capabilities/mapping/relocalization.md +++ b/docs/platforms/quadruped/go2/premap.md @@ -1,10 +1,10 @@ -# Relocalization - -This walkthrough shows the pre-map capabilities, including how to record, -export a premap from a mem2 `.db`, and run the robot with relocalization -enabled. You can also navigate to a place the robot hasn't visited during -this run, as long as it's part of the global map. +# Creating a Map +Main steps: +1. `dimos run unitree-go2-memory` to create a .db file +2. Auto-clean the .db file into a usable map +3. Load the map back (replay) +4. Load the map into the Go2 (live) ![relocalize on the live go2 and nav_to a point in the premap](assets/reloc_and_nav_to.webp) @@ -15,6 +15,7 @@ this run, as long as it's part of the global map. dimos --robot-ip {YOUR_ROBOT_IP} run unitree-go2-memory ``` + If `DIMOS_ROBOT_IP` is set in your environment (or `.env`), you can drop the `--robot-ip` flag: @@ -27,16 +28,16 @@ from the repo root so the bare-name lookup finds this file. In the next steps `{DB_NAME}` refers to the stem of your recording - `recording_go2` if you kept the default. -## 2. Export the premap +## 2. Auto-clean the .db, convert into a Map -Convert the recording to a relocalization premap (`.pc2.lcm`): +To create the map file (`.pc2.lcm`): ```bash # default name from step 1: -dimos map recording_go2 --export +dimos map global recording_go2 --export # renamed: -dimos map {DB_NAME} --export +dimos map global {DB_NAME} --export ``` `--export` implies `--pgo` (runs pose graph optimization) and writes @@ -53,10 +54,10 @@ When a bare file name is given, the tool searches in: Examples: ```bash -dimos map go2_hongkong_office --export -dimos map ./go2_hongkong_office.db --export -dimos map data/go2_hongkong_office.db --export -dimos map /abs/path/to/scan.db --export +dimos map global go2_hongkong_office --export +dimos map global ./go2_hongkong_office.db --export +dimos map global data/go2_hongkong_office.db --export +dimos map global /abs/path/to/scan.db --export ``` Sample log: diff --git a/docs/platforms/quadruped/go2/setup.md b/docs/platforms/quadruped/go2/setup.md new file mode 100644 index 0000000000..26b87ddd45 --- /dev/null +++ b/docs/platforms/quadruped/go2/setup.md @@ -0,0 +1,116 @@ +# Unitree Go2 — Setup + +Full autonomous navigation, mapping, and agentic control on a real Go2 — no ROS required. + +## Requirements + +- Unitree Go2 Pro or Air (stock firmware 1.1.7+, no jailbreak needed) +- Ubuntu 22.04/24.04 with CUDA GPU (recommended), or macOS (experimental) +- Python 3.12 + +## Install + +First, install system dependencies for your platform: +- [Ubuntu](/docs/installation/ubuntu.md) +- [macOS](/docs/installation/osx.md) +- [Nix](/docs/installation/nix.md) + +Then install DimOS: + +```bash +uv venv --python "3.12" +source .venv/bin/activate +uv pip install 'dimos[base,unitree]' +``` + +## Run on Your Go2 + +### First-time setup, connecting to wifi, finding robot IP + +Use `dimos go2tool` to provision wifi and find the robot's IP. Skip if the robot is already on your network and you know its IP. + +1. Power on the Go2 — it advertises over BLE immediately. + +2. Provision wifi (one-time per network): + +optionally use discover to make sure robot is detected + +```bash +dimos go2tool discover +``` + +configure wifi + +```bash +dimos go2tool connect-wifi --ssid --password +``` + +Scans BLE and connects to the only robot it finds, or prompts you to pick if there are several. + +3. Find the robot's IP: + +```bash +dimos go2tool discover +``` + +Prints `SOURCE NAME IP MAC SERIAL` for every robot it sees over BLE and LAN. Export the IP: + +```bash +export ROBOT_IP= +``` + +### Pre-flight checks + +1. Robot is reachable and low latency `<10ms`, 0% packet loss +```bash +ping $ROBOT_IP +``` + +2. Built-in obstacle avoidance is on. (DimOS handles path planning, but the onboard obstacle avoidance provides an extra safety layer around tight spots) + +### Ready to run DimOS + +```bash +export ROBOT_IP= +dimos run unitree-go2 +``` + +That's it. DimOS connects via WebRTC (no jailbreak required), starts the full navigation stack, and opens the command center in your browser. + +### What's Running + +| Module | What It Does | +|--------|-------------| +| **GO2Connection** | WebRTC connection to the robot — streams LiDAR, video, odometry | +| **VoxelGridMapper** | Builds a 3D voxel map using column-carving (CUDA accelerated) | +| **CostMapper** | Converts 3D map → 2D costmap via terrain slope analysis | +| **ReplanningAStarPlanner** | Continuous A* path planning with dynamic replanning | +| **WavefrontFrontierExplorer** | Autonomous exploration of unmapped areas | +| **RerunBridge** | 3D visualization in browser | +| **WebsocketVis** | Command center at localhost:7779 | + +### Send Goals + +From the command center ([localhost:7779](http://localhost:7779)): +- Click on the map to set navigation goals +- Toggle autonomous exploration +- Monitor robot pose, costmap, and planned path + +## Agentic Control + +Natural language control with an LLM agent that understands physical space: + +```bash +export OPENAI_API_KEY= +export ROBOT_IP= +dimos run unitree-go2-agentic +``` + +Then use the human CLI to talk to the agent: + +```bash +humancli +> explore the space +``` + +The agent subscribes to camera, LiDAR, and spatial memory streams — it sees what the robot sees. diff --git a/docs/platforms/quadruped/go2/simulation.md b/docs/platforms/quadruped/go2/simulation.md new file mode 100644 index 0000000000..3f97423ec2 --- /dev/null +++ b/docs/platforms/quadruped/go2/simulation.md @@ -0,0 +1,24 @@ +# Unitree Go2 — Simulation + +Run the full Go2 navigation stack without any hardware — replay recorded sessions or simulate in MuJoCo. Same code, no robot. + +See [Setup](/docs/platforms/quadruped/go2/setup.md) for installing DimOS first. + +## Try It — No Hardware Needed + +```bash +# Replay a recorded Go2 navigation session +# First run downloads ~2.4 GB of LiDAR/video data from LFS +dimos --replay run unitree-go2 +``` + +Opens the command center at [localhost:7779](http://localhost:7779) with Rerun 3D visualization — watch the Go2 map and navigate an office in real time. + +## MuJoCo Simulation + +```bash +uv pip install 'dimos[base,unitree,sim]' +dimos --simulation run unitree-go2 +``` + +Full navigation stack in MuJoCo — same code, simulated robot.