Close

From SLAM to Smart Navigation

A project log for Perceptor - ROS2 Perception, Planning, Control

Modified Roomba with ROS2, LIDAR, and odometry running SLAM Toolbox for real-time mapping and navigation

vipin-mVipin M 08/01/2025 at 06:440 Comments

 Following previous success fixing laser scan drift, I have upgraded the Perceptor robot from a basic SLAM platform into a modular autonomous navigation system with advanced features like keepout zones and variable speed control.

Overview

In the previous entry, I addressed laser scan drift on an RPLiDAR-equipped iRobot Create 2. After frame correction and sensor calibration, SLAM stability was achieved. This post focuses on the transition from mapping to fully autonomous navigation using ROS 2 and Nav2.

SLAM to Navigation with Nav2

Autonomous navigation requires multiple components beyond SLAM:

ROS 2’s Navigation Stack (Nav2) enables this functionality but demands hardware-aware configuration.

Replacing SLAM with AMCL

I replaced SLAM with AMCL (Adaptive Monte Carlo Localization) to localize using a static map. This allowed me to retain the same sensor suite while shifting to a particle filter approach:

amcl:  ros__parameters:    laser_model_type: "likelihood_field"    max_particles: 2000    min_particles: 500    initial_pose:      x: 0.0      y: 0.0      yaw: 0.0

Despite a minimal sensor stack, AMCL yielded reliable localization across varied test environments.

Modular Launch Design

To streamline development and debugging, I adopted a modular launch approach across four terminals:

# Terminal 1: Base and sensor drivers
ros2 launch perceptor launch_robot.launch.py

# Terminal 2: Localization
ros2 launch perceptor localization_launch.py map:=home.yaml

# Terminal 3: Nav2 stack
ros2 launch perceptor navigation_launch.py

# Terminal 4: Optional filters and extensions
ros2 launch perceptor keepout_extension.launch.py

Benefits:

Keepout Zones via Costmap Filters

To restrict the robot from entering specific regions, I implemented keepout zones using Nav2's costmap filters. Required components:

  1. Binary mask image defining exclusion zones

  2. Filter info server to define spatial metadata

  3. Integration with global costmap

Correct alignment between map and mask was critical. Misalignment led to unintended path planning behavior.

keepout_filter:  plugin: "nav2_costmap_2d::KeepoutFilter"
enabled: True
filter_info_topic: "/costmap_filter_info"

Configuration Issue: Missing Publisher

Initial implementation failed due to the absence of a speed limit publisher:

ros2 topic info /speed_limit --verbose
# Publisher count: 0  <- No effect on speed

Adding the following parameter resolved the issue:

speed_filter:  plugin: "nav2_costmap_2d::SpeedFilter"  enabled: True  filter_info_topic: "/speed_filter_info"  speed_limit_topic: "/speed_limit"

Without this, the filter parses the mask but never communicates velocity limits to the controller.

Integration Challenges

Coordinate Frame Alignment

All masks and maps required:

Simultaneous Filter Operation

Running multiple filters required:

Performance Optimization

On Raspberry Pi 5:

Current Capabilities

Perceptor now supports:

Best Practices and Takeaways

Roadmap

Planned enhancements:

Discussions