Project Idea
10 min read
February 2025

Building an Autonomous Ground Vehicle with ROS2

Component selection, chassis design and ROS2 navigation stack integration for AGV projects.

An Autonomous Ground Vehicle (AGV) built on ROS 2 is an excellent platform for learning robotics fundamentals: sensor fusion, localisation, path planning, and actuation all come together in a tangible system you can drive in a real environment. This project guide covers component selection, mechanical assembly, and software integration using the ROS 2 Navigation Stack (Nav2).

Platform and Chassis Selection

For a first AGV, a differential-drive (two-wheel + caster) chassis simplifies kinematics considerably. Suitable options: a compact rover-style chassis kit (600 RPM DC gearmotors, 120:1 ratio, payload ~1 kg), or a custom aluminium frame with 100 mm diameter wheels. Avoid mecanum wheel platforms for a first build — the additional kinematic complexity adds tuning burden without proportional learning value.

Motor and Driver Selection

Use brushed DC gearmotors with encoders for closed-loop velocity control. 12 V motors with 200–400 RPM no-load speed give manageable top speed (0.3–0.6 m/s) for indoor testing. Pair with a dual H-bridge driver (BTS7960 for 43 A peak, or TB6612FNG for lighter loads). Encoders with 200+ CPR give adequate velocity resolution at low speeds. Wire encoder signals to your microcontroller or to GPIO pins on your compute board.

Compute Architecture

A two-board setup is recommended: a microcontroller (ESP32 or STM32) handles real-time motor control and encoder reading; a single-board computer or compact AI compute module runs ROS 2 and the navigation stack. Communicate over UART using a serial protocol or micro-ROS over USB. Micro-ROS on the ESP32 exposes motor commands and encoder odometry directly as ROS 2 topics, eliminating a custom protocol layer.

Sensor Suite for Navigation

Minimum viable sensor set: one 360° 2D LiDAR unit for SLAM and obstacle detection, one IMU module (e.g. MPU-6050 or BNO055) for heading fusion. Optional for outdoor use: a GPS module for global localisation, a depth camera for 3D obstacle detection. Mount the LiDAR at least 150 mm above the ground plane to avoid ground-return noise.

ROS 2 Nav2 Integration

Install ROS 2 Jazzy and the Nav2 stack: `sudo apt install ros-jazzy-navigation2 ros-jazzy-nav2-bringup`. Create a URDF for your robot and publish a static TF tree. Run `slam_toolbox` in mapping mode to generate an occupancy grid map of your environment. Save the map. Switch to localisation mode using `slam_toolbox` or `amcl`. Configure the Nav2 planner (DWB for indoor, MPPI for outdoor with obstacles) and launch the full navigation stack with your map file.

Odometry and Sensor Fusion

Wheel odometry alone drifts — small slip errors accumulate over seconds. Fuse wheel odometry with IMU heading using the `robot_localization` ROS 2 package (EKF node). Publish wheel odometry on `/odom` and IMU data on `/imu/data`. Configure the EKF to fuse x/y velocity from odometry with yaw rate from the IMU. This reduces drift to under 2% of distance travelled on hard floors.

Tuning and First Autonomous Run

Start with the default Nav2 parameters and drive manually using teleop_twist_keyboard to verify odometry, TF, and LiDAR data are all consistent in RViz. Then set a 2D Nav Goal in RViz. Expect the first run to need: inflation radius adjustment (too tight = stuck; too wide = refuses to navigate), DWB velocity limits tuned to your robot's actual max speeds, and costmap update frequency matched to your LiDAR scan rate.