TurtleBot4 Autonomous Maze Navigation

TurtleBot4

Project Overview

For ENAE450: Robotics Programming at the University of Maryland, my team designed and implemented autonomous maze navigation on a TurtleBot4. The competition had two parts: navigating a known, pre-mapped maze using a saved SLAM map with Nav2, and autonomously exploring and escaping an unknown maze in real time using frontier-based exploration. Both approaches combined SLAM, the Nav2 stack, and custom ROS2 controller nodes.

Hardware

The TurtleBot4 is built on an iRobot Create3 base with a Raspberry Pi 4 running ROS2 Humble. Its sensor suite includes a 2D LiDAR scanner, IMU, and wheel encoders. The LiDAR was the primary sensor for both obstacle detection and map generation. All ROS2 communication between the development laptop and the robot was handled over WiFi.

Part 1: Pre-Mapped Maze Race

For the known environment, the approach was straightforward:

  1. Run SLAM while manually driving through the maze with TeleOp, verifying the LiDAR map in RViz2
  2. Save the generated map using map_server_cli
  3. Launch the Nav2 stack with localization using the saved map
  4. Set a Nav2 goal pose at the maze exit and let the planner handle navigation

The SLAM node, Nav2 stack, and RViz2 were all launched with a single launch file (full_pt1.launch.py).

Part 1 Pre-mapped Maze with Odometry

Part 2: Unknown Maze Exploration

For the novel environment, we developed a frontier-based exploration algorithm that autonomously navigated the robot through an unmapped maze:

  1. The SLAM toolbox builds a live OccupancyGrid where open cells are 0, walls are 100, and undiscovered areas are -1
  2. The robot's position from /odom is translated to a grid coordinate
  3. BFS finds the nearest frontier cell (a discovered cell bordering an unknown cell)
  4. The frontier position is converted back to world coordinates and sent as a Nav2 goal
  5. After each goal is reached, the node computes an openness score of the surrounding area
  6. If the score exceeds a threshold (indicating open space outside the maze), the robot does a 180 and the run terminates; otherwise it loops back to find the next frontier

Key Functions

  • find_nearest_frontier() — BFS from the robot's position to the nearest discovered cell bordering an unknown area
  • compute_open_space_score() — BFS-based flood fill counting reachable open cells within a radius; low score = corridor, high score = open area (maze exit)
  • world_to_grid() / grid_to_world() — Coordinate transforms between world frame and OccupancyGrid indices
  • timer_callback() — Main loop: initial 360-degree spin for SLAM initialization, then frontier-navigate-score loop until maze exit detected
Part 2 SLAM Map with Odometry

Results

  • Part 1: Successfully navigated the pre-mapped maze from entrance to exit using SLAM localization and Nav2 path planning
  • Part 2: Frontier-based exploration algorithm autonomously navigated and escaped the unknown maze, detecting the exit via open-space scoring
  • Both parts used custom launch files to bring up the full SLAM + Nav2 + controller stack with a single command