Victor Stepanov

Roboticist

Autonomous Path Planning

A modular C++ autonomy stack with A*, PRM, RRT planners and spline-based trajectory generation.

🧭 Overview

After graduate school, I realized there was a significant gap between the structured material taught in Modern Robotics and the practical systems described in Planning Algorithms by Steven LaValle. I wanted to truly understand how real-world autonomous systems are architected—how a robot plans a path, smooths a trajectory, and executes it—all while adapting to mission goals. At the same time, I wanted to deepen my fluency in C++ by building something robust and modular from scratch.

This project became my sandbox for exploring autonomy: a C++ software stack for ground-based robots that spans from high-level behaviors to low-level trajectory generation.


🎯 Objectives

My goal was to create a reusable and extensible C++ autonomy stack that could serve as both a learning tool and a launchpad for future robotics work. I wanted clean separation between layers—global planning, local planning, behavior logic, visualization—so that each part could be swapped out, expanded, or unit tested independently. Bonus points if it could eventually plug into ROS2.


⚙️ What I Built

  • 2D C-Space Generator: Inflates obstacles to simulate robot-safe regions.
  • Global Planners:
    • A*: With cost heuristics and step-by-step visual debugging.
    • PRM: Probabilistic roadmap generation using random sampling and k-nearest neighbors.
    • RRT: Tree growth with random node expansion and collision checking.
  • Path Smoothing: Reduced jagged waypoints for more realistic movement.
  • Catmull-Rom Trajectory Generator: Converted smoothed paths into continuous-time trajectories.
  • CLI Interface: For selecting planners, setting start/goal inputs, and triggering output renders.
  • GridVisualizer: Debug utility that outputs .png images of planning behavior.
  • Simulation Layer: Compiles frame-by-frame outputs into .mp4 videos showing full robot motion.
  • Architecture:
    • Global Planners:
      A*, PRM, and RRT — each implemented from scratch with a common interface (planner/*.h) and visualized using the GridVisualizer.
    • Path Smoothing & Trajectory Generation:
      A custom smoother and Catmull-Rom spline generator located in trajectory/TrajectoryGenerator.h.
    • Behavior Layer:
      Includes high-level mission logic like DockingMission (behavior/docking/DockingMission.*) that orchestrates planning and execution via internal state transitions.
    • Local Planner:
      Simple stub implementation (local_planner/SimpleLocalPlanner.*) designed around a common interface to support future extensions.
    • Perception Layer:
      Modular grid processing components like OccupancyGrid2D, GridConversion, and ObstacleManager used for building and managing the robot’s world model.
    • Simulation Tools:
      A frame-by-frame simulator and video generator (simulation/SimulationRunner.h, GridVisualizer, and FrameRenderer) that compiles .mp4 visualizations of the planning output.

✅ Outcome

I now have a full-featured, modular C++ codebase that connects high-level robot intent to executable motion. It’s a working example of how global planners feed into trajectory smoothing, how behaviors structure mission logic, and how layers can be composed into a functioning autonomy stack.

The stack is already serving as a foundation for future projects. I plan to expand it to SE(2) planning, SLAM integration, and potentially port parts of it into ROS2. Most importantly, this project helped me solidify how all the components of autonomy actually fit together—from theory to working code.


🗂️ Project Structure

robotics-path-planning
├── Makefile
├── README.md
├── docs
│   ├── SystemArchitecture.md
│   ├── behavior
│   │   └── README.md
│   ├── images
│   │   └── architecture-diagram.png
│   ├── local_planner
│   │   └── README.md
│   └── perception
│       └── README.md
├── img
│   └── docking_simulation.mp4
├── include
│   ├── behavior
│   │   ├── Behavior.h
│   │   └── docking
│   │       └── DockingMission.h
│   ├── core
│   │   ├── CSpaceBuilder.h
│   │   └── GridTypes.h
│   ├── local_planner
│   │   ├── LocalPlannerInterface.h
│   │   └── SimpleLocalPlanner.h
│   ├── perception
│   │   ├── GridConversion.h
│   │   ├── ObstacleManager.h
│   │   ├── OccupancyGrid2D.h
│   │   └── PerceptionLayer.h
│   ├── planner
│   │   ├── AStarPlanner.h
│   │   ├── PRMPlanner.h
│   │   ├── PlannerInterface.h
│   │   └── RRTPlanner.h
│   ├── simulation
│   │   ├── FrameRenderer.h
│   │   ├── GridVisualizer.h
│   │   └── SimulationRunner.h
│   └── trajectory
│       └── TrajectoryGenerator.h
└── src
    ├── behavior
    │   └── docking
    │       └── DockingMission.cpp
    ├── control
    ├── core
    │   └── CSpaceBuilder.cpp
    ├── local_planner
    │   └── SimpleLocalPlanner.cpp
    ├── main.cpp
    ├── path.cpp
    ├── perception
    │   ├── GridConversion.cpp
    │   ├── ObstacleManager.cpp
    │   ├── OccupancyGrid2D.cpp
    │   └── PerceptionLayer.cpp
    ├── planner
    │   ├── AStarPlanner.cpp
    │   ├── PRMPlanner.cpp
    │   └── RRTPlanner.cpp
    ├── simulation
    │   ├── FrameRenderer.cpp
    │   ├── GridVisualizer.cpp
    │   └── SimulationRunner.cpp
    └── trajectory
        └── TrajectoryGenerator.cpp

26 directories, 42 files