A modular autonomy stack for a differential-drive robot: perception → mapping → A* planning → pure-pursuit control → safety layer, validated in a seeded simulator with a reproducible benchmark. Runs on any laptop (CPU only) and is designed to move to a Raspberry Pi robot without rewriting the navigation logic.
Live project site: https://rohitsingh83.github.io/AI-Autonomous-Navigation-System/
Benchmark over 60 seeded random worlds (python main.py benchmark --episodes 60):
| Metric | Result |
|---|---|
| Goal success rate | 100 % (60 / 60) |
| Collisions (ground truth) | 0 across all episodes |
| Worst-case clearance to any obstacle or wall | 0.012 m (2 of 60 runs below 5 cm; all positive) |
| Mean steps to goal | 480 (≈ 24 s simulated time at dt = 0.05 s) |
| Mean path length driven | 25.7 m |
| Replans per episode (event-driven) | 4.7 |
| Unknown obstacles discovered by sensors | 60 % |
| Mean compute time per control cycle | 0.10 ms (laptop CPU) |
Full per-seed data: docs/benchmark_results.csv · Summary: docs/benchmark_summary.json · Chart: images/benchmark_summary.png
Autonomous mobile robots (warehouse AGVs, delivery robots, self-driving cars, drones) must reach a goal without knowing the whole environment in advance, while never hitting people or objects. Two questions must be answered continuously:
- What is around me? → perception and mapping
- Where do I go next, safely? → planning, control and safety
This project implements both in a transparent, testable form.
The same layered architecture (perception → world model → global planner → local tracker → safety override) appears in production stacks such as Autoware and Apollo, in ROS 2 navigation (nav2), and in warehouse robotics from companies like Amazon Robotics and Locus. Pure pursuit and A* are standard baselines in both industry and academic robotics courses. This project implements each layer in plain Python so every decision can be read, measured and explained.
| Layer | Tool | Why |
|---|---|---|
| Language | Python 3.11+ | Industry standard for robotics prototyping |
| Vision | OpenCV (HSV threshold, contours, free-space rays) | Fast, CPU-only, used in real colour-tracking robots |
| Optional DL | Ultralytics YOLO (yolo_detector.py) |
Plug-in for real camera footage |
| Numerics | NumPy | Occupancy grids and vectorised geometry |
| Planning | A* on an inflated occupancy grid + line-of-sight smoothing | Optimal on a grid, explainable, fast |
| Control | Pure pursuit + turn-slowdown + side repulsion | Standard path tracker with an explicit safety layer |
| Simulation | Custom 2-D kinematic simulator with ray-cast ultrasonics and rendered camera | No GPU, no install headaches, fully deterministic |
| Visualisation | Matplotlib + Pillow (dashboard, GIF) | Headless-safe output for README and recruiters |
| Quality | pytest, GitHub Actions CI | Shows engineering discipline |
| Hardware (optional) | Raspberry Pi, HC-SR04, L298N, USB/CSI camera | Sim-to-real path |
Why not CARLA / Gazebo first? They need a GPU, large downloads and long setup, which blocks most students. The chosen simulator is small enough to read in an afternoon, and the same navigation code runs on a real robot (run_robot.py). CARLA is listed as a future upgrade.
┌────────────┐ ┌──────────────────────────┐ ┌─────────────────────────┐
│ Simulator │──▶│ Perception │──▶│ Navigator (world model) │
│ world │ │ • red-obstacle detector │ │ • sensor fusion → grid │
│ vehicle │ │ • free-space estimator │ │ • replan triggers │
│ ultrasonic│ │ • (optional) YOLO │ │ • safety override │
│ camera │ └──────────────────────────┘ └───────────┬─────────────┘
└─────▲──────┘ │ path
│ ┌─────────────────▼──────────────┐
│ v, ω (motor command) │ Planner: inflate → A* → smooth │
│ │ → resample (0.1 m) │
└────────────────────────────────────┴─────────────────┬──────────────┘
▼
┌────────────────────────────────┐
│ Control: pure pursuit + slow- │
│ down in turns + side repulsion │
└────────────────────────────────┘
Full module-by-module description: docs/architecture.md
AI-Autonomous-Navigation-System/
├── main.py # CLI: run an episode or a benchmark
├── run_robot.py # Same navigation stack on a real Raspberry Pi robot
├── configs/
│ ├── default.json # every simulation/planner/controller parameter
│ └── hardware.json # BCM pin map (fixes the GPIO 23 clash in the original guide)
├── src/
│ ├── simulation/ # world, vehicle physics, ultrasonic + camera simulators, scenarios
│ ├── perception/ # preprocessing, obstacle detector, free-space, optional YOLO
│ ├── planning/ # occupancy grid, A*, planner facade
│ ├── control/ # pure pursuit, navigator (fusion + replanning + safety)
│ ├── hardware/ # HC-SR04, L298N, camera drivers (Raspberry Pi only)
│ ├── visualization/ # dashboard renderer
│ ├── pipeline.py # one episode: sense → perceive → decide → act → log
│ └── benchmark.py # many-seed experiments and summary statistics
├── tests/ # 21 tests: planning, perception, control, simulator, custom maps, end-to-end
├── scripts/ # export site data & generate proof screenshots
├── notebooks/ # interactive Jupyter exploration notebooks (perception, A* planning, EDA)
├── data/ # benchmark results & sample maps (warehouse, bottleneck, obstacle course)
├── models/ # optional model weights (see models/README.md)
├── images/ # screenshots used in this README
├── videos/ # demo GIF
├── docs/ # live GitHub Pages website (interactive replay, canvas HUD, telemetry)
├── outputs/ # generated by runs (git-ignored)
├── .github/workflows/ # GitHub Actions CI (tests) & automated GitHub Pages deployment
├── requirements.txt
├── requirements-optional.txt
├── pytest.ini
└── .gitignore
Requires Python 3.11+ (tested on 3.13). No GPU needed.
Windows (PowerShell)
python -m venv .venv
.\.venv\Scripts\Activate.ps1
python -m pip install --upgrade pip
pip install -r requirements.txtmacOS / Linux
python3 -m venv .venv
source .venv/bin/activate
python -m pip install --upgrade pip
pip install -r requirements.txtCheck the install:
python -c "import cv2, numpy, matplotlib; print('OK', cv2.__version__)"
pytest -q# 1. One episode with terminal progress, dashboard PNG, metrics, trajectory and GIF
python main.py run --seed 7 --gif
# outputs/runs/seed_007/dashboard.png | metrics.json | trajectory.csv | navigation.gif
# 2. Benchmark 60 seeded worlds, save CSV + summary + chart
python main.py benchmark --episodes 60
# outputs/benchmark/results.csv | summary.json | benchmark_summary.png
# 3. Custom map episode (e.g. warehouse corridors, narrow passage, obstacle course)
python main.py run --map data/sample_maps/warehouse_corridors.json
# 4. Tests (unit + custom map + end-to-end regression)
pytest -qSuccess looks like: the terminal ends with "final_state": "GOAL_REACHED", "collisions": 0, and dashboard.png shows a green trajectory from the white start dot to the gold star.
Sample terminal output (seed 7, abridged):
Running episode seed=7 -> outputs/runs/seed_007
[t= 0.00s] state=DRIVING pos=( 2.00, 2.00) v=0.05 front=2.00m replans=0
[t= 5.00s] state=DRIVING pos=( 6.10, 4.39) v=1.18 front=2.00m replans=1
[t= 10.00s] state=DRIVING pos=( 9.84, 8.62) v=1.20 front=2.00m replans=2
[t= 15.00s] state=DRIVING pos=(14.36,12.11) v=1.09 front=2.00m replans=3
[t= 20.00s] state=DRIVING pos=(17.27,17.09) v=0.66 front=2.00m replans=3
=== EPISODE RESULT ===
{ "success": true, "final_state": "GOAL_REACHED", "steps": 409, "sim_time_s": 20.45,
"planned_length_m": 22.261, "path_length_m": 22.31, "replans": 3,
"collisions": 0, "min_clearance_m": 0.6, "unknown_discovered": 2, "unknown_total": 4 }
- Scenario generation — a 20 × 20 m arena with 12 circular obstacles. Four are unknown (absent from the prior map). A scenario is accepted only if a path exists with full knowledge and the prior-map path is actually blocked by an unknown obstacle, so every run exercises replanning.
- Prior map — the robot starts with known obstacles, inflated by its radius plus a 0.5 m safety margin.
- Sense — three simulated HC-SR04 beams (left, front, right) ray-march through the world with Gaussian noise. A 6 m top-down camera image is rendered with obstacles, goal and noise.
- Perceive — red-obstacle HSV mask → contours → enclosing circles → metric detections in the robot frame. A free-space estimator scores directions.
- Fuse and decide — detections and echoes are written into the robot's map. If an obstacle touches the remaining path, A* replans from the current pose. Replans also fire when the robot drifts more than 0.5 m off its path.
- Safety — if the front echo is below 0.45 m, the robot stops and turns toward the more open side. Side echoes slow it down and push it away from nearby obstacles.
- Act — pure pursuit tracks a 0.1 m-spaced path (lookahead 1.0 m). Speed drops in sharp turns, near obstacles, and near the goal. The vehicle model enforces speed, turn-rate and acceleration limits.
- Log — every run writes a dashboard, trajectory CSV and metrics JSON. Ground-truth collisions and clearance are computed from the true world, which the navigator never sees.
| Problem found during testing | Root cause | Fix |
|---|---|---|
| 17 collisions in the first run | Pure pursuit steered at sparse waypoints, so the "lookahead" point could sit across an obstacle | Resample the path to 0.1 m spacing |
| Robot drove along the arena wall | Walls were not inflated in the planning grid | Block cells within the margin of the walls |
| Oscillation between two routes | Periodic replanning flipped between homotopy classes | Replan on events and off-path error only |
| Robot spun in place next to a wall | Emergency stop looked at side sensors and deadlocked | Front sensor brakes; sides slow down and repel |
| Robot stuck with no path | Narrow gap plus a 0.5 m margin left no route | Graceful degradation: retry with a 0.12 m clearance, otherwise stop |
| Robot drifted, index froze | Tracker searched only 40 points ahead | Search the full remaining path |
Tuning note: a planning margin of 0.45 m produced collisions, and 0.5 m produced none across 60 seeds. The margin is a documented, tunable safety parameter.
Raw per-episode data: docs/benchmark_results.csv · Summary: docs/benchmark_summary.json
The navigator is the same code on the robot. Only the sensors and actuators change. Wiring, the corrected pin map and the 5 V → 3.3 V level shifter for the HC-SR04 echo are in docs/hardware_wiring.md.
python run_robot.py --goal 2.0 1.5 # on the Raspberry Pi, robot lifted off the ground firstThe hardware drivers are written and syntax-checked but have not been tested on a physical robot in this project. Treat the simulator results as the verified part.
- Real camera + YOLOv8 detection (
src/perception/yolo_detector.pyis ready) - ROS 2 wrapper, using
nav2costmaps and/cmd_vel - Hybrid A* or RRT* for non-holonomic (car-like) motion
- SLAM (e.g. GMapping or a lightweight EKF) instead of an assumed prior map
- Dynamic (moving) obstacles with time-aware planning
- CARLA integration for urban driving scenarios
- Reinforcement-learning local planner, compared against the baseline in the benchmark
The interactive site lives in docs/ as pure HTML, CSS and JavaScript with an offline fallback. It replays real simulation runs on an HTML5 canvas and graphs the live benchmark CSV:
- Automated Deploy (GitHub Actions):
.github/workflows/pages.ymlautomatically deploys the site to GitHub Pages whenever you push tomain. - Manual Branch Deploy: Alternatively, in your GitHub repository:
- Repo Settings > Pages.
- Source: Deploy from a branch. Branch:
main, folder:/docs. Save. - The site goes live at
https://<username>.github.io/<repo-name>/.
To refresh the replay data after tweaking simulator or planner parameters:
python scripts/export_site_data.py --seed 7
python scripts/generate_screenshots.py --seed 7- Designed a layered autonomy architecture with clear interfaces between modules
- Implemented A*, path smoothing, pure pursuit and sensor fusion from first principles
- Diagnosed real control bugs with instrumented debugging and fixed them with measured evidence
- Built a reproducible benchmark, automated tests and CI
- Understood the sim-to-real gap and how hardware pins, voltage levels and safety interact
Rohit Singh · Indian Institute of Technology Delhi (IIT Delhi) GitHub · rohitsingh89788@gmail.com
MIT. See LICENSE.









