← All projects

Event-Triggered Tube MPC for a Crazyflie Quadrotor

ROS 2, Gazebo, CrazySim SITL, CVXPY + OSQP, Docker
Linear Control Systems course project (team), 2026 · my part: the simulation stack and the Docker image
code / Docker image

Tube MPC keeps a drone safe under bounded disturbances: a nominal MPC plans a disturbance-free path, and an LQR feedback law holds the real drone inside a robust tube around it. Standard tube MPC solves a QP at every step, which is expensive for a nano-quadrotor. Our event-triggered version re-solves only when the tracking error is about to leave the tube. We tested it offline under four disturbance scenarios and then flew it on a Bitcraze Crazyflie 2.1 in CrazySim software-in-the-loop (SITL).

Tube
The mRPI safety tube

The drone is modelled as a 3D double integrator. The LQR gain K makes the error dynamics AK = A − BK stable, so the error stays in a minimal robust positively invariant (mRPI) set Ω for any bounded disturbance. Ω is a 72-facet polytope with a radius of 0.408 m. The MPC plans with constraints tightened by Ω, so the real drone stays inside the true limits.

Trigger
Solve only when needed

The controller re-solves the nominal QP (CVXPY + OSQP, horizon 20, 20 Hz) only when the tracking error stays near the tube boundary for 3 steps in a row, or when the stored plan runs out. Between solves, the LQR law tracks the stored plan.

Event trigger timelines for four scenarios: 15, 32, 18 and 16 solves out of 200
QP solves over 10 s in each scenario: 15, 32, 18 and 16 out of 200 steps.
Stress test
Four disturbance scenarios

Offline, against standard MPC and full tube MPC (both re-solve at every step): persistent crosswind, 100% payload drop, high-speed catch with a gust, and a UWB sensor glitch. The event-triggered controller solved the QP 15–32 times instead of 200 (84–93% fewer) with zero constraint violations in every scenario. The cost is a higher tracking error (RMSE 0.64–0.84 m against 0.55–0.79 m for standard MPC).

Bar charts of tracking RMSE, constraint violations (none) and QP solve count for standard, full tube and event-triggered tube MPC
Tracking RMSE, constraint violations (none for any controller) and QP solves, for each scenario.
SITL
Flying the Crazyflie in simulation

I integrated CrazySim, the Crazyflie firmware in SITL and our MPC ROS 2 package into one Gazebo + ROS 2 + RViz pipeline. The drone flew M- and S-shaped waypoint paths end to end, with no bound violations. RViz shows the tube live around the nominal pose, and a red marker at each trigger.

Gazebo with the Crazyflie on the left and RViz on the right showing the M-shaped flight path and the blue tube
M path: Gazebo (left) and RViz (right) with the flight trail and the mRPI tube (blue cylinder).
Gazebo and RViz during the S-shaped flight path
S path, same drone and arena.
Debug
Making SITL fly

The first stack did not fly. The SITL firmware ignored commands sent through Crazyswarm2, so I wrote a direct CFLib bridge that keeps one connection open for the whole run. Predicting the setpoint forward from odometry caused a runaway climb to 8.65 m; sending the MPC's own nominal position and velocity fixed it. The first arena limits excluded some waypoints, so the QP became infeasible near the boundary; wider limits and a regenerated tube fixed that.

Docker
One-command demo

I packaged the full stack (Gazebo, ROS 2, Crazyflie SITL, CFLib and the MPC) into one Docker image of about 2.6 GB, with X11 display and software-rendering fallback. On any Ubuntu machine, phase2 M or phase2 S starts the full demo.

My part

The team designed the controller together. My part was the simulation stack (CrazySim, firmware SITL, the CFLib bridge, the tube visualisation and the launch flow), the debugging needed to make the drone fly, and the Docker image.

What I learnt

  • Robust MPC: mRPI sets, constraint tightening, and why the tube gives guarantees that plain MPC does not.
  • Compute against accuracy: event triggering saves most of the solver work, and costs some tracking error.
  • SITL integration: firmware, simulator and ROS 2 each have their own timing and connection rules.
  • Reproducibility: a pinned Docker image lets anyone run the demo without the setup work.