MEAM 6200 · Simulation stack and Crazyflie hardware flights
Autonomous Quadrotor: Estimation, Planning and Control
A full GPS-denied autonomy stack — A* planning, curvature-scheduled trajectories, SE(3) geometric control and a stereo-inertial ESKF — scoring 93.29/100 in simulation, then flown on a real Crazyflie through three mazes under Vicon.

Period
Aug – Dec 2025
Stack
SE(3) Control · VIO / ESKF · A* · Minimum-Jerk · Crazyflie · Python
Highlights
- 0193.29/100 on the six-map autograder with the VIO estimate closing the loop — no ground truth anywhere in the controller
- 02All six extra-credit maps passed at full points (30/30)
- 03SE(3) geometric controller on the true nonlinear dynamics, driven by a stereo-inertial error-state Kalman filter
- 04Curvature-based time allocation with forward and backward feasibility passes (v_max 8.1 m/s, a_max 5.2 m/s², gamma = 4.0)
- 05Flown on a Crazyflie 2.x under 100 Hz Vicon: three maze runs, start-to-goal, no collisions
- 06Measured hardware tracking of 30–36 cm RMS and 83 cm peak — which showed the 0.2 m obstacle inflation margin was smaller than worst-case error
- 07Found the starter-code bug where the planner rebuilt an empty occupancy map on every call, so A* was planning straight through walls
Modules & Architecture
SE(3) geometric controller▼
Position PD producing a desired force vector, from which the desired body frame and collective thrust follow. It works on the rotation group rather than a hover linearization, so it stays valid through aggressive attitude. On hardware the outer position loop runs on the ground station and hands a desired quaternion to the Crazyflie's onboard rate controller.
A* search and line-of-sight shortcutting▼
A* over a 0.15 m occupancy voxel grid with obstacles inflated for a spherical collision model. A greedy shortcutter then probes ahead and keeps the furthest waypoint reachable by a collision-free straight segment, cutting the path from O(100) waypoints to O(10).
Trajectory generation and time allocation▼
C4-continuous piecewise fifth-order polynomials through the sparse waypoints, with continuity of velocity, acceleration, jerk and snap at interior points. Segment speeds are scheduled by local turn angle, then made dynamically reachable by forward and backward acceleration passes.
Stereo-inertial ESKF in the loop▼
IMU propagation of the error state with stereo feature measurement updates, supplying the position, velocity and attitude the controller acts on. Closing this loop is what forced every tuning decision in the project.
Hardware flights — Crazyflie 2.x + Vicon (Team 8)▼
Three maze runs on a 30 g Crazyflie with 100 Hz Vicon pose over a ROS bridge, commands relayed at 100 Hz over Crazyradio. All gains reduced by roughly 50% from simulation values to survive measurement noise, thrust mismatch and ground effect. Team project with Shuyu Zhang, Samhitha Vedire and Bowen Wang.
Extra credit: planning on a sensor-range map▼
The starter code rebuilt an empty occupancy map on every planner call, so A* planned straight through walls and the vehicle collided on every local map. Fixing that, plus a larger 0.5 m margin, took all six maps to full points. Worth stating plainly: this reveals the whole map up front and plans once, so it does not implement the receding-horizon replanning the task was really asking for.
Demo video
Maze flight on the Crazyflie, under Vicon
Write-up
This was built in three stages that only became interesting once they were connected. First a planner and controller driven by the simulator's true state: A* over an inflated voxel grid, a spline through the shortcut waypoints, and an SE(3) geometric controller tracking it on the full nonlinear dynamics. Then, separately, a stereo-inertial error-state Kalman filter that produced a state estimate but never actually flew anything. The third stage closed the loop — the controller now sees the noisy ESKF estimate and nothing else.
That switch broke everything that had worked. Tuning that is comfortable against perfect state becomes unstable against an estimate, because small estimation errors feed the controller, the vehicle drifts off the spline, and the controller saturates chasing it. The real lesson is that closed-loop bandwidth is capped by the estimator: any gain or commanded acceleration that pushes content above what the ESKF can track makes the estimate oscillate, and then the controller faithfully chases that oscillation.
Two failure modes bounded the tuning from opposite sides. Too aggressive and the vehicle flew away — position error past the simulator's 20 m abort limit. Too conservative and it could never satisfy the simultaneous position, velocity and attitude conditions at the goal, circling in a limit cycle until the 150 s timeout. The two regions do not fully overlap, which is the way out: raising the acceleration limit while lowering the curvature gain gets the vehicle to corners faster and slows it less in them, so the controller never has to track a large step in commanded speed. Capping top speed at 8.1 m/s keeps straight-line flight inside what the VIO loop can deliver. That combination scored 93.29/100 across all six maps.
Hardware changed the constants, not the structure. On a 30 g Crazyflie 2.x with Vicon pose at 100 Hz, millimetre-level measurement noise and roughly 10 ms of latency cap the derivative gain long before the theory says they should; unmodelled mass and thrust-curve mismatch leaves a standing offset; ground effect and prop wash add disturbances simulation never showed. Every gain came down by about half. The step response settled at roughly 1 s rise time, 21% overshoot, damping ratio around 0.45.
The most interesting hardware finding was a systematic 15 cm upward drift during lateral moves. When the vehicle pitches hard to chase a lateral acceleration, the thrust vector tilts off vertical and its vertical component drops. The altitude loop compensates, but with a ~1 s rise time it cannot react instantly, so the transient accumulates over sustained motion — an attitude-coupling effect distinct from the hover steady-state error, and fixable with a feedforward term for the tilt angle.
Measuring tracking error across the three maze runs produced the result worth keeping: 30–36 cm RMS with peaks to 83 cm, against an obstacle inflation margin of 0.2 m. The flights succeeded, but only because the planner happened to route well clear of surfaces — the margin was never actually large enough to cover worst-case error. At least 0.35 m is the honest recommendation, at the cost of tighter feasible passages.