How to run it
All commands run from the repo root on the host. The stack is the same Docker image; only which services you start differs.
main — engine + mock robot (no navigation)
Build once, start the engine and the fake robot, then run the example trees. The palette page you are reading is served by that engine.
docker compose -f docker/compose.yaml build dev docker compose -f docker/compose.yaml run --rm dev ./scripts/build.sh docker compose -f docker/compose.yaml up -d engine mocks ./scripts/bt_exec.py run examples/find_and_grab_cup.xml # expect: success ./scripts/bt_exec.py run examples/find_missing_bottle.xml # expect: failure + reason ./scripts/bt_exec.py run examples/bad_hallucinated.xml # expect: 422, nothing runs
Make the mock misbehave while it runs, to test recovery branches:
docker compose -f docker/compose.yaml exec mocks bash ros2 param set /mock_robot fail.navigate_to_object 1.0 ros2 param set /mock_robot delay.visualize_object 3.0 ros2 param set /mock_robot objects "['cup','bottle']"
Nav2, obstacle map UI and simulated robot
Same workspace, more services. Start everything. The mock hands its navigation servers over to the real Nav2 stack; USE_RVIZ=true opens RViz.
MOCK_DISABLE=navigate_to_object,rotate_in_place,is_at_object USE_RVIZ=true \ docker compose -f docker/compose.yaml --profile sim up -d engine mocks map nav-sim
Obstacle map UI: http://localhost:8081/ — drag to draw obstacles, Nav2 sees them within about half a second.
Tests (about 2 minutes for the end-to-end ones):
./scripts/test_nav_sim.py # 9 end-to-end tests through Nav2 ./scripts/test_nav_sim.py detour # only tests whose name matches docker compose -f docker/compose.yaml run --rm \ -e PYTHONPATH=/home/main/mc_main_nav/ws/src/diff_nav:/home/main/mc_main_nav/ws/src/table_map dev \ bash -c 'source /opt/ros/humble/setup.bash && python3 -m pytest -q ws/src/diff_nav/test ws/src/table_map/test'
RViz on its own (also works against the real robot on the same ROS_DOMAIN_ID):
docker compose -f docker/compose.yaml --profile gui run --rm rviz
On the robot Raspberry Pi instead of the simulator:
docker compose -f docker/compose.yaml --profile robot up -d nav
Stop everything
docker compose -f docker/compose.yaml --profile sim --profile gui --profile robot down