Introduction
Build an autonomous guided vehicle (AGV) for warehouse logistics with SLAM navigation, barcode scanning, and fleet management. This comprehensive guide covers everything from design through implementation, testing, and deployment.
Build an autonomous guided vehicle (AGV) for warehouse logistics with SLAM navigation, barcode scanning, and fleet management.
Build an autonomous guided vehicle (AGV) for warehouse logistics with SLAM navigation, barcode scanning, and fleet management. This comprehensive guide covers everything from design through implementation, testing, and deployment.
Install ROS Noetic on Raspberry Pi. Configure diff_drive_controller package: set wheel separation (distance between wheels), wheel radius, publish TF transform between base_link and odom frames using wheel encoder data. Robot moves by publishing to /cmd_vel topic (linear.x for forward, angular.z for turning). Calculate wheel velocities: v_left = (v - ω×d/2), v_right = (v + ω×d/2) where d=wheel separation.
10 components required for this project.
| # | Component | Purpose | Qty |
|---|---|---|---|
| 1 | RPLidar A1 (360° LIDAR) | Environment mapping for SLAM | x1 |
| 2 | Raspberry Pi 4 (4GB) | ROS navigation stack host | x1 |
| 3 | Arduino Mega | Low-level motor and sensor control | x1 |
| 4 | Differential Drive Base (heavy duty) | Robust mobile platform | x1 |
| 5 | Brushless DC Hub Motors (24V, 250W) | High-torque drive | x2 |
| 6 | Incremental Encoders (1000 PPR) | Odometry for position tracking | x2 |
| 7 | QR Code/Barcode Scanner (Honeywell) | Package and shelf identification | x1 |
| 8 | Intel RealSense D435 Depth Camera | 3D obstacle detection and shelf scanning | x1 |
| 9 | 24V 20Ah LiFePO4 Battery | Long-duration operation | x1 |
| 10 | 7" Industrial Tablet (HMI) | Task assignment and status display | x1 |
Follow these 6 steps carefully.
Install ROS Noetic on Raspberry Pi. Configure diff_drive_controller package: set wheel separation (distance between wheels), wheel radius, publish TF transform between base_link and odom frames using wheel encoder data. Robot moves by publishing to /cmd_vel topic (linear.x for forward, angular.z for turning). Calculate wheel velocities: v_left = (v - ω×d/2), v_right = (v + ω×d/2) where d=wheel separation.
Launch RPLidar node for 360° laser scan data. Run gmapping package: subscribes to /scan (LIDAR) and /odom (encoder-based odometry), publishes /map (occupancy grid) and TF odom→map transform. Teleoperate robot through entire warehouse area. Building complete map typically takes 15–30 minutes for 1000m² facility. Save map: rosrun map_server map_saver -f warehouse_map. This map is used for all subsequent autonomous navigation.
Configure the ROS Navigation Stack: global planner (Navfn or A*) plans paths on the saved map. Local planner (DWA — Dynamic Window Approach) handles real-time obstacle avoidance. AMCL (Adaptive Monte Carlo Localization) localizes robot within the map using LIDAR matching. Set waypoints for each storage location: rack_A1, rack_A2...rack_Z8. Robot navigates to any rack on command from WMS (Warehouse Management System).
WMS sends pick order: product SKU, source rack, destination. Robot: navigates to source rack (A*), scans barcode on rack to confirm correct location, takes depth camera image to identify and localize item on shelf, communicates pick coordinates to manipulator (or human operator with display), confirms pick completion, navigates to packing station, delivers item. Log pick time, distance traveled, battery used.
For multiple robots: implement a central fleet manager (Python server). Robots register via ROS service call. Assign tasks from order queue to nearest available robot. Implement traffic management: bidirectional aisles require robot yielding (lower priority robot stops at aisle intersections). Zone reservation: robot claims a grid cell before entering — prevents collisions. Monitor all robots' positions, battery levels, and task status on a central dashboard.
Monitor battery SOC continuously. When SOC < 20%: complete current task, navigate to charging station (always reserved in map), dock precisely using camera-based docking to charging contact alignment, begin charging. Charge to 90% (not 100% — better battery longevity), then resume task queue. Implement predictive charging: if estimated task duration > remaining runtime, interrupt current task and charge before starting.
Core code for fleet_manager.py:
import rospy
from geometry_msgs.msg import PoseStamped
from actionlib_msgs.msg import GoalStatusArray
import threading
class FleetManager:
def __init__(self):
rospy.init_node('fleet_manager')
self.robots = {}
self.task_queue = []
def assign_task(self, robot_id, target_pose):
pub = rospy.Publisher(f'/{robot_id}/move_base_simple/goal',
PoseStamped, queue_size=1)
goal = PoseStamped()
goal.header.frame_id = "map"
goal.pose = target_pose
pub.publish(goal)
rospy.loginfo(f"Task sent to {robot_id}: ({target_pose.position.x:.1f}, {target_pose.position.y:.1f})")
def get_nearest_robot(self, target_location):
"""Find nearest available robot"""
min_dist = float('inf')
nearest = None
for robot_id, status in self.robots.items():
if status['available']:
dist = euclidean_distance(status['position'], target_location)
if dist < min_dist:
min_dist = dist
nearest = robot_id
return nearest
def process_orders(self):
while not rospy.is_shutdown():
if self.task_queue:
order = self.task_queue.pop(0)
robot = self.get_nearest_robot(order['location'])
if robot:
self.assign_task(robot, order['pose'])
rospy.sleep(1)
Test Warehouse Management Robot by verifying each subsystem individually before full integration.
Verify power voltages, check ground connections, use serial monitor for debug.
An interactive simulator will be available here — simulate circuits and run code in-browser without hardware.