Skip to content

robertwchen/autonomous-serving-robot

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

4 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Autonomous Serving Robot

ROS2 TurtleBot serving robot with TSP route optimization, LiDAR obstacle avoidance, and return-to-origin navigation.

Built as a personal project for my Autonomous Mobile Robots course at UVA.


Overview

A ROS2 node running on a TurtleBot3 that acts as an autonomous serving robot. You give it a set of table numbers through the terminal, it computes the shortest visit order, navigates to each table using a proportional Go-to-Goal controller, avoids obstacles it encounters using LiDAR, waits at each table for a tap to confirm delivery, and returns to the origin when all deliveries are done.

Six table positions are defined in a bounded workspace. The robot starts at the origin (the "kitchen"), visits all requested tables in the TSP-optimal order, and closes the loop automatically.

Workspace


Why I Built This

I wanted this to feel closer to a real robot system, not just a simple point-to-point demo. A serving robot has to handle multiple stops, obstacles, imperfect sensing, and recovery when the real world gets messy.

The interesting part was getting the TSP planner and the reactive obstacle avoidance to work together without breaking the overall delivery task. When the robot deviates around an obstacle, it has to resume the same goal it was tracking before — not get confused or get stuck in a loop. Getting that state machine tight, and making sure the clear-count logic prevented oscillation in cluttered environments, took more iteration than expected.


Demo

Physical testing on TurtleBot3 — table set {1, 3, 6}, two obstacles encountered:

Physical Testing

Simulation (The Construct)

Simulation Steps


Key Features

  • Multi-table delivery — accepts any combination of the 6 defined table IDs per run
  • TSP route optimization — brute-forces all permutations, prints a ranked table, picks the shortest path
  • Go-to-Goal controller — proportional heading + distance control, rotate-in-place when heading error is large
  • ROS2 publishers and subscribers — odometry, LiDAR, IMU with explicit QoS configuration
  • Odometry-based local frame — locks origin on first odometry message; all table positions are relative to it
  • LiDAR obstacle detection — 20 Hz front-window scan check
  • BYPASS state machine — TURN toward free space → arc FORWARD past the obstacle → resume goal
  • Tap-to-advance — IMU jerk detection advances to the next waypoint when a plate is picked up
  • Return-to-origin(0, 0) is automatically queued as the final waypoint after all tables are served

System Architecture

Architecture


Route Optimization

TSP Route

With at most six tables, the system can brute-force every possible visit order (at most 720 permutations) in well under a millisecond. Each permutation is scored by summing Euclidean distances along the full trip: origin → table 1 → table 2 → ... → origin. The result is printed as a ranked table so you can see why the chosen route is optimal, and the shortest path is loaded into the waypoint queue.

See solve_tsp() in src/ttb_tsp_serving_robot.py for the implementation.


Obstacle Avoidance

Obstacle Avoidance

The control loop checks a narrow front window (LiDAR indices 180–360) on every tick. When the minimum range in that window drops below block_dist (0.60 m), the robot enters a two-state BYPASS machine:

  1. TURN — rotates in place toward the diagonal window (front-left or front-right) with more average free space. A hysteresis ratio prevents the robot from flip-flopping between sides when both are similar.
  2. FORWARD — drives forward with a slight arc for a fixed duration. If still blocked at the end of the arc, it loops back into TURN.

BYPASS exits only after the front window exceeds clear_dist (0.70 m) for 6 consecutive cycles. The short clear-count requirement filters out false clears from sensor noise without making recovery sluggish. Once BYPASS exits, the robot resumes its original Go-to-Goal target.

When the robot is within docking_ignore_dist (0.60 m) of its goal, the obstacle check is suppressed to prevent false triggers when pulling up to a table.


Testing

Testing ran in two phases.

Simulation on The Construct's TurtleBot3 environment let me validate the navigation logic and tune BYPASS parameters before touching real hardware. I could easily place obstacles, pick table sets, and verify that the robot always resumed its original goal after avoidance.

Simulation Steps


Physical testing on a TurtleBot3 Burger used foam tiles as table markers and foam boxes as obstacles in a lab open space. The runs below used table set {1, 3, 6}.

The robot selects the TSP-optimal order and heads to the first table:

Heading to Table 1

After the first delivery it moves on to the next table without any user input:

Heading to Table 3

On the way to Table 6 it picks up an obstacle in its front LiDAR window:

Obstacle Detected

It enters BYPASS, turns toward the clearer side, and arcs around:

Obstacle Avoidance

Once the path is clear it resumes Go-to-Goal toward the original target:

Path Resumed

After finishing all deliveries it heads back to the kitchen — and hits another obstacle on the return leg:

Obstacle Detected on Return

Same BYPASS logic handles it:

Avoiding on Return

It resumes and returns to origin cleanly:

Return to Origin

The main differences from simulation were LiDAR noise at range and odometry drift on longer runs — both required threshold and gain retuning compared to simulation-tuned values.

Physical Testing


What I Learned

Going into this I mostly understood ROS2 conceptually — by the end I actually understood it. A few things that stuck:

ROS2 fundamentals clicked through debugging. I couldn't just skim the docs; I had to figure out why my subscriptions were silently receiving nothing (wrong QoS), why my coordinate system drifted across runs (using raw odometry instead of locking a local frame), and why the robot kept oscillating at obstacles (no hysteresis, no clear-count). Each of those bugs taught me something I wouldn't have gotten from reading alone.

LiDAR data is messier than it looks. Before building the obstacle logic I had to sanitize every scan — NaN, inf, and sub-3cm readings all show up on a real sensor and will break anything downstream if you don't handle them.

Sim-to-real is a real gap. Gains and thresholds that worked perfectly on The Construct needed retuning on the physical robot. Odometry drifts differently, the sensor has more noise, and the floor has friction. You have to go back and tune on hardware regardless of how clean your sim tests are.

Reactive avoidance only works if you're disciplined about state. The BYPASS state machine looks simple on paper but it took several iterations to get right — especially making sure the robot always resumed its original goal after clearing an obstacle, not a stale intermediate heading.


Future Improvements

  • Add a real map and localization stack (Nav2 / AMCL) instead of relying on raw odometry
  • Replace the reactive BYPASS with a proper local planner (DWA or VFH) for more predictable avoidance paths
  • Add a lightweight GUI for table selection instead of terminal input
  • Add route logging and replay for post-run debugging
  • Camera-based table or person detection for smarter handoff confirmation

Setup

Requirements: ROS2 Humble or later, Python 3.10+, TurtleBot3 Burger or Waffle (or compatible simulation).

# Source ROS2
source /opt/ros/humble/setup.bash

# Run the node
python3 src/ttb_tsp_serving_robot.py

The node subscribes and publishes on the /TTB04/ namespace. Change the topic prefix in the __init__ method to match your robot's namespace.

See docs/system_design.md for a full technical breakdown.


Report

The full project report (including figures from both simulation and physical testing) is in docs/final_report.pdf.

About

ROS2 TurtleBot serving robot with TSP route optimization, LiDAR obstacle avoidance, and return-to-origin navigation.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages