How it is built
Architecture overview
A flight controller is the small computer that keeps a civilian multirotor or fixed-wing aircraft in the air. It reads inertial and other sensors at a high rate, estimates the aircraft's attitude, velocity and position, compares that estimate with what the pilot or the mission wants, and writes motor and servo commands, all on a fixed clock that does not skip. A multirotor cannot be flown open loop for even a second, so the control loops are the aircraft's stability, not an add-on to it.
The software is a cascade. An outer loop turns a position or velocity target into a desired tilt and thrust; a middle loop turns attitude error into a desired body rotation rate; an inner loop turns rate error into torque demands; a mixer turns thrust and torque demands into one command per motor. Each inner loop runs faster than the one outside it, so the outer loop sees an inner loop that has already settled. Next to the cascade sit the state estimator, the sensor drivers, a mode and failsafe state machine, a logger, and a link to the ground station. PX4 and ArduPilot are the open full-featured stacks; Betaflight is the open stack tuned for racing and freestyle multirotors with a very fast inner loop.
Parts:
- Sensor drivers — read gyro, accelerometer, barometer, magnetometer, GNSS over the board's buses — spi-i2c-bus-drivers (no page yet), dma-transfers (no page yet), Interrupt handling
- State estimator — fuse sensors into attitude, velocity, position — sensor-fusion (no page yet), built on Extended Kalman filter, complementary-filter (no page yet), Rigid-body transforms and Quaternion rotations
- Signal filtering — remove vibration and noise before the control loop — biquad-filters (no page yet), built on Fast Fourier transform
- Controllers — position, attitude and rate loops — PID control, and pure-pursuit-path-tracking (no page yet) for path following
- Mixer and output — turn thrust and torque demands into motor commands — control-allocation-mixing (no page yet), built on PWM generation
- Scheduler — run each task at its rate with priorities — Fixed-rate control loop and Preemptive priority scheduling
- Mode and failsafe logic — arming, flight modes, link-loss and battery responses — Hierarchical state machine
- Internal messaging and logging — pass data between tasks, record the flight — SPSC ring buffer and CRC-32C checksums
gyro/accel ──SPI+DMA──► drivers ──► notch/low-pass filters ──┐
baro, mag, GNSS ──I²C/UART──► drivers ───────────────┐ │
▼ ▼
state estimator (EKF or complementary filter)
│ attitude, velocity, position
pilot / mission ─► mode logic ─► position ─► velocity ─► attitude ─► rate (PID) ─► mixer ─► PWM / digital ESC
(state machine) loop loop loop loop │
▼
motors
all stages ──► message queues ──► logger (CRC-protected blocks) and ground link
There are two profiles of the same design. A racing or freestyle profile pushes the rate loop and the gyro sampling as fast as the chip allows and does little else. A navigation profile (survey, inspection, delivery, manned light aircraft autopilots) adds position estimation with GNSS, waypoint missions and failsafes, and runs the slower outer loops on the same cycle structure.
How the parts fit together
Sensor drivers
The inertial measurement unit (IMU) is the heartbeat. A typical board reads the gyro and accelerometer over SPI, which is fast enough for sampling in the kilohertz range, and slower sensors (barometer, magnetometer, GNSS) over I²C or UART. Sampling must be regular: the IMU raises a data-ready signal, an interrupt runs a short handler that only stamps the time and wakes a driver task, and bulk transfers are handed to DMA so the CPU is not blocked while the bytes arrive (dma-transfers, no page yet). The driver tags every sample with the timestamp of the data-ready event, not the time the CPU got round to reading it. A timestamp error of a millisecond is a significant angle error during a fast rotation, and the estimator cannot recover it afterwards. Bus errors are counted and a sensor that stops answering is marked failed, which is what lets the failsafe logic act.
State estimator
The estimator turns raw, drifting measurements into a usable state. Attitude comes mainly from the gyro, which is accurate over short times but drifts, corrected slowly by the accelerometer (which measures gravity when the vehicle is not accelerating) and the magnetometer (heading). The cheap and robust form is a complementary filter (no page yet): integrate the gyro, and pull the result towards the accelerometer and magnetometer attitude with a small gain. Mahony and Madgwick are the best-known formulations, and Mahony et al. give a stability proof for the nonlinear filter on the rotation group. Attitude is held as a quaternion because it composes cheaply and has no gimbal lock; rigid-body transforms relate the body frame to the navigation frame.
For position and velocity the standard is an extended Kalman filter. The state holds attitude, velocity, position and the sensor biases; prediction integrates the IMU at its full rate, and corrections arrive when GNSS, barometer, magnetometer, optical flow or airspeed data come in, each with a noise model and a consistency test that rejects an innovation that is too large. This is the sensor-fusion (no page yet) pattern. PX4's estimator is called EKF2; ArduPilot's is EKF3. Because the measurements arrive late and at different rates, the filter keeps a short buffer of its own past states and applies each measurement at the time it was taken.
Signal filtering
Propellers and motors shake the airframe, and the gyro measures that shaking at the motor frequency and its harmonics. Feeding it into the derivative term of a PID or into the estimator saturates the motors and heats them. Filtering is the answer, and it is a trade-off: every filter adds delay, and delay in a feedback loop reduces the margin of stability. The building block is the second-order recursive filter (biquad-filters, no page yet) in cascades: low-pass filters to remove broadband noise and notch filters to remove narrow peaks. The peaks are found by spectral analysis with the fast Fourier transform on logged or live gyro data, and in flight a dynamic notch follows the peak as throttle changes; in racing firmware the frequency can come from telemetry of the motor speed. The filter design directly sets how aggressive the PID gains can be.
Controllers
The inner loop is a PID controller per axis on body rate. The proportional term reacts to the present error, the integral term removes steady offsets such as an unbalanced battery, and the derivative term (computed on the measurement, not the error, to avoid kicks on set-point steps) damps the response. Anti-windup is mandatory, because the integral must stop growing when the motors are already saturated. A feed-forward term from the stick or the trajectory reduces lag. The attitude loop outside it is typically a proportional controller on the attitude error, giving a rate command; the velocity and position loops continue the cascade.
For fixed-wing and for waypoint following, a path has to be tracked rather than a point. Geometric methods such as pure pursuit (pure-pursuit-path-tracking, no page yet) aim at a look-ahead point on the path and steer towards it; the nonlinear guidance logic used in fixed-wing autopilots (the "L1" family) is the same idea written as a lateral acceleration command. Longer look-ahead gives smooth but corner-cutting paths; shorter gives tight but oscillating paths.
Mixer and output
The controllers decide a total thrust and three torques. control-allocation-mixing (no page yet) maps them to one command per actuator through a matrix that depends on the airframe geometry: for a quadcopter in X configuration, each motor gets the thrust plus a signed share of roll, pitch and yaw. The mixer has to handle saturation. If one motor would be driven above its maximum, naive clipping changes the attitude torque the vehicle receives; good mixers scale down the lower-priority demands (typically yaw first) or shift the whole thrust so that roll and pitch authority is kept. PX4 documents its control allocation, with an effectiveness matrix per vehicle type, as a replacement for fixed mixers, and it also handles vehicles with tilting rotors and surfaces.
The result goes to the speed controllers (ESCs). Classic hobby ESCs take a PWM pulse whose width carries the command; a timer's period and compare registers draw the pulse train, with DMA to avoid CPU involvement at high rates. Digital protocols such as DShot send the command as a digital word with a checksum and avoid the analogue calibration problem; PX4 documents DShot support, and bidirectional DShot carries motor speed back, which is what feeds the dynamic notch.
Scheduler
Everything above has to run on a clock that never skips. The fixed-rate control loop
discipline applies: the rate loop executes at an exact period, computed against absolute deadlines, with a fixed
dt used in the integrators and filters instead of whatever interval was measured. Tasks run at different rates
(rate loop at the fastest, attitude and estimator slower, navigation and logging slowest) under
preemptive priority scheduling: the highest-priority ready task runs, and a short
control task preempts a long logging task at once. PX4 runs on the NuttX real-time operating system (and Linux on
some targets) with a work-queue structure; ArduPilot uses ChibiOS. A watchdog resets the processor if the main loop
stops, and, as a design rule, the control path must not wait on storage or on the radio.
Mode and failsafe logic
Which loop is active, and what its targets are, depends on the flight mode: manual and acrobatic rate control, stabilised attitude, altitude hold, position hold, mission, return-to-launch, land. A hierarchical state machine fits well, because many reactions are shared by all sub-modes (disarm on a crash, return on low battery, land on loss of the estimator), and sub-modes inherit them instead of copying them. Arming has pre-conditions (sensors healthy, calibration good, estimator converged, battery sufficient), and failsafes are a prioritised list of triggers (radio link lost, data link lost, battery critical, geofence breach, estimator failure) and responses. The state machine must also be safe to re-enter: after a momentary radio loss the vehicle should not oscillate between "return" and "manual".
Internal messaging and logging
Tasks exchange data through typed queues: PX4's uORB is a publish-subscribe layer inside the process, with the latest value always available to a late subscriber. Where one task produces and one consumes, a single-producer single-consumer ring buffer gives a wait-free hand-off without locks, which is what you want between the IMU task and the logger. The logger writes selected topics to an SD card or flash; because power can be cut by a crash, the log is written in blocks with a CRC-32C so a damaged tail is detected and skipped on read. The same checksum protects stored parameters. Telemetry to the ground station uses MAVLink, a compact framed protocol with its own checksum and sequence number.
Data and control flow
One control cycle (multirotor, navigation profile):
- The IMU data-ready interrupt fires; the driver reads the sample by DMA, stamps it, and publishes it.
- The filters process the sample; the estimator predicts with it and applies any measurements that are due.
- At the position-loop rate the position and velocity controllers turn the mission or stick target into a tilt and thrust request.
- At the attitude rate the attitude error becomes a rate setpoint.
- At the rate-loop rate the PID loop turns the rate error into torque demands; the mixer allocates motor commands; the outputs update (PWM or DShot).
- Logging and telemetry consume the same samples at a lower rate.
A failsafe event: the radio link is lost; the mode logic checks the configured response, switches to return-to-launch, the position loops fly the path home, and land logic takes over near the target. If the estimator reports a lost position, the state machine drops to a mode that does not need position (for instance descent under attitude control).
Scaling
Limits, in the order they bite:
- Loop latency from sensor to motor: sampling, filtering and the output protocol add delay. Levers: higher gyro sampling rates, lighter filters, faster output protocols, DMA.
- CPU and memory on a microcontroller. The estimator and the logger compete with the rate loop. Levers: a chip with a floating-point unit, moving heavy work to a companion computer, bounded queues.
- Vibration and noise limit usable gains more than CPU does. Levers: mechanical damping, notch filters, balanced propellers, rate-limited derivative terms.
- Vehicle configurations: a stack that supports many frames needs a configurable mixer and a parameter system, not hand-written code per airframe. Levers: geometry-driven control allocation.
- Aircraft size and certification context: for larger civilian aircraft, redundant sensors and processors with cross-checking become necessary; this design does not claim to provide it on its own.
Failure modes
| Failure | Symptom | Cause | Fix |
|---|---|---|---|
| Vibration noise | motors hot, twitching in hover, derivative term noisy | frame resonance, unbalanced props, gyro aliasing | soft-mount the IMU, notch and low-pass filters, higher sample rate |
| Timing jitter | oscillation that tuning does not fix | loop not periodic, variable dt, long interrupt | absolute deadlines, fixed dt, short interrupt handlers, priorities |
| Integrator windup | overshoot after saturation, slow recovery | integral grows while motors are clipped | anti-windup, saturation-aware mixer |
| Bad heading or position | flyaway or toilet-bowl circles | magnetometer disturbed by motor current, wrong frame convention | compass calibration and motor compensation, estimator innovation checks |
| Mixer saturation | uncontrolled yaw or flip at full throttle | one motor clipped, torque authority lost | priority-aware allocation, thrust limits, headroom |
| Sensor bus failure | sudden stop of IMU data | bus error, bad cable, interrupt storm | error counters, failover to a second IMU, failsafe to a safe mode |
| Corrupted log or parameters | boot with default or wrong parameters | power loss during write | checksummed blocks, double-buffered writes |
| Mode oscillation | repeated switching between return and manual | threshold chatter on link or battery | hysteresis and latching in the state machine |
Real implementations
| name | what it is | repo | licence | notes |
|---|---|---|---|---|
| PX4 Autopilot | open flight stack for multirotors, planes and VTOL; uORB, EKF2, control allocation | PX4/PX4-Autopilot | BSD-3-Clause | docs at docs.px4.io |
| ArduPilot | open autopilot for copters, planes, rovers and boats | ArduPilot/ardupilot | GPL-3.0 | EKF3 estimator |
| Betaflight | open firmware for racing and freestyle multirotors | betaflight/betaflight | GPL-3.0 | fast gyro loop, dynamic notch |
| MAVLink | the telemetry and command protocol used by PX4 and ArduPilot | mavlink.io | see repo | message definitions and framing |
The alternative: a flight controller can be a single loop on a microcontroller without an operating system (a cyclic executive), which is simpler to reason about for a small, fixed airframe. A companion-computer architecture puts the navigation and vision tasks on a Linux board that talks to the flight controller over MAVLink, leaving the hard real-time loops on the microcontroller. Pick the RTOS-based stack when the vehicle needs several flight modes and several tasks at different rates; pick the companion-computer split when perception is heavy.
Sources
- R. Mahony, T. Hamel and J.-M. Pflimlin, Nonlinear complementary filters on the special orthogonal group, IEEE Trans. Automatic Control, 2008. DOI
- PX4 documentation: architecture overview, control allocation, uORB messaging, EKF2 navigation filter, DShot.
- R. C. Coulter, Implementation of the Pure Pursuit Path Tracking Algorithm, CMU Robotics Institute technical report, 1992. PDF
- MAVLink protocol: mavlink.io.