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.