Skip to the content
FixTheRobot Explore Robotics / UAV / Module 7 / M7-T4

UAV Systems Engineering · Module 7

M7-T4: Real-time operating systems

Real-time does not mean fast. It means the worst case is known and bounded, which is what a control loop needs.

  • Lesson 4 of 19
  • Embedded Systems, Timing and System Integration
  • Established engineering
  • About 6 minutes to read

A control loop that usually runs in 2 ms and sometimes in 40 ms is a loop that eventually fails. A real-time operating system gives bounded scheduling latency and tools to reason about the worst case. This lesson covers the core ideas and what they mean for PX4’s NuttX and for a Linux companion.

Learning objectives

After this lesson, you should be able to:

  • Define hard, firm and soft real-time and give a UAV example of each.
  • Run a response-time analysis for fixed-priority tasks.
  • Explain priority inversion and priority inheritance.
  • Compare how NuttX on a flight controller and Linux on a companion handle real-time requirements.

Conceptual explanation

Established Fixed-priority scheduling theory is from Liu and Layland (1973) and the response-time analysis literature; priority inheritance from Sha, Rajkumar and Lehoczky (1990). Whether a particular OS configuration meets a deadline is a measurement, not a property of its name.

A real-time system must produce results within deadlines. Hard real-time means a missed deadline is a failure (an attitude loop that misses its cycle); firm means a late result is useless but not catastrophic (a late camera frame is dropped); soft means lateness degrades quality (a slightly late video preview).

An RTOS provides preemptive priority scheduling: the highest-priority ready task always runs, a task is preempted as soon as a higher-priority one becomes ready, and the time to do so is bounded. Ingredients that must also be bounded: interrupt latency, the time interrupts are masked, and the time a task can be blocked by lower-priority tasks holding shared resources.

  • NuttX (used by PX4 on flight controllers) is a POSIX-like RTOS with priority scheduling; PX4 runs its modules as tasks or work-queue items with priorities.
  • Linux (on a companion) is a general-purpose OS: it can provide soft or, with the PREEMPT_RT patch and care, firm real-time behaviour, but its worst-case latency depends on drivers, kernel configuration and load, and must be measured (for example with cyclictest).
Real-time schedulingTasks have periods and deadlines; the scheduler runs the highest-priority ready task and preempts lower ones. Schedulability analysis shows whether all deadlines are met in the worst case, including blocking by shared resources.Tasksperiod, WCET, deadlinePrioritiesrate-monotonicSchedulerpreemptiveResourcesmutex, inheritanceAnalysisresponse timeReal-time means predictable worst-case timing, not “fast”.
Worst-case thinking: periods, priorities, blocking, response time.
Animation of two schedules of three tasks sharing a lock. The low-priority task takes the lock first; the high-priority task arrives and must wait for it; a medium-priority task arrives and, without priority inheritance, preempts the low task so the high task is delayed by the medium task, which is priority inversion. With priority inheritance the low task temporarily runs at high priority, finishes its critical section and releases the lock sooner, and the high task completes earlier. Completion times are printed.
Priority inversion: HH is blocked on a lock held by LL, and MM (which does not need the lock) preempts LL, so MM effectively runs before HH. Priority inheritance raises LL to H’s priority while it holds the lock, bounding the blocking to one critical section. Discrete scheduler simulation with illustrative durations (time units of 1 ms); computed. (Looping, about 6 seconds; drawn and computed for this course with illustrative values.)

Engineering intuition

Imagine a small office where the phone (highest priority) interrupts a report (lower priority), and the report-writer occasionally holds the only photocopier that the phone-answerer also needs. If the phone-answerer waits for the copier while a medium-priority errand runs, the urgent job is delayed by an unrelated one: priority inversion. Priority inheritance fixes it by temporarily raising the copier holder’s priority so it finishes quickly.

The key mental shift is from average to worst case. The average execution time of the EKF is irrelevant; its worst-case execution time and the worst-case interference from higher-priority tasks decide whether its deadline holds.

Mathematical formulation

For fixed-priority preemptive tasks with execution time CiC_{i}, period TiT_{i} (deadline Di≤TiD_{i}\le T_{i}), blocking BiB_{i}, tasks indexed by decreasing priority, the worst-case response time RiR_{i} is the smallest fixed point of

Response-time analysis
Ri=Ci+Bi+∑j<i⌈RiTj⌉CjR_i = C_i + B_i + \sum_{j<i}\left\lceil\frac{R_i}{T_j}\right\rceil C_j
schedulable if Ri≤Di for all i\text{schedulable if } R_i \le D_i \text{ for all } i

Iterate from Ri(0)=Ci+BiR_{i}^{(0)}=C_{i}+B_{i} until it converges or exceeds DiD_{i}. For rate-monotonic priorities (shorter period, higher priority) and implicit deadlines (D=T)(D=T) the Liu-Layland sufficient bound is U≤n(21/n−1)U\le n(2^{1/n}-1). Priority inheritance bounds blocking to the length of one critical section of each lower-priority task per resource instead of unbounded blocking by medium-priority tasks. Jitter of a periodic task’s start, J=Rmax⁡−Rmin⁡J=R_{\max}-R_{\min}, enters the control design as extra delay.

CiC_{i}, TiT_{i}, DiD_{i}
worst-case execution time, period, deadline.
BiB_{i}
worst-case blocking from lower-priority tasks.
RiR_{i}
worst-case response time.

Architecture and data flow

