ROBOTICS • DEC 22, 2025 • 9 MIN READ

Building Autonomous Mobile Robots with ROS 2 and LiDAR

A capable SLAM-driven robot no longer costs tens of thousands. It costs a few hundred, and a great deal of tuning.

Key takeaways

  • Odometry is the foundation, and it is where most projects fail. If your map bends or drifts, fix wheel radius, wheelbase, encoder counts and IMU calibration before touching any SLAM parameter.
  • Use ROS 2, not ROS 1. ROS 1 has reached end of life. ROS 2's DDS middleware also removes the single point of failure that the ROS 1 master represented.
  • A 2D LiDAR sees one horizontal plane. Tables become four circles, descending stairs are invisible, and floor-level objects do not exist. Plan for supplementary sensing.
  • Nav2 splits into layers: AMCL localises, the global planner routes, the local planner (DWB) emits velocity commands, and costmaps underpin both. The inflation radius is the parameter you will most often need to tune.
  • Build in order: closed-loop motor control → encoder odometry → IMU fusion → SLAM → autonomous navigation. Each step depends on the previous one being correct.

What changed

Autonomous navigation used to be the preserve of well-funded research labs. Two things changed that. ROS 2 matured into a genuinely production-capable framework, and 360-degree LiDAR dropped to a price where a hobbyist can buy one.

The result is that a capable SLAM-driven robot can be built for a few hundred dollars in parts. What has not changed is the engineering. The parts are cheap; making them work together reliably is still the hard part, and that is what this article is about.

The hardware stack

Our reference platform in the lab uses parts that are widely available and well supported, which matters more than raw specification when you are debugging at midnight:

COMPUTE & SENSING

Raspberry Pi 4 (4 GB), RPLidar A2 for 360° scanning, MPU6050 IMU for orientation, quadrature encoders on both drive wheels

ACTUATION & POWER

Dual DC gear motors, L298N or a MOSFET H-bridge driver, 12 V Li-Po pack with a regulated 5 V rail for logic

The software side is Ubuntu 22.04 with ROS 2 Humble, Nav2 for the navigation stack, and either Cartographer or slam_toolbox for mapping.

One decision here is worth dwelling on. The Raspberry Pi is not a real-time device, and it should not be closing your motor control loop. We put a microcontroller between the Pi and the motors: the Pi decides where to go, and the microcontroller handles the PID loop that makes the wheels actually turn at the commanded velocity. This is the same separation-of-concerns argument that governs MCU selection, and it applies just as strongly here.

Odometry is the foundation, and it is where projects fail

Before SLAM, before Nav2, before any of the interesting parts, the robot must know how far it has moved. This is odometry, and getting it wrong poisons everything downstream.

Wheel encoders give you distance travelled per wheel, from which you derive position and heading. The problem is that wheels slip, carpet compresses, and your measured wheel radius is never quite the real wheel radius. These errors do not cancel out. They accumulate, and after a few minutes of driving your robot's belief about its position has drifted meaningfully from reality.

This is why the IMU is not optional. Fusing gyroscope data with wheel odometry corrects the heading errors that wheel slip introduces, and heading errors are the ones that hurt most, because a small angular error becomes a large positional error as the robot drives away from it.

If your map comes out bent or the robot slowly rotates its world view, do not start tuning SLAM parameters. Measure your wheel radius and wheelbase precisely, verify your encoder counts per revolution, and calibrate the IMU. The overwhelming majority of "SLAM is broken" reports are actually "odometry is wrong".

SLAM: building a map while you are lost in it

Simultaneous localisation and mapping solves a genuinely circular problem: to build a map you need to know where you are, and to know where you are you need a map. SLAM resolves this by estimating both at once and letting each refine the other.

In practice, the LiDAR produces a scan of the surrounding geometry many times per second. Scan matching compares the current scan against the accumulating map and asks: given what I expected to see from where I think I am, and given what I actually see, where must I really be? That correction gets folded back into the pose estimate, and the corrected scan is added to the map.

