Navigate a Robot with ROS 2 and Nav2

Build an autonomous robot navigation system using SLAM, Nav2, and Gazebo.

Introduction

30 Second Summary

Think about warehouse robots that zip between shelves, delivery bots that navigate sidewalks, or self-driving cars choosing lanes. They all solve the same core problem: figuring out where they are, building a picture of their surroundings, and planning a safe path forward.

In this project, you will build a fully autonomous navigation system for a simulated robot. You will drive the robot around to create a map using SLAM, then switch to autonomous mode where the robot plans paths, avoids obstacles, and reaches destinations you click on a map.

What You'll Build

You can open RViz, click anywhere on your map, and watch a robot compute a path and drive itself there while dodging obstacles in real time.

By the end of this project, you'll have:

  • A simulated TurtleBot3 robot moving through a world with walls and obstacles in Gazebo, responding to your keyboard controls and streaming live LiDAR sensor data.
  • A 2D occupancy grid map you built from scratch by driving the robot through its environment, watching the map grow scan by scan as the robot discovers new areas.
  • Fully autonomous navigation where you click a destination on the map and the robot drives itself there, replanning around obstacles in its way.
  • Secret Mission: Write a Python node that sends navigation goals programmatically, making the robot patrol between waypoints without any manual clicking.

Are there any prerequisites?

This project requires a spare laptop (or dedicated machine) running a fresh Ubuntu 24.04 installation with at least 16GB of RAM. You should be comfortable using a terminal and have basic Python knowledge.

No dedicated GPU is needed. Integrated graphics handles the lightweight TurtleBot3 simulation just fine.

Before We Start

Before We Start...

Before we dive in, let's lock in what you're about to build and why it matters for robotics roles that ask for navigation and control algorithm experience.

Install ROS 2 Jazzy and the Navigation Stack

Your Ubuntu 24.04 laptop is a blank slate. Before you can launch a robot, build maps, or navigate autonomously, you need the software that makes it all possible.

In this step, you will install ROS 2 Jazzy (the robotics middleware), Gazebo Harmonic (the simulator), and the Nav2 navigation stack. These form the foundation for everything you build in this project.

In this step, get ready to:
  • Add the ROS 2 apt repository and install the full desktop package.
  • Install the Nav2 navigation packages, SLAM Toolbox, and TurtleBot3 simulation.
  • Configure your shell environment so ROS 2 commands work in every new terminal.
Add the ROS 2 apt repository and install the desktop package

ROS 2 packages live in a dedicated apt repository maintained by Open Robotics. You need to register that repository on your system before apt can find and install anything ROS-related.

  • Open a terminal. Press Ctrl+Alt+T to launch one.
  • Enable the Ubuntu Universe repository and install curl by running these commands:
sudo apt install software-properties-common
sudo add-apt-repository universe
sudo apt update && sudo apt install curl -y

What do these commands do?

  • software-properties-common provides the add-apt-repository tool your system needs to manage extra repositories.
  • The Universe repository contains community-maintained packages that ROS 2 depends on.
  • curl is a download tool you will use to grab the ROS 2 repository configuration file.
  • Download and install the ROS 2 apt source configuration by running these commands:
