Step 0 — Ground rules (what must be true)
For SLAM to work you must have ALL 3:
LaserScan data (you have it on /robot_0/base_scan) âś…
TF transforms exist (at least a transform from robot base to laser, and odom-related TF) âť—
Time is consistent (you have /clock, so we use use_sim_time:=True) âś…
Your current blocker is almost certainly (2) TF. We’ll verify it early (Step 3).
Step 1 — Open 3 terminals (recommended layout)
T1 = Stage simulation
T2 = Throttle tool
T3 = SLAM toolbox
(Optionally T4 = RViz)
In every terminal, run:
source /opt/ros/jazzy/setup.bash
source ~/nav_class_ws/install/setup.bashStep 2 — Start Stage (your demo)
Terminal T1:
ros2 launch stage_ros2 demo.launch.py one_tf_tree:=trueWait until Stage window + RViz window appear (or Stage only if your launch is different).
Step 3 — Quick health check (DO NOT SKIP)
3.1 Check sim time exists
ros2 topic echo /clock --once✅ If it prints → we will use use_sim_time:=True.
3.2 Check LaserScan exists (your known working topic)
ros2 topic echo /robot_0/base_scan --onceâś… Must print.
3.3 Check TF exists (this is the BIG ONE)
Run:
ros2 topic list | egrep "^/tf$|^/tf_static$"Then:
ros2 topic echo /tf --once
ros2 topic echo /tf_static --onceInterpret
✅ If /tf prints something → TF is alive → go to Step 4
❌ If /tf hangs and /tf_static hangs → TF is NOT being published → go to Step 3.4 (TF Fix)
3.4 TF Fix (only if TF is dead)(Go to the solution https://ihsumlee.sytes.net/node/12)
Step 4 — Performance improvement: Throttle scan (10 Hz)
Terminal T2 (leave it running, it stays silent—this is normal):
sudo apt update
sudo apt install -y ros-jazzy-topic-tools
ros2 run topic_tools throttle messages /robot_0/base_scan 10.0 /robot_0/base_scan_throttleVerify it works (in any other terminal):
ros2 topic echo /robot_0/base_scan_throttle --onceâś… Must print.
Step 5 — Prepare SLAM params file (clean + stable)
Create config folder and copy default params:
mkdir -p ~/nav_class_ws/config
cp /opt/ros/jazzy/share/slam_toolbox/config/mapper_params_online_async.yaml \
~/nav_class_ws/config/mapper_params_stage.yamlEdit:
nano ~/nav_class_ws/config/mapper_params_stage.yamlInside, set these values (exactly):
slam_toolbox:
ros__parameters:
use_sim_time: true
scan_topic: /robot_0/base_scan_throttle
map_frame: map
tf_buffer_duration: 30.0We don’t set base_frame/odom_frame yet because your TF frame names may be namespaced. We’ll set them only if needed.
Save and exit.
Step 6 — Start SLAM Toolbox
Terminal T3:
ros2 launch slam_toolbox online_async_launch.py \
slam_params_file:=/home/lee/nav_class_ws/config/mapper_params_stage.yamlWhat you should NOT see repeatedly
“No tf data received”
“Invalid frame ID … frame does not exist”
“timestamp earlier than all the data in the transform cache” nonstop
A few drops are OK on VM, but not nonstop. if you do not have message from /map, please fix it on (https://ihsumlee.sytes.net/node/13)
Step 7 — Confirm map is being published
In a new terminal:
ros2 topic echo /map --once✅ If it prints → map is working.
If it hangs, then SLAM still can’t process scans due to TF mismatch. Go to Step 7.1.
Step 7.1 — If /map hangs, identify the real TF frame names
Run:
ros2 run tf2_tools view_framesIf the PDF says “No tf data received” → TF is dead → go back to Step 3.4 TF Fix.
If frames exist, look for:
odom frame name (maybe robot_0/odom)
base frame name (maybe robot_0/base_link or base_link)
laser frame name (you saw it is laser)
Then update your params file to include:
odom_frame: robot_0/odom
base_frame: robot_0/base_link(Use the names from your TF graph.)
Restart SLAM.
Step 8 — RViz settings (stable on VM)
In RViz:
8.1 Fixed Frame
If SLAM is running: set Fixed Frame to map
If SLAM not yet stable: use robot_0/odom (or whichever odom exists)
Yes — you can type it manually if it doesn’t appear, but it must be a real TF frame.
8.2 Displays
Add Map: topic /map
Add LaserScan: topic /robot_0/base_scan (or throttle)
Optional: Odometry /robot_0/odom
8.3 Performance
Turn TF display OFF
LaserScan: increase Queue Size (RViz2 calls it “Queue Size” or “Filter size” depending on plugin; if not visible, scroll in LaserScan display)
Global Options → Frame Rate: set to 10
Step 9 — Save the map (.pgm + .yaml)
When you are happy with the built map:
ros2 run nav2_map_server map_saver_cli -f ~/nav_class_ws/maps/my_mapThis creates:
my_map.yaml
my_map.pgm
Step 10 — (Later) Use the saved map for navigation
You can load it in Nav2 (when you teach Part 3).
The ONE thing I need from you (so you don’t get stuck again)
When you said “No tf data received” before, that means SLAM will never work.
So please run just this and paste the output:
ros2 topic list | egrep "^/tf$|^/tf_static$"
ros2 topic echo /tf --once
ros2 node list | head -n 30With that, I can tell you immediately whether your Stage launch is missing TF publishers, and give the exact fix (without confusion).
If you want, you can also paste your demo.launch.py and I’ll point to the exact lines to add robot_state_publisher (the real root fix).