This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
This project uses Pixi as its package manager (conda-based) with ROS 2 Jazzy packages from the robostack-jazzy channel. All commands should be run via pixi run <task> from the project root.
The robot model is fixed to TURTLEBOT3_MODEL=waffle_pi (set in pixi.toml).
pixi run mapping # Full stack: Gazebo + async SLAM + Nav2 + RViz (for mapping)
pixi run nav # Full stack: Gazebo + AMCL + Nav2 on pre-saved map
pixi run teleop # Keyboard teleoperation
pixi run savemap # Save current map to map.yaml / map.pgmThere is no build step — this project consists of launch files and configuration only.
Two primary workflows:
- Gazebo —
turtlebot3_houseworld - slam_toolbox (async) — builds occupancy grid; tuned via
config/slam_params.yaml - Nav2 (
navigation_launch.py) — planner/controller/BT for waypoint driving while mapping - RViz2 — custom config (
config/mapping.rviz) with SLAM pose graph display
SLAM provides the map→odom transform. No AMCL.
- Gazebo — same world
- AMCL + map_server (
localization_launch.py) — localisation against a saved map - Nav2 (
navigation_launch.py) — planner/controller/BT - RViz2 — nav2 default view
AMCL provides localisation. No SLAM.
| File | Purpose |
|---|---|
pixi.toml |
Task definitions, dependencies, env vars |
launch/mapping.launch.py |
Top-level SLAM mapping launch |
launch/nav.launch.py |
Top-level navigation launch |
launch/components/ |
Composable single-component launch files |
config/slam_params.yaml |
slam_toolbox tuning |
config/nav2_params.yaml |
Full Nav2 params (all 10 lifecycle nodes) |
config/mapping.rviz |
RViz config for mapping with SLAM graph display |
navigation_launch.py in Jazzy manages 10 lifecycle nodes including docking_server (from opennav_docking). This node hard-fails on configure if dock_plugins is not explicitly set — it does not default to empty. config/nav2_params.yaml must include:
docking_server:
ros__parameters:
dock_plugins: ['simple_charging_dock']
simple_charging_dock:
plugin: 'opennav_docking::SimpleChargingDock'Notable non-default values:
loop_search_maximum_distance: 1.5(default 10.0)loop_match_minimum_response_fine: 0.65(default 0.35)loop_match_minimum_response_coarse: 0.45(default 0.35)debug_logging: true— enables Ceres solver summaries; high initial cost in output indicates a false loop closure was accepted- Solver:
CeresSolverwithSPARSE_NORMAL_CHOLESKY