You already have:
a saved map: classroom_map.yaml + classroom_map.pgm
TF frames (from view_frames):
robot_0/odom → robot_0/base_link → robot_0/laser
We will do map-based navigation using AMCL + Nav2.
Step 0 — Files & assumptions
Assume your saved map is here:
~/nav_class_assets/maps/classroom_map_simple.yaml
If not, locate it:
ls ~/nav_class_assets/mapsMake a directory inside nav_claass_assets, called worlds. Move to "worlds" and make a directory "include".
mkdir worlds
cd worlds
Download robot.inc and classroom.worl and place them in the "worlds" directory. (change robot.inc.txt to robot.inc)
mkdir include directory
cd include
download pioneer2dx.inc and place it in the "include" directory. (change pioneer2dx.inc.txt to robot.inc)
Step 1 — Launch Stage with standard TF topics
Terminal 1:
source /opt/ros/jazzy/setup.bash
source ~/nav_class_ws/install/setup.bash
ros2 launch stage_ros2 stage.launch.py world:=/home/lee/nav_class_assets/worlds/classroom enforce_prefixes:=false(Optional but recommended for VMs) throttle scan:
Terminal 2:
source /opt/ros/jazzy/setup.bash
ros2 run topic_tools throttle messages /base_scan 10.0 /scanStep 2 — Prepare a Nav2 params file for robot_0 (one-time)
Install Nav2 if you do not have one. (Link)
1) Make sure the map YAML is valid
Run:
ls -lh /home/lee/nav_class_assets/maps/classroom_map.yaml
sed -n '1,50p' /home/lee/nav_class_assets/maps/classroom_map.yamlA valid map YAML must look like this (example):
image: classroom_map_simple.pgm
mode: trinary
resolution: 0.05
origin: [-10.0, -7.5, 0.0]
negate: 0
occupied_thresh: 0.65
free_thresh: 0.25Most common mistake
image: points to a .pgm that doesn’t exist in the same folder.
Check:
grep '^image:' /home/lee/nav_class_assets/maps/classroom_map.yaml
ls -lh /home/lee/nav_class_assets/maps/If image: classroom_map_simple.pgm, then that file must exist in the same directory:
/home/lee/nav_class_assets/maps/classroom_map.pgm.
âś… If you want zero risk, use the downloaded map you already have (e.g. classroom_map_simple.yaml + .pgm) and set map:=... in the launch command.
2) Make sure Nav2 params file is complete (missing DWB critics)
The error No critics defined for FollowPath happens when your params file does not include the DWB controller configuration block.
✅ Easiest fix: copy Nav2’s default params file and then only modify the few lines you need (frames + scan topic).
Step 2.1 Copy the default Nav2 params
mkdir -p ~/nav_class_assets/nav2
cp /opt/ros/jazzy/share/nav2_bringup/params/nav2_params.yaml \
~/nav_class_assets/nav2/nav2_stage_robot0.yamlThis default file includes the DWB critics list, so the controller will configure correctly.
Step 2.2 Edit only the required lines
Open it by vim or gedit:
vim ~/nav_class_assets/nav2/nav2_stage_robot0.yamlNow change these keys (search with Ctrl+W in nano):
(A) use_sim_time
Set use_sim_time: true for all servers (or at least for amcl/map_server/nav2 stack). In a VM sim with /clock, it should be true.
(B) Map file
Find yaml_filename: under map_server: and set it to your downloaded map:
map_server:
ros__parameters:
use_sim_time: true
yaml_filename: /home/lee/nav_class_assets/maps/classroom_map.yaml(C) AMCL scan topic + frames (robot_0 namespace)
Find AMCL section and set:
amcl:
ros__parameters:
use_sim_time: true
base_frame_id: base_link
odom_frame_id: odom
global_frame_id: map
scan_topic: /scan
set_initial_pose: true
initial_pose:
x: 0.0
y: 0.0
yaw: 0.0(D) Costmap robot_base_frame
Search robot_base_frame: and set to:
robot_base_frame: base_link(E) Local costmap global frame
Set local costmap global_frame to:
global_frame: odom
robot_base_frame: base_link
width: 3 (but 3.0)
height: 3 (but 3.0)
(F) Map server
map_server: ros__parameters: use_sim_time: true yaml_filename: /home/lee/nav_class_assets/maps/classroom_map.yaml
(G)Add lifecycle manager navigation
lifecycle_manager_localization:
ros__parameters:
use_sim_time: true
autostart: true
node_names: ["map_server", "amcl"]
lifecycle_manager_navigation:
ros__parameters:
use_sim_time: true
autostart: true
node_names:
- controller_server
- planner_server
- behavior_server
- bt_navigator
- waypoint_follower
- velocity_smoother
- collision_monitor
- smoother_server
- route_server
- docking_server
That’s it. Do not delete the controller_server section — it contains the DWB critics.
Problem solved: [link]
3) Launch Nav2 with an explicit
map:=..argument (recommended)
This avoids relying only on yaml_filename in the params file and helps debugging.
Quick verification checklist (after launch)
In a new terminal:
1) Map is published
ros2 topic echo /map --once2) Controller server is active (no “critics” error)
ros2 node list | grep controlle3) Nav2 cmd_vel is being published when you send a goal
ros2 topic list | grep cmd_velStep 3 — Start Nav2 localization + navigation
Terminal 3:
source /opt/ros/jazzy/setup.bashros2 launch nav2_bringup bringup_launch.py params_file:=/home/lee/nav_class_assets/nav2/nav2_stage_robot0.yaml use_sim_time:=True use_composition:=False autostart:=True
This brings up
map_server
AMCL
Nav2 stack
Step 4 — Open RViz and load Nav2 config
Terminal 4:
source /opt/ros/jazzy/setup.bash rviz2
orLIBGL_ALWAYS_SOFTWARE=1 rviz2 --ros-args -p use_sim_time:=true
In RViz:
- Fixed Frame = map
- Add displays:
- Map topic: /map
- LaserScan topic: /scan
- TF
Step 5 — Initialize localization (must do)
Before doing initialization, please open a terminal to bridge /cmd_vel_nav to /cmd_vel.
ros2 run topic_tools relay /cmd_vel_nav /cmd_vel
AMCL needs an initial pose.
In RViz:
Click “2D Pose Estimate”
Click on the map near where robot_0 actually is
Drag to set its heading (arrow direction)
Wait a few seconds — you should see the AMCL pose stabilize.
Step 6 — Send a navigation goal
In RViz:
Click “Nav2 Goal” (or “2D Goal Pose” depending on RViz toolbar)
Click a target on the map
Drag to set goal heading
Robot should plan and start moving.
Quick troubleshooting checklist (most common issues)
A) Robot doesn’t move
Check cmd_vel:
ros2 topic echo /robot_0/cmd_vel --onceIf nothing is published, Nav2 controller isn’t active (or bringup failed).
B) “No transform” errors
Confirm frames exist:
ros2 run tf2_tools view_framesMake sure your params match the real frames:
robot_0/base_link
robot_0/odom
C) AMCL not updating / no laser
ros2 topic echo /robot_0/base_scan_throttle --onceIf no message, fix throttle topic or use /robot_0/base_scan.
D) Robot doesn’t move
ros2 topic echo /robot_0/cmd_vel --onceE) Laser not reaching Nav2
ros2 topic echo /robot_0/base_scan_throttle --onceF) TF missing (must use one_tf_tree:=true)
ros2 topic echo /tf --onceF) AMCL not publishing map→robot_0/odom, so map frame missing
Cannot set Fixed Frame = map [Solution]
Small improvement for class stability
Because your Stage demo runs 3 robots, focus on robot_0 only:
turn off robot_1/robot_2 displays in RViz
If you tell me the exact filename of your saved map (and confirm the path), I can give you a fully copy-paste “bringup” command with no hardcoded /home/lee (using $HOME instead).
Download maps:
Download them here: (See also the maps in the attachments)