Sensor interrupt (IMU data ready) → driver task (high priority) → estimator task → controller tasks → output driver. Lower-priority tasks: navigator, commander, MAVLink, logger. In PX4, modules run on work queues with defined priorities (rate controllers on the highest, logging and communication lower). Shared data goes through uORB, which is designed to avoid long blocking; any additional shared resource you add (a mutex in a custom module) becomes a candidate source of priority inversion.

Real-world UAV applications

  • Choosing priorities and periods for custom flight-controller modules.
  • Setting up a PREEMPT_RT or isolated-core configuration on a companion.
  • Explaining jitter in a flight log.
  • Writing the timing section of a safety case.

Implementation example

This runs as shown. Response-time analysis for a PX4-like task set (illustrative periods and worst-case execution times, not PX4’s actual values), with a blocking term to show priority inversion’s effect, and a check against a brute-force preemptive schedule simulation.

import math, numpy as np
tasks = [  # (name, period s, WCET s) rate-monotonic order: shortest period first. Illustrative values.
    ('rate ctrl', 0.004, 0.0006), ('attitude', 0.008, 0.0010), ('ekf', 0.010, 0.0025), ('navigator', 0.050, 0.0060), ('logger', 0.100, 0.0150)]
def response_times(tasks, blocking=None):
    R = []
    for i, (n, T, C) in enumerate(tasks):
        B = (blocking or {}).get(n, 0.0); r = C + B
        while True:
            r_new = C + B + sum(math.ceil(r / tasks[j][1]) * tasks[j][2] for j in range(i))
            if abs(r_new - r) < 1e-12 or r_new > T: r = r_new; break
            r = r_new
        R.append(r)
    return R
R = response_times(tasks); Rb = response_times(tasks, {'attitude': 0.0030})            # attitude blocked 3 ms by a lower-priority critical section
for (n, T, C), r, rb in zip(tasks, R, Rb): print(f"{n:>9}: T {T * 1e3:5.0f} ms  C {C * 1e3:5.2f} ms  R {r * 1e3:6.2f} ms  R with blocking {rb * 1e3:6.2f} ms  {'OK' if rb <= T else 'MISS'}")
# brute-force check by simulating preemptive fixed-priority scheduling in 10 us ticks
dt = 1e-5; H = 0.2; remaining = [0.0] * len(tasks); rel = [0.0] * len(tasks); worst = [0.0] * len(tasks)
for k in range(int(H / dt)):
    t = k * dt
    for i, (n, T, C) in enumerate(tasks):
        if abs((t / T) - round(t / T)) < dt / T / 2 and t > 0 or k == 0: remaining[i] += C; rel[i] = t
    for i in range(len(tasks)):
        if remaining[i] > 1e-12:
            remaining[i] -= dt
            if remaining[i] <= 1e-12: worst[i] = max(worst[i], t + dt - rel[i])
            break
print("simulated worst response (ms):", [round(w * 1e3, 2) for w in worst])
assert all(w <= r + 2e-4 for w, r in zip(worst, R)) and R[2] < tasks[2][1] and Rb[1] > R[1]
Response-time analysis with and without blocking, cross-checked by a tick-based preemptive schedule simulation. The task parameters are illustrative.

Common engineering mistakes

Equating real-time with fast

It is about bounded worst-case timing.

Using average execution times

Use measured worst case under load, with margin.

Unprotected shared resources

Priority inversion; use inheritance and short critical sections.

Too many high-priority tasks

The priority scheme collapses when everything is urgent.

Assuming a real-time kernel is real-time without measurement

Measure worst-case latency on your hardware under load (cyclictest).

Failure modes

Failure modes, symptoms and causes
Failure modeHow it shows upLikely cause
Occasional control-loop overrunRare glitches in attitudeWorst-case path or blocking longer than analysed
Priority inversionHigh-priority task stallsMutex held by a low-priority task, medium task preempting it
Starvation of low-priority tasksLogger or telemetry stopsUtilisation by high-priority tasks too high
Jitter in sensor timestampsNoisy dtTimestamping after the scheduling delay instead of at the interrupt

Debugging approach

  1. Measure per-task execution time distributions and the worst case.
  2. Trace scheduling events to find preemption and blocking.
  3. Check for mutexes shared across priorities.
  4. Timestamp at the interrupt, not in the task.

Practical exercises

  1. Compute RR for each task in your own module set and compare with the measured values.
  2. Add a task with a 20 ms period and 4 ms WCET and find which deadlines then fail.
  3. Run cyclictest on your companion with and without load and report the maximum latency.
  4. Explain priority inversion with a timeline for three tasks.

Interview questions

Write an answer in your own words, then reveal the model answer. Nothing is sent anywhere.

Question 1

What is the difference between hard and soft real-time?

Model answer

In hard real-time a missed deadline is a failure (an attitude control loop); in soft real-time it degrades quality (a late video frame).

Question 2

What is priority inversion and how is it avoided?

Model answer

A high-priority task waits for a resource held by a low-priority task that a medium-priority task preempts; priority inheritance temporarily raises the holder’s priority so that blocking is bounded.

Question 3

How do you show a task set is schedulable?

Model answer

Use utilisation bounds as a quick sufficient test, and response-time analysis with measured worst-case execution times and blocking for a definitive answer on fixed-priority systems.

References and further reading

Primary papers, official documentation and standards. Each claim above that is specific to a tool or version points here.

What’s next

Mark this lesson

Saved in this browser and synced to your account when you are signed in.

Next lesson

M7-T5: ROS 2 execution and scheduling

Describe ROS 2 executors, callback groups and QoS, and explain how they cause latency and starvation.