export ROS_APT_SOURCE_VERSION=$(curl -s https://api.github.com/repos/ros-infrastructure/ros-apt-source/releases/latest | grep -F "tag_name" | awk -F'"' '{print $4}')
curl -L -o /tmp/ros2-apt-source.deb "https://github.com/ros-infrastructure/ros-apt-source/releases/download/${ROS_APT_SOURCE_VERSION}/ros2-apt-source_${ROS_APT_SOURCE_VERSION}.$(. /etc/os-release && echo ${UBUNTU_CODENAME:-${VERSION_CODENAME}})_all.deb"
sudo dpkg -i /tmp/ros2-apt-source.deb

What does this do?

This downloads a small .deb package from the official ros-infrastructure GitHub repository. That package registers the ROS 2 apt sources and signing keys on your system. Future updates to repository configuration happen automatically when this package updates.

  • Now install ROS 2 Jazzy Desktop by running:
sudo apt update
sudo apt install ros-jazzy-desktop -y

What is ros-jazzy-desktop?

The ros-jazzy-desktop package is the recommended full install. It includes the ROS 2 core libraries, RViz (a 3D visualization tool), demo nodes, and the Gazebo integration bridge.

This installation may take 5-10 minutes depending on your internet speed.

  • Confirm the install completed by running:
dpkg -l | grep ros-jazzy-desktop

You should see a line starting with ii followed by ros-jazzy-desktop. This confirms the package is installed.

Seeing dependency errors?

On fresh Ubuntu 24.04 installs, your apt sources may only include the base noble suite. Check your sources file:

grep Suites /etc/apt/sources.list.d/ubuntu.sources

If noble-updates or noble-backports are missing, edit the file and update the Suites line to: Suites: noble noble-updates noble-backports. Then run sudo apt clean && sudo apt update && sudo apt full-upgrade -y and try the install again.

Still stuck? Help me fix ROS 2 Jazzy dependency errors on Ubuntu 24.04.

Install the navigation and simulation packages

The desktop package gives you the ROS 2 core. Now you need the specific packages for autonomous navigation: Nav2 for path planning, SLAM Toolbox for map building, and the TurtleBot3 simulation models.

  • Install all the navigation and simulation packages by running:
sudo apt install -y ros-jazzy-navigation2 ros-jazzy-nav2-bringup ros-jazzy-slam-toolbox ros-jazzy-nav2-minimal-tb3-sim ros-jazzy-turtlebot3-navigation2 ros-jazzy-ros-gz

What are these packages?

  • ros-jazzy-navigation2 is the Nav2 stack itself: path planners, controllers, recovery behaviors, and costmap generation.
  • ros-jazzy-nav2-bringup provides launch files that start the full Nav2 pipeline with one command.
  • ros-jazzy-slam-toolbox is the SLAM package you will use to build maps from LiDAR data.
  • ros-jazzy-nav2-minimal-tb3-sim and ros-jazzy-turtlebot3-navigation2 provide the TurtleBot3 robot model, Gazebo worlds, and navigation configs.
  • ros-jazzy-ros-gz is the bridge between ROS 2 and Gazebo Harmonic, the modern simulator that replaced Gazebo Classic.
  • Confirm the navigation packages installed by running:
dpkg -l | grep ros-jazzy-navigation2

You should see a line with ii and ros-jazzy-navigation2 listed. This confirms Nav2 is ready.

Package not found?

If apt cannot find a package, make sure the ROS 2 apt source was installed correctly in the previous substep. Run apt-cache search ros-jazzy-navigation2 to check if the package appears in your cache. If not, run sudo apt update and try again.

Need more help? Help me troubleshoot why ros-jazzy packages are not found by apt.

Configure your shell environment and verify the install

ROS 2 commands only work when the environment is sourced. You also need to tell the TurtleBot3 packages which robot model to use. Adding both to ~/.bashrc means every new terminal is automatically configured.

  • Add the ROS 2 source and TurtleBot3 model export to your ~/.bashrc by running:
echo 'source /opt/ros/jazzy/setup.bash' >> ~/.bashrc
echo 'export TURTLEBOT3_MODEL=waffle_pi' >> ~/.bashrc
source ~/.bashrc

Why waffle_pi?

TurtleBot3 comes in multiple models. The waffle_pi includes both a 360-degree LiDAR sensor and a camera. The LiDAR is the critical sensor for SLAM and navigation. The smaller burger model only has LiDAR, but waffle_pi gives you more to work with.

Before you run the verification command, what do you think ros2 topic list will print when ROS 2 is sourced but no nodes are running?

  • Verify your installation by running:
ros2 topic list

You should see two default topics printed:

/parameter_events
/rosout

These two topics exist by default in any ROS 2 environment. Seeing them confirms that ROS 2 Jazzy is installed and your shell is sourced correctly.

Seeing 'command not found' for ros2?

This means your shell has not sourced the ROS 2 setup file. Run source ~/.bashrc in your current terminal, or open a brand new terminal window. Then try ros2 topic list again.

If it still fails, check that the line source /opt/ros/jazzy/setup.bash exists in your ~/.bashrc by running cat ~/.bashrc | grep ros.

Still stuck? Help me fix ros2 command not found after installing ROS 2 Jazzy.

✔️ Awesome, I've got everything!

Great. Double check that your ~/.bashrc has both lines saved by running:

tail -2 ~/.bashrc

You should see:

source /opt/ros/jazzy/setup.bash
export TURTLEBOT3_MODEL=waffle_pi

ⓧ I'd like to double check the full code

Your ~/.bashrc should contain these two lines (typically at the very end of the file):

source /opt/ros/jazzy/setup.bash
export TURTLEBOT3_MODEL=waffle_pi

If either line is missing, add it with echo as shown earlier, then run source ~/.bashrc again.

Your development environment is fully armed. You have ROS 2 Jazzy, the Nav2 navigation stack, SLAM Toolbox, and a TurtleBot3 simulation ready to launch. Next up, you will bring the robot to life in Gazebo and see its sensors in action.

Launch Your First Robot in Gazebo and Drive It

Your ROS 2 environment is installed and sourced. Now it is time to see a robot come alive.

Before any autonomy can happen, you need to confirm the robot's sensors actually work. Teleoperating the robot builds your intuition for how it perceives the world through LiDAR. This raw sensor data is the foundation that SLAM and navigation depend on.

In this step, get ready to:
  • Launch a TurtleBot3 simulation in Gazebo Harmonic.
  • Drive the robot with keyboard teleoperation and watch it move.
  • Visualize the robot's LiDAR sensor data in RViz.
Launch the TurtleBot3 Gazebo world

The TurtleBot3 simulation drops a virtual robot into a room with walls and cylindrical obstacles. This is the environment you will map and navigate later.

  • Launch the simulation by running this command in your terminal:
ros2 launch turtlebot3_gazebo turtlebot3_world.launch.py

What does this command do?

This starts Gazebo Harmonic with a pre-built world containing a TurtleBot3 waffle_pi robot. Gazebo is a physics simulator that models the robot's motors, sensors, and collisions in real time.

The command takes over this terminal. You will need to open new terminals for additional commands.

After a few seconds, the Gazebo window opens. You see a small black robot (the TurtleBot3) sitting in a room with grey walls and several white cylindrical obstacles.

Gazebo window not appearing?

  • Wait up to 30 seconds on the first launch. Gazebo downloads model assets the first time it runs.
  • Check the terminal for errors. If you see a message about missing models, run sudo apt install ros-jazzy-turtlebot3-gazebo and try again.
  • Make sure you sourced your shell correctly. Run source ~/.bashrc and try the launch command again.

Help me troubleshoot why Gazebo is not launching with my TurtleBot3 simulation.

Drive the robot with keyboard teleoperation

The robot is sitting still in the world. To confirm it is alive and responsive, you will drive it around manually using your keyboard.

  • Open a new terminal window by pressing Ctrl+Alt+T.
  • Launch the keyboard teleoperation node by running:
ros2 run turtlebot3_teleop teleop_keyboard

The terminal displays a control diagram showing the available keys:

  • w increases forward speed.
  • x increases backward speed.
  • a turns left.
  • d turns right.
  • s or space stops the robot.
  • Press w a few times to move the robot forward. Watch it move in the Gazebo window.
  • Press a or d to turn, then w again to drive in a different direction.
  • Press s to stop. Leave this terminal open with teleop still running.

The robot should visibly move in Gazebo each time you press a key. You now have direct control of a simulated robot.

Robot not moving in Gazebo?

  • Make sure the teleop terminal is focused (click on it). The node only reads keys when its terminal has focus.
  • Confirm TURTLEBOT3_MODEL is set by running echo $TURTLEBOT3_MODEL in the teleop terminal. It should print waffle_pi.
  • If the terminal shows an error about the model not being set, run source ~/.bashrc and try the teleop command again.

Help me figure out why my TurtleBot3 is not responding to keyboard controls in Gazebo.

Visualize LiDAR sensor data in RViz

The robot is moving, but you cannot yet see what the robot itself perceives. RViz is a visualization tool that shows sensor data from the robot's perspective.

  • Open a third terminal by pressing Ctrl+Alt+T.
  • Launch RViz with the Nav2 configuration by running:
ros2 launch nav2_bringup rviz_launch.py

RViz opens with several pre-configured displays. However, you will likely see errors in the Displays panel because the Fixed Frame is set to map by default, and no map exists yet.

  • In the RViz window, look at the left panel under Global Options.
  • Click the Fixed Frame field (it currently says map) and change it to odom.

Why change the Fixed Frame?

The Fixed Frame is the coordinate frame RViz uses as its reference point. Right now the robot only publishes an odom frame (its position relative to where it started). The map frame does not exist yet because you have not built a map. Changing to odom tells RViz to use the reference frame that actually exists.

Once the Fixed Frame is set to odom, the LaserScan display activates. You should see colored dots (points) arranged in patterns around the robot. These represent the LiDAR returns. Each dot is a surface the laser beam hit.

What is LiDAR showing me?

The TurtleBot3 waffle_pi has a 360-degree laser scanner that fires beams outward and measures how far each one travels before hitting something. The dots you see in RViz are the points where each beam struck a wall or obstacle.

This is all the robot knows about the world right now. It has no memory, no map, and no idea of its global position. It only sees a single snapshot of distances around it at this instant.

  • Switch to your teleop terminal (the second one) and drive the robot toward a wall.
  • Watch the RViz dots move closer together as the robot approaches the wall.
  • Turn the robot and drive it past a cylindrical obstacle. Notice how the dots form a curved pattern around the cylinder.

Before you move on, predict: if you drive the robot into an open space away from all walls, what will happen to the LiDAR dots in RViz?

Drive there and check. The dots spread far apart or disappear where no surface is within the laser's range. The robot is effectively blind in that direction.

Not seeing any dots in RViz?

  • Confirm the Fixed Frame is set to odom (not map). The LaserScan cannot render without a valid frame.
  • In the Displays panel, find LaserScan and check the box next to it is ticked (enabled). If there is no LaserScan entry, click Add at the bottom, select By topic, expand /scan, select LaserScan, and click OK.
  • Make sure the Gazebo simulation is still running in your first terminal. RViz cannot display data if the simulation has stopped.

Help me get the LaserScan to display in RViz for my TurtleBot3 simulation.

You now have a robot that moves, senses its surroundings, and streams that sensor data live. But notice the limitation: the robot only sees a single frame of distances. It has no memory, no map, and no sense of where it has been. Next, you will fix that by giving it SLAM.

Build a Map with SLAM Toolbox

Your robot can see obstacles right in front of it through LiDAR, but it has no memory.

Every time the robot moves, the previous scan is gone. It has no global picture of where walls, corridors, and open space are. SLAM Toolbox solves this by stitching LiDAR scans together as the robot drives, building a persistent occupancy grid map in real time. Without this map, autonomous navigation is impossible.

In this step, get ready to:
  • Launch SLAM Toolbox and see the map start forming around the robot.
  • Drive through the entire environment to build a complete map.
  • Save the finished map to disk for Nav2 to use later.
Launch SLAM Toolbox and visualize the map

SLAM Toolbox subscribes to the robot's LiDAR topic and publishes an occupancy grid on /map. You will launch it in a new terminal and add a Map display in RViz to watch the map grow.

  • Open a new terminal tab (the Gazebo simulation and teleop from Step 2 should still be running).
  • Launch SLAM Toolbox in online async mode by running this command:
ros2 launch slam_toolbox online_async_launch.py use_sim_time:=true

You see log output as SLAM Toolbox starts subscribing to the robot's sensor data.

What does this command do?

The use_sim_time:=true parameter tells SLAM Toolbox to use Gazebo's simulated clock instead of your computer's real clock. Without it, the timestamps on LiDAR scans would not match the robot's position data, and the map would be garbled.

  • Switch to the RViz window from Step 2.
  • Click the Add button at the bottom-left of the Displays panel.
  • In the dialog, click the By topic tab.
  • Expand /map and select Map, then click OK.

A small patch of map appears around the robot in RViz. Black cells are walls the LiDAR detected, white cells are confirmed free space, and grey is unexplored territory.

Don't see the map in RViz?

  • Make sure the SLAM Toolbox terminal is still running without errors.
  • Check the Fixed Frame in the top-left of RViz. Change it to map if it shows something else.
  • Confirm the topic by expanding the Map display in the Displays panel and verifying the Topic field shows /map.

Why isn't my SLAM map showing in RViz?

Drive through the environment to complete the map

The map only grows where the robot has been. You need to drive through every corridor and get close to every wall so the LiDAR can reach all surfaces.

  • Switch to your teleop terminal (the one running teleop_keyboard from Step 2).
  • Drive the robot slowly using the W/A/S/D/X keys. Move forward with W, rotate with A and D, and stop with S.
  • Navigate through the entire turtlebot3_world environment. Drive along each wall and through every open area.
  • Watch the RViz map update in real time. Grey areas turn white (free space) or black (walls) as you explore.

Drive slowly for a better map

If you drive too fast, SLAM Toolbox may have trouble aligning consecutive scans. Keep the robot at a steady walking pace. Aim to cover the entire space, especially corners and behind obstacles.

Keep driving until the map in RViz looks complete. You should see all walls rendered as solid black lines with white free space between them, and no large grey patches remaining.

What is an occupancy grid map?

The map is a grid of cells, each storing a probability of being occupied. Black cells (probability near 100%) are obstacles. White cells (probability near 0%) are safe to drive through. Grey cells are unknown because the LiDAR has never reached them.

Nav2 uses this grid to plan paths. It cannot route the robot through grey or black cells, so a complete map means better navigation coverage.

Save the map and stop SLAM

With the map complete in RViz, you need to save it to disk. Nav2 will load this saved map in the next step to localize and navigate.

  • Open a new terminal tab (keep SLAM Toolbox running for now).
  • Save the map to your home directory by running this command:
mkdir -p ~/maps && ros2 run nav2_map_server map_saver_cli -f ~/maps/my_map

What does this command do?

  • The mkdir -p ~/maps part creates the ~/maps directory if it does not already exist.
  • The map_saver_cli tool captures the current occupancy grid from the /map topic and writes two files: a .pgm image (the grid as pixels) and a .yaml metadata file (resolution, origin coordinates, and thresholds).

Before you check the result, what two files do you expect to find in ~/maps/?

  • Verify the map was saved by running:
ls ~/maps/

You should see my_map.pgm and my_map.yaml listed.

Map files not appearing?

  • Make sure the SLAM Toolbox terminal was still running when you ran the save command. The map saver reads from the live /map topic.
  • If you see a timeout error, try running the save command again. The map server needs a moment to respond.
  • Confirm the correct topic exists by running ros2 topic list | grep map and checking that /map is listed.

Help me troubleshoot why my map did not save.

  • Now stop SLAM Toolbox by pressing Ctrl+C in its terminal.
  • Stop the teleop node by pressing Ctrl+C in the teleop terminal.

Leave the Gazebo simulation running. You will reuse it in the next step.

Your map is saved and ready. In the next step, you will load it into Nav2 and watch the robot navigate to any point you click, all on its own.

Navigate Autonomously with Nav2

Your map is complete. You drove the robot through the environment, and SLAM Toolbox stitched together LiDAR scans into a full occupancy grid saved at ~/maps/my_map.yaml.

The robot still cannot drive itself, though. It has a map but no way to figure out where it is on that map, no way to plan a path to a destination, and no way to steer around obstacles in real time. Nav2 provides the full autonomy stack that solves all three problems at once.

In this step, get ready to:
  • Launch the Gazebo simulation and the full Nav2 navigation stack with your saved map.
  • Initialize the robot's localization so it knows where it sits on the map.
  • Send navigation goals and watch the robot drive itself to destinations autonomously.
Launch the simulation and Nav2 stack

You need three separate processes running simultaneously: the Gazebo simulation (the physics world), the Nav2 stack (the robot's brain), and RViz (your visualization window). Each one runs in its own terminal.

  • Open a fresh terminal and launch the TurtleBot3 Gazebo world by running this command:
ros2 launch turtlebot3_gazebo turtlebot3_world.launch.py

The Gazebo window opens showing your TurtleBot3 in the same room with cylindrical obstacles and walls you mapped earlier.

What does this launch command do?

This starts the Gazebo Harmonic physics simulator with a pre-built world containing walls, corridors, and cylindrical obstacles. It also spawns the TurtleBot3 waffle_pi model with its LiDAR sensor and publishes all the simulated sensor data as ROS 2 topics.

  • Open a second terminal and launch the full Nav2 stack with your saved map by running:
ros2 launch nav2_bringup bringup_launch.py use_sim_time:=true map:=$HOME/maps/my_map.yaml

You see log messages scrolling as Nav2 configures and activates its nodes. Wait until you see a message indicating that managed nodes are active.

What is Nav2 launching here?

This single command starts the entire navigation stack: AMCL for localization (figuring out where the robot is on the map), a global planner for computing paths, a local controller for following those paths while avoiding obstacles, costmaps that inflate obstacles with safety buffers, and recovery behaviors for getting unstuck.

The use_sim_time:=true flag tells all nodes to use the simulator's clock instead of real time. The map parameter points to the map you saved in the previous step.

Nav2 nodes not becoming active?

The Nav2 lifecycle manager takes 10-30 seconds to configure and activate all nodes. If you see errors about nodes failing to start, wait a moment and try relaunching. Make sure the Gazebo simulation is fully running in your first terminal before launching Nav2.

help me troubleshoot Nav2 nodes not activating after running bringup_launch.py

  • Open a third terminal and launch RViz with the Nav2 configuration by running:
ros2 launch nav2_bringup rviz_launch.py

RViz opens and displays your occupancy grid map. You should see the black-and-white map you built earlier loaded in the background.

Map not appearing in RViz?

Make sure the Nav2 bringup terminal shows all nodes as active before launching RViz. If the map still does not appear, check that the path $HOME/maps/my_map.yaml is correct by running ls ~/maps/ in a terminal.

help me figure out why my map is not showing in RViz after launching Nav2

Initialize the robot's localization

The robot does not know where on the map it currently sits. AMCL uses a particle filter that starts with particles spread across the map. Without telling it the robot's approximate starting position, navigation will fail.

Before you fix this, try sending a navigation goal right now to see what happens.

  • In RViz, click the Nav2 Goal button in the top toolbar.
  • Click anywhere on the map to set a destination.

What do you think will happen? Will the robot start moving?

The robot does not move. Navigation fails because AMCL has not converged on the robot's actual position. The particle cloud is spread everywhere, so Nav2 cannot compute a valid path from an unknown starting location. This is the localization initialization problem that every robotics engineer encounters.

Why does localization need to be initialized?

AMCL (Adaptive Monte Carlo Localization) uses hundreds of particles to represent possible robot positions. When you first start Nav2, those particles are distributed randomly across the entire map. The robot has no idea which particle represents its true location.

By providing a rough initial pose estimate, you collapse those particles to a small area around the robot's actual position. From there, AMCL refines the estimate as the robot moves and matches LiDAR scans against the map.

  • Look at the Gazebo window and note where the robot is positioned in the world.
  • In RViz, click the 2D Pose Estimate button in the top toolbar.
  • Click on the map at the robot's approximate location, then drag in the direction the robot is facing to set the orientation.

You see the particle cloud (a cluster of small arrows) collapse from being spread across the map to clustering tightly around the robot's actual position. The localization is now initialized.

Exact position not required

Your click does not need to be perfectly placed. Nav2 refines the position as the robot navigates. You can also click 2D Pose Estimate again to reset if it looks wrong.

Particle cloud not collapsing?

Make sure you are clicking on the correct approximate location and dragging in the right direction. The drag direction sets the robot's orientation. If the particles stay scattered, try clicking 2D Pose Estimate again with a more accurate position.

help me fix AMCL localization that is not initializing properly after setting 2D Pose Estimate in RViz

Send navigation goals and watch the robot navigate

With localization initialized, Nav2 is fully active. The robot knows where it is on the map, and the full planning and control pipeline is ready to receive goals.

  • In RViz, click the Nav2 Goal button in the top toolbar.
  • Click a destination on the map that is across the room from the robot's current position.

Before you click, what do you expect to see this time? Think about what is different now that localization is initialized.

Nav2 computes a global path (shown as a green line in RViz). The local controller drives the robot along that path, and the costmaps show colored inflation zones around obstacles that the robot avoids. Watch the robot navigate to your goal autonomously in both the RViz and Gazebo windows.

What are costmaps?

Costmaps are layered grids that Nav2 uses to represent how expensive it is for the robot to travel through each cell. Cells occupied by walls have infinite cost. Cells near obstacles have high cost (the inflation layer). Free space has zero cost.

The global costmap covers the entire map and helps the planner find a path. The local costmap covers a small area around the robot and helps the controller react to nearby obstacles in real time.

  • Try sending goals to 2-3 different locations on the map.
  • Watch how the robot replans its path when you send a new goal while it is still moving.
  • Observe the green planned path, the costmap overlays, and the robot's movement in Gazebo.

You should see the robot successfully reach each destination, adjusting its path around obstacles in real time. The green path updates as the robot moves, and the costmaps show the safety zones around walls and cylindrical obstacles.

Robot not reaching the goal?

If the robot gets stuck or spins in place, it may be triggering recovery behaviors. Try sending a goal to a wide open area first. If the robot still does not move, check that your localization (particle cloud) is still tightly clustered. You can re-set the 2D Pose Estimate if the particles have drifted.

help me debug why my TurtleBot3 is not reaching navigation goals in Nav2

You have a fully autonomous robot. It localizes itself on your map, plans paths to any destination you click, and avoids obstacles in real time. Next up, you will write a Python node that sends navigation goals programmatically, making the robot patrol between waypoints without any manual clicking.

Secret mission

Write a Python Waypoint Patrol Node

Clicking goals in RViz proves navigation works, but real robots need programmatic control. In this secret mission, you write a Python node that sends navigation goals automatically, making the robot patrol between waypoints without any manual input.

Clean Up Your Resources

Clean Up Your Resources

Decide whether to keep your resources running, pause them to come back later, or delete them entirely. This project runs entirely locally on your Ubuntu machine, so there are no ongoing cloud costs.

Resources you used:

  • ROS 2 Jazzy packages (installed via apt: ros-jazzy-desktop, ros-jazzy-navigation2, ros-jazzy-nav2-bringup, ros-jazzy-slam-toolbox, and related packages).
  • Map files in ~/maps/ (my_map.pgm and my_map.yaml).
  • Python patrol script (waypoint_patrol.py).
  • Shell environment changes in ~/.bashrc (ROS 2 source line and TURTLEBOT3_MODEL export).

Keep everything running

No action needed. Choose this if you plan to keep experimenting with ROS 2 navigation, SLAM, or other robotics projects on this machine.

  • Your ROS 2 packages remain installed and ready to use.
  • Your map files stay in ~/maps/ for future navigation sessions.
  • The ~/.bashrc changes mean every new terminal is ready for ROS 2 work.

Pause - I'll come back to this later

Stop any running processes to free up system memory. Your files and packages stay installed so you can pick up where you left off.

  • Press Ctrl+C in any terminal still running Gazebo, Nav2, teleop, or your patrol script.
  • Close any remaining terminal windows from the project.
  • Your map files, patrol script, and ROS 2 installation all remain on disk for next time.

Delete - I don't want to use this again

Remove all project files, ROS 2 packages, and shell configuration changes from your machine.

  • Stop any running processes by pressing Ctrl+C in all open terminals.
  • Delete your map files and patrol script by running:
rm -rf ~/maps
rm waypoint_patrol.py
  • Remove all ROS 2 Jazzy packages by running:
sudo apt remove '~nros-jazzy-*' && sudo apt autoremove
  • Remove the ROS 2 apt repository by running:
sudo apt remove ros2-apt-source
sudo apt update
  • Remove the ROS 2 lines from your ~/.bashrc. Open the file in a text editor:
nano ~/.bashrc
  • Find and delete these two lines:
source /opt/ros/jazzy/setup.bash
export TURTLEBOT3_MODEL=waffle_pi
  • Save the file (Ctrl+O, then Enter) and exit nano (Ctrl+X).
  • Open a new terminal to confirm the changes took effect.

Nice Work!

Nice Work!

You just built a fully autonomous navigation system for a simulated robot. From a fresh Ubuntu install to a robot that plans paths and dodges obstacles on its own, you now have hands-on experience with the complete SLAM-to-navigation pipeline that robotics roles demand.

You've learned how to:

  • Installed ROS 2 Jazzy with the full Nav2 navigation stack and launched a TurtleBot3 in Gazebo Harmonic with working LiDAR sensor data.
  • Built a complete occupancy grid map from scratch using SLAM Toolbox by driving the robot through its environment and stitching together LiDAR scans.
  • Achieved fully autonomous navigation where the robot localizes itself with AMCL, plans paths around obstacles, and drives to any destination you click in RViz.
  • (Secret Mission) Wrote a Python waypoint patrol node that sends navigation goals programmatically, making the robot cycle between waypoints without any manual input.

Ready to quiz yourself?