Position in the full course
This is the ninth step of the course.
The full learning order is:
1. ROS 2 node/topic/launch review
2. TF2 frame concept
3. Static sensor frames
4. Dynamic odometry frame
5. URDF + robot_state_publisher
6. SLAM mapping
7. AMCL localization
8. Nav2 path planning
9. RViz goal navigation
10. TF2 debugging in Nav2
In Step 8, you checked Nav2 path planning using command-line actions.
In Step 9, you will use RViz2 to send a navigation goal.
The main goal is:
Use RViz2 to set the robot initial pose.
Use RViz2 to send a navigation goal.
Observe Nav2 planning, control, and robot movement.
1. Learning objectives
After this module, you should be able to:
- Explain the purpose of RViz2 in Nav2 navigation.
- Set the robot initial pose using 2D Pose Estimate.
- Send a navigation goal using Nav2 Goal or 2D Goal Pose.
- Observe the global path in RViz2.
- Observe local and global costmaps.
- Observe robot motion toward the goal.
- Check
/navigate_to_poseaction feedback. - Check
/cmd_veloutput. - Understand the difference between planning and full navigation.
- Debug common RViz goal navigation problems.
2. Suggested teaching duration
Suggested duration: 2 hours
| Time | Activity |
| ----------- | -------------------------------------- |
| 0β15 min | Review Step 8 Nav2 planning |
| 15β30 min | Explain RViz2 navigation workflow |
| 30β45 min | Launch map, AMCL, and Nav2 |
| 45β60 min | Configure RViz2 displays |
| 60β75 min | Set initial pose |
| 75β95 min | Send navigation goal |
| 95β110 min | Observe path, costmaps, and /cmd_vel |
| 110β120 min | Summary and homework |
3. What RViz2 does in Nav2
RViz2 is a visualization and interaction tool.
In Nav2, you use RViz2 to:
view the map
view the robot model
view TF frames
view LiDAR scan
view costmaps
view planned path
set the initial pose
send a navigation goal
monitor navigation behavior
RViz2 does not control the robot directly.
Instead, RViz2 sends requests to Nav2.
For example:
RViz2 goal tool
β
NavigateToPose action
β
BT Navigator
β
Planner Server
β
Controller Server
β
/cmd_vel
β
Robot moves
4. Review: what must work before using RViz goal navigation
Before you send a goal in RViz2, you should already have:
map loaded
AMCL localization working
Nav2 navigation stack active
TF tree connected
LiDAR scan available
odometry available
/cmd_vel accepted by robot or simulation
Check these commands first:
ros2 topic echo /map --once
ros2 topic echo /scan --once
ros2 topic echo /odom --once
ros2 run tf2_ros tf2_echo map base_link
ros2 action list | grep navigate
You should see:
/navigate_to_pose
5. Target TF tree
Before full navigation, your TF tree should look like this:
map
βββ odom
βββ base_link
βββ base_laser
βββ camera_link
βββ imu_link
Meaning:
| Transform | Usually published by |
| ------------------------- | ------------------------ |
| map β odom | AMCL |
| odom β base_link | odometry |
| base_link β base_laser | URDF or static transform |
| base_link β camera_link | URDF or static transform |
| base_link β imu_link | URDF or static transform |
Check the TF tree:
ros2 run tf2_tools view_frames
xdg-open frames.pdf
6. Launch system for RViz goal navigation
Option A: TurtleBot simulation
This is the easiest classroom option.
source /opt/ros/jazzy/setup.bash
ros2 launch nav2_bringup tb3_simulation_launch.py \
headless:=False \
slam:=False \
map:=$HOME/ros2_ws/maps/classroom_map.yaml
Important:
The map must match the simulation world.
If the map and world do not match, AMCL and navigation will fail.
Option B: Your own AMR
For your own AMR, start the robot bringup first.
You need:
LiDAR driver
odometry node
robot_state_publisher
AMCL localization
Nav2 navigation stack
RViz2
Example sequence:
Terminal 1: Robot bringup
source ~/ros2_ws/install/setup.bash
# Example only:
# ros2 launch your_robot_bringup robot_bringup.launch.py
Terminal 2: Localization
source /opt/ros/jazzy/setup.bash
ros2 launch nav2_bringup localization_launch.py \
map:=$HOME/ros2_ws/maps/classroom_map.yaml \
use_sim_time:=False
Terminal 3: Navigation
source /opt/ros/jazzy/setup.bash
ros2 launch nav2_bringup navigation_launch.py \
use_sim_time:=False
Terminal 4: RViz2
source /opt/ros/jazzy/setup.bash
rviz2
7. Configure RViz2 for Nav2
In RViz2, set:
Fixed Frame = map
Add these displays:
| Display | Topic or setting |
| -------------- | ----------------------------- |
| Map | /map |
| TF | Show frame names |
| RobotModel | robot_description |
| LaserScan | /scan |
| Odometry | /odom |
| Path | /plan or planner path topic |
| PoseArray | /particle_cloud |
| Global Costmap | /global_costmap/costmap |
| Local Costmap | /local_costmap/costmap |
Recommended RViz2 displays:
Map
TF
RobotModel
LaserScan
Odometry
Path
PoseArray
Global Costmap
Local Costmap
8. Step 1 in RViz2: Set initial pose
Before sending a navigation goal, you must tell AMCL approximately where the robot is.
In RViz2:
1. Click 2D Pose Estimate.
2. Click the robot's approximate position on the map.
3. Drag the arrow in the robot's facing direction.
4. Release the mouse button.
This publishes to:
/initialpose
You can verify it:
ros2 topic echo /initialpose
Then click 2D Pose Estimate again in RViz2.
If the terminal shows a message, RViz2 successfully published the initial pose.
9. Check localization after setting initial pose
After setting the initial pose, check:
ros2 run tf2_ros tf2_echo map odom
Then check:
ros2 run tf2_ros tf2_echo map base_link
You should see transform values.
In RViz2, you should observe:
LiDAR scan aligns with the map.
Robot model is near the correct position.
Particle cloud is near the robot.
If the robot is not aligned with the map, set the initial pose again.
10. Step 2 in RViz2: Send a navigation goal
In RViz2, use the goal tool.
Depending on your RViz2/Nav2 configuration, the button may appear as:
Nav2 Goal
2D Goal Pose
2D Nav Goal
Use the Nav2 goal tool if available.
Steps:
1. Click Nav2 Goal or 2D Goal Pose.
2. Click a reachable point on the map.
3. Drag the arrow to set the final robot orientation.
4. Release the mouse button.
This sends a navigation request to Nav2.
Conceptually, RViz2 sends:
/navigate_to_pose
The goal contains:
goal x position
goal y position
goal orientation
frame_id = map
11. What should happen after sending a goal?
After sending a valid goal, you should observe:
A global path appears.
The local costmap updates.
The controller publishes velocity commands.
The robot starts moving.
The robot follows the path.
The robot stops near the goal.
In RViz2, look for:
planned path
robot movement
costmap changes
LiDAR scan alignment
particle cloud stability
12. Check NavigateToPose action
Open a terminal:
ros2 action list
You should see:
/navigate_to_pose
Check action type:
ros2 action type /navigate_to_pose
Expected type:
nav2_msgs/action/NavigateToPose
You can inspect the interface:
ros2 interface show nav2_msgs/action/NavigateToPose
13. Send a navigation goal from command line
RViz2 is convenient, but command-line testing is also useful.
Example:
ros2 action send_goal /navigate_to_pose nav2_msgs/action/NavigateToPose \
"{
pose: {
header: {
frame_id: 'map'
},
pose: {
position: {
x: 1.0,
y: 0.5,
z: 0.0
},
orientation: {
x: 0.0,
y: 0.0,
z: 0.0,
w: 1.0
}
}
},
behavior_tree: ''
}"
This asks Nav2:
Navigate to x = 1.0, y = 0.5 in the map frame.
Final orientation uses quaternion w = 1.0.
To get feedback during navigation, use:
ros2 action send_goal --feedback /navigate_to_pose nav2_msgs/action/NavigateToPose \
"{
pose: {
header: {
frame_id: 'map'
},
pose: {
position: {
x: 1.0,
y: 0.5,
z: 0.0
},
orientation: {
w: 1.0
}
}
},
behavior_tree: ''
}"
14. Observe /cmd_vel
When Nav2 controls the robot, it usually publishes velocity commands.
Check:
ros2 topic echo /cmd_vel
You should see values like:
linear:
x: 0.1
angular:
z: 0.2
Meaning:
linear.x controls forward/backward speed.
angular.z controls turning speed.
If /cmd_vel is active but the robot does not move, possible reasons include:
motor driver is not subscribed to /cmd_vel
wrong command velocity topic
robot emergency stop is active
simulation is paused
controller output is being remapped
15. Observe path and costmap topics
Check path topics:
ros2 topic list | grep plan
ros2 topic list | grep path
Check costmap topics:
ros2 topic list | grep costmap
Common topics:
/plan
/global_costmap/costmap
/local_costmap/costmap
/global_costmap/published_footprint
/local_costmap/published_footprint
In RViz2, display:
global costmap
local costmap
planned path
robot footprint
This helps you understand why Nav2 chooses a path.
16. Cancel a navigation goal
If the robot is moving incorrectly, cancel the goal.
In RViz2:
Use the Nav2 panel Cancel button if available.
From command line, you can also send Ctrl+C if the goal was sent using ros2 action send_goal.
For a real robot, always prepare a physical emergency stop.
Important safety note:
For real AMR testing, keep the robot speed low, keep the area clear, and prepare an emergency stop.
17. Good navigation behavior
Good navigation usually looks like this:
The robot starts from the correct pose.
The LiDAR scan aligns with the map.
The global path avoids obstacles.
The local costmap updates near the robot.
The robot moves smoothly.
The robot stops near the goal.
The final orientation is close to the goal arrow direction.
18. Bad navigation behavior
Bad navigation may look like this:
The robot starts from the wrong map position.
The robot spins in place.
The robot moves away from the goal.
The robot cannot plan a path.
The robot stops immediately.
The global path crosses obstacles.
The costmap blocks the whole area.
The robot reaches the goal position but not orientation.
When this happens, debug in this order:
1. Check map.
2. Check initial pose.
3. Check TF tree.
4. Check scan alignment.
5. Check costmaps.
6. Check Nav2 lifecycle.
7. Check /cmd_vel.
8. Check robot driver.
19. Create a simple RViz configuration package
If you want a cleaner classroom setup, create an RViz configuration package or store the RViz file in your existing amr_navigation package.
Open RViz2, configure displays, then save:
File β Save Config As
Save it as:
~/ros2_ws/src/amr_navigation/rviz/nav2_goal_navigation.rviz
Then modify your launch file to load it automatically.
Example RViz2 node in launch file:
rviz_node = Node(
package='rviz2',
executable='rviz2',
name='rviz2',
output='screen',
arguments=['-d', rviz_config_file]
)
This makes your course easier because you do not need to manually add displays every time.
20. Optional: Create one launch file for localization, navigation, and RViz2
You can create a single launch file for classroom use.
Create:
cd ~/ros2_ws/src/amr_navigation
nano launch/nav2_goal_navigation.launch.py
Example launch file:
import os
from ament_index_python.packages import get_package_share_directory
from launch import LaunchDescription
from launch.actions import IncludeLaunchDescription
from launch.launch_description_sources import PythonLaunchDescriptionSource
from launch_ros.actions import Node
def generate_launch_description():
package_name = 'amr_navigation'
bringup_dir = get_package_share_directory('nav2_bringup')
map_file = os.path.join(
os.path.expanduser('~'),
'ros2_ws',
'maps',
'classroom_map.yaml'
)
params_file = os.path.join(
get_package_share_directory(package_name),
'config',
'nav2_params.yaml'
)
rviz_config_file = os.path.join(
get_package_share_directory(package_name),
'rviz',
'nav2_goal_navigation.rviz'
)
localization_launch = IncludeLaunchDescription(
PythonLaunchDescriptionSource(
os.path.join(bringup_dir, 'launch', 'localization_launch.py')
),
launch_arguments={
'map': map_file,
'use_sim_time': 'false',
'params_file': params_file
}.items()
)
navigation_launch = IncludeLaunchDescription(
PythonLaunchDescriptionSource(
os.path.join(bringup_dir, 'launch', 'navigation_launch.py')
),
launch_arguments={
'use_sim_time': 'false',
'params_file': params_file
}.items()
)
rviz_node = Node(
package='rviz2',
executable='rviz2',
name='rviz2',
output='screen',
arguments=['-d', rviz_config_file]
)
return LaunchDescription([
localization_launch,
navigation_launch,
rviz_node
])
Important:
This launch file assumes your robot bringup is already running.
It does not start LiDAR, odometry, or robot_state_publisher.
21. Build and run the combined launch file
Build:
cd ~/ros2_ws
colcon build --packages-select amr_navigation
source install/setup.bash
Run:
ros2 launch amr_navigation nav2_goal_navigation.launch.py
Then in RViz2:
1. Set initial pose using 2D Pose Estimate.
2. Wait until scan aligns with map.
3. Send goal using Nav2 Goal or 2D Goal Pose.
4. Observe path and robot motion.
22. How Step 9 connects to Step 10
In Step 9, you used RViz2 to send goals and observe navigation.
In Step 10, you will debug TF2 and Nav2 problems.
The reason is:
Most Nav2 failures are caused by TF, frame name, timestamp, costmap, or localization problems.
Step 10 will help you answer questions such as:
Why does RViz2 show No transform?
Why does Nav2 fail to plan?
Why is the robot not moving?
Why does the robot move in the wrong direction?
Why does the costmap block the path?
23. Common problems and solutions
Problem 1: RViz2 goal button is missing
Possible reasons:
Nav2 RViz plugin is not loaded.
RViz2 configuration does not include the Nav2 panel.
The button name is different in your RViz2 setup.
Solution:
Check the top toolbar for Nav2 Goal, 2D Goal Pose, or 2D Nav Goal.
Open Panels and add the Nav2 panel if available.
You can also send /navigate_to_pose from command line.
Problem 2: Robot does not move after sending goal
Possible reasons:
Nav2 nodes are not active.
Goal is invalid.
No path is found.
Controller is not active.
No /cmd_vel output.
Robot driver is not subscribed to /cmd_vel.
Emergency stop is active.
Check:
ros2 lifecycle get /bt_navigator
ros2 lifecycle get /planner_server
ros2 lifecycle get /controller_server
ros2 topic echo /cmd_vel
ros2 action list
Problem 3: Goal is rejected or aborted
Possible reasons:
Goal is outside the map.
Goal is inside an obstacle.
Robot is not localized.
Costmap blocks the goal.
TF map β base_link is missing.
Check:
ros2 run tf2_ros tf2_echo map base_link
ros2 topic echo /global_costmap/costmap --once
Solution:
Set initial pose again.
Choose a goal in free space.
Check the costmap in RViz2.
Problem 4: Robot moves in the wrong direction
Possible reasons:
base_link frame direction is wrong.
Wheel odometry sign is wrong.
cmd_vel interpretation is wrong.
Robot model x-axis is not forward.
LiDAR frame is misconfigured.
Check:
ros2 run tf2_ros tf2_echo odom base_link
ros2 topic echo /cmd_vel
Important convention:
For a mobile robot, base_link x-axis should point forward.
Problem 5: Robot spins in place
Possible reasons:
Initial orientation is wrong.
AMCL localization is poor.
Goal orientation is difficult to reach.
Controller parameters are not tuned.
Odometry yaw is noisy.
Solution:
Set initial pose again.
Choose a nearby goal.
Reduce speed.
Check odometry and IMU fusion.
Tune controller parameters later.
Problem 6: LiDAR scan does not align with map
Possible reasons:
Initial pose is wrong.
base_link β base_laser transform is wrong.
Map does not match the environment.
AMCL is not converged.
LiDAR scan topic is wrong.
Solution:
Use 2D Pose Estimate again.
Check base_link β base_laser.
Check /scan in RViz2.
Use the correct map.
Problem 7: Costmap blocks the whole area
Possible reasons:
Robot radius is too large.
Inflation radius is too large.
Unknown space is treated as occupied.
Obstacle layer receives bad scan data.
TF is wrong.
Check:
ros2 topic echo /global_costmap/costmap --once
ros2 topic echo /local_costmap/costmap --once
Solution:
Inspect costmap in RViz2.
Check robot_radius.
Check inflation_radius.
Check scan data.
Check TF.
Problem 8: RViz2 shows βNo transformβ
Possible reasons:
Fixed Frame is wrong.
map β odom is missing.
odom β base_link is missing.
base_link β sensor frame is missing.
use_sim_time setting is wrong.
Check:
ros2 run tf2_tools view_frames
ros2 run tf2_ros tf2_echo map base_link
Solution:
Set Fixed Frame to map.
Check AMCL.
Check odometry.
Check robot_state_publisher.
Check use_sim_time.
24. Practice assignment
Assignment title
Send a Nav2 Goal Using RViz2
Task 1: Check system readiness
Submit screenshots of:
ros2 topic echo /map --once
ros2 topic echo /scan --once
ros2 topic echo /odom --once
ros2 run tf2_ros tf2_echo map base_link
Task 2: Check Nav2 actions and lifecycle
Submit screenshots of:
ros2 action list
ros2 lifecycle get /bt_navigator
ros2 lifecycle get /planner_server
ros2 lifecycle get /controller_server
Expected state:
active
Task 3: Configure RViz2
In RViz2, set:
Fixed Frame = map
Add:
Map
TF
RobotModel
LaserScan
PoseArray
Path
Global Costmap
Local Costmap
Submit a screenshot.
Task 4: Set initial pose
Use:
2D Pose Estimate
Submit a screenshot showing:
Robot model on the map
LiDAR scan aligned with the map
Particle cloud near the robot
Task 5: Send navigation goal
Use:
Nav2 Goal or 2D Goal Pose
Submit a screenshot showing:
Goal pose
Planned path
Robot moving or reaching goal
Costmaps
Task 6: Check /cmd_vel
Run while the robot is moving:
ros2 topic echo /cmd_vel
Submit a screenshot.
Task 7: Explain the result
Write a short explanation:
The map topic is:
The scan topic is:
The odometry topic is:
The navigation action is:
The command velocity topic is:
The initial pose was set using:
The goal was sent using:
The robot successfully reached the goal: yes/no
One problem I observed was:
How I fixed or would fix it:
25. Mini quiz
- What is RViz2 used for in Nav2?
- What button is used to set the robot initial pose?
- What button is used to send a navigation goal?
- What action is used for full navigation to one goal pose?
- What topic usually carries velocity commands?
- Why must AMCL localization work before sending a goal?
- What should you check if the robot does not move?
- What should you check if the scan does not align with the map?
- What should you check if RViz2 shows βNo transformβ?
- Why is the goal orientation important?
- Why should you keep speed low when testing a real AMR?
- What is the difference between a planned path and robot movement?
26. Key summary
In this module, you learned how to use RViz2 for Nav2 goal navigation.
The normal workflow is:
1. Launch robot bringup.
2. Launch localization.
3. Launch Nav2 navigation.
4. Open RViz2.
5. Set Fixed Frame to map.
6. Set initial pose using 2D Pose Estimate.
7. Confirm scan aligns with map.
8. Send goal using Nav2 Goal or 2D Goal Pose.
9. Observe path, costmaps, /cmd_vel, and robot motion.
You learned that RViz2 sends a navigation request to:
/navigate_to_pose
Nav2 then uses:
BT Navigator
Planner Server
Controller Server
Costmaps
to move the robot toward the goal.
The most important idea is:
RViz2 is the user interface.
Nav2 is the navigation system.
The robot moves only when Nav2 produces valid /cmd_vel commands and the robot driver accepts them.
In the next module, you will learn:
TF2 debugging in Nav2
This final module will help you diagnose the most common problems in mapping, localization, planning, and RViz goal navigation.