The 2D LiDAR sees a single horizontal plane. This is worth internalising, because it is the source of a whole class of confusing failures. A table with a thin top and legs appears to the robot as four small circles. A staircase going down is invisible. An object lying on the floor below the scan plane does not exist. Your robot will confidently drive into things that it cannot, by construction, see.

The mitigation is additional sensing: bump sensors as a last resort, downward-facing sensors for drop-offs, and a depth camera if you genuinely need to perceive three-dimensional obstacles.

The Nav2 architecture

Nav2 splits navigation into layers, and understanding the split makes the whole thing far easier to debug.

The inflation radius on the costmap is the parameter that most commonly needs attention. Set it too small and the robot clips corners and scrapes walls. Set it too large and it refuses to enter doorways it can physically fit through, reporting that no valid path exists. Tune it against your robot's actual footprint plus a sensible margin.

Things that will go wrong

Some failure modes are common enough to name in advance, because recognising them saves days.

The robot spins in place before moving. Usually a mismatch between the robot's declared kinematics and its real ones, or a local planner configured for a holonomic base when your robot is differential drive.

Localisation jumps suddenly. The particle filter has found a better hypothesis somewhere else. This happens in environments with repetitive geometry, such as a long corridor of identical doors, where the LiDAR scan is genuinely ambiguous. More distinct features, or better odometry to constrain the filter, is the answer.

The robot stops and refuses to plan. Check whether the goal is inside the inflation radius of an obstacle. From Nav2's point of view you have asked it to drive into a wall.

Everything works in simulation and fails on the real robot. The gap is almost always odometry and sensor noise, neither of which the simulator models honestly by default. Simulation is excellent for validating logic and useless for validating calibration.

Where to start

Build it in this order, and resist the temptation to skip ahead. Get the motors turning under closed-loop velocity control. Get encoder odometry publishing and verify it by driving a measured two metres and checking what the robot thinks it did. Fuse the IMU and verify heading. Only then bring up the LiDAR and SLAM. Only after you have a clean, non-drifting map should you attempt autonomous navigation.

Every step in that sequence depends on the one before it being correct. Teams that jump straight to Nav2 because that is the exciting part spend weeks debugging a navigation stack that was never going to work, because the robot underneath it did not know where it was.

Sources and further reading

Primary references for the standards, regulations and figures cited above:

Common Questions

Frequently Asked Questions

Why ROS 2 instead of ROS 1?

ROS 1 has reached end of life, so new projects should not start there. Beyond that, ROS 2 is built on DDS middleware, which gives it real-time capable communication, proper security, and multi-robot support without the single point of failure that the ROS 1 master represented. For anything intended to reach production, ROS 2 is the only sensible choice.

Do I need an expensive LiDAR?

Not to start. A 2D LiDAR such as an RPLidar A2 is enough to build a genuinely working SLAM and navigation system, and it costs a small fraction of a 3D unit. You move to 3D LiDAR when your environment demands it, for example when you must detect obstacles at varying heights, or navigate spaces where a single horizontal scan plane misses things that matter.

Is a Raspberry Pi powerful enough to run Nav2?

A Raspberry Pi 4 with 4 GB runs 2D SLAM and Nav2 adequately for a modest indoor robot, and it is what we use for prototyping. It will struggle once you add camera-based perception, 3D LiDAR processing or any machine learning inference. At that point move to something like a Jetson, or split the workload across a compute board and a real-time microcontroller.

Why does my robot's map drift or bend?

Almost always odometry. SLAM fuses wheel odometry with LiDAR scans, and if odometry is systematically wrong, the map warps. The usual culprits are wheel slip, an incorrectly measured wheel radius or wheelbase, and an uncalibrated IMU. Fix odometry accuracy first. No amount of SLAM parameter tuning will rescue a robot that does not know how far it has travelled.

Building a robot that needs to navigate on its own?

We build autonomous platforms end to end, from the motor drivers to the navigation stack. Tell us about your application.

REQUEST A CONSULTATION

Keep Reading

Related Articles