UAV Systems Engineering · Module 6
M6-T4: PX4 modules and communication
uORB is the nervous system of PX4. Learn to read it and you can see what every module believes.
Every signal in PX4 is a uORB topic: sensor data, estimates, setpoints, status flags, actuator outputs. Understanding publish/subscribe semantics (latest value, queues, update rates) explains a surprising number of subtle bugs, such as missed events and stale data.
Learning objectives
After this lesson, you should be able to:
- Explain publish/subscribe semantics in uORB, including the latest-value model and queued topics.
- Read a topic definition (.msg file) and map it to ROS 2 messages.
- Use listener, uorb top and the logger to inspect a running vehicle.
- Identify topics that carry events, and why their queue depth matters.
Conceptual explanation
Implementation-specific uORB semantics are described in the PX4 documentation. Topic names, fields and queue depths vary between releases; the message definitions live in the msg/ directory of the PX4 repository for your version.
uORB (micro Object Request Broker) is PX4’s internal publish/subscribe middleware. A topic has a typed definition (a .msg file), any number of publishers (usually one) and any number of subscribers. Key semantics:
- Latest value: by default a subscriber reads the most recent message; if the publisher wrote twice between reads, the first is overwritten and lost.
- Independent subscribers: each tracks its own “last seen” position and can check for updates or block until one arrives.
- Queues: topics that carry events (for example commands) are declared with a queue depth greater than one so that bursts are not lost.
- Timestamps: every message carries a microsecond timestamp in the vehicle’s time base; some also carry a sample timestamp for the underlying measurement.
Modules are started by the startup scripts (the airframe configuration and rc scripts), run as tasks or work-queue items, and can be inspected with the console (module status for most modules, top for task load).

Engineering intuition
uORB is a bulletin board, not a mailbox. A bulletin board shows the latest notice; people reading it twice see the same notice. If two notices are pinned between visits, the earlier is gone. That is perfect for states (the current position) and dangerous for events (a command to disarm). Events therefore use a queue.
The corollary for companion-computer integration: the ROS 2 side sees topics through the DDS bridge, which applies its own QoS. A “reliable, keep-last-1” subscription has the bulletin-board semantics too; ask whether each topic you use is a state or an event.
Mathematical formulation
For a topic published at rate and a subscriber that samples at (polling), the fraction of messages seen by a latest-value subscriber is , and for an uncorrelated sample time the data age at read time is uniformly distributed on :
With a queue of depth a burst of up to messages between reads is preserved. If events arrive as a Poisson process with rate and the subscriber reads every seconds, the probability of losing at least one event with is (more than one arrival in an interval) which for is about 9 %; with it falls below 0.02 %. This is a toy model of why events use queues; the real depths are set per topic in the definition.
- ,
- publish and sample rates (Hz).
- queue depth of the topic.
- event arrival rate (1/s).
Architecture and data flow
Within PX4: drivers and modules publish; the logger subscribes to a configured set of topics and writes the ULog; the MAVLink module subscribes to topics to build telemetry messages and publishes topics from received messages (for example commands); the uXRCE-DDS client subscribes to or publishes the topics listed in its configuration. The set of topics visible to ROS 2 is therefore a configuration, not automatic. See the uXRCE-DDS lesson for the mapping.
Real-world UAV applications
- Inspecting internal state during bench tests with listener and uorb top.
- Choosing the topics to log for an experiment.
- Writing a custom PX4 module that publishes diagnostics.
- Diagnosing missed commands and stale data between modules.
Implementation example
This runs as shown. A toy model of latest-value and queued topics, not PX4 code, that reproduces the loss probability from the maths section by simulation and shows the benefit of a queue.
import numpy as np
rng = np.random.default_rng(3)
def lost_fraction(lam, T, q, trials=200000):
# events arrive as a Poisson process; the subscriber reads every T seconds and sees at most q events per interval
n = rng.poisson(lam * T, trials)
lost = np.maximum(n - q, 0).sum(); return lost / max(n.sum(), 1)
def p_more_than_one(lam, T): return 1 - np.exp(-lam * T) * (1 + lam * T)
print(f"P(more than 1 event in an interval), lambda T = 0.5: {p_more_than_one(1.0, 0.5):.3f}")
for q in (1, 2, 4, 8): print(f"queue depth {q}: fraction of events lost {lost_fraction(1.0, 0.5, q):.5f}")
assert abs(p_more_than_one(1.0, 0.5) - 0.0902) < 1e-3
assert lost_fraction(1.0, 0.5, 1) > 10 * max(lost_fraction(1.0, 0.5, 4), 1e-6)On a real vehicle, the console commands are the tools:
uorb top -1 # one snapshot of topic rates
listener sensor_combined -n 3 # three messages
listener vehicle_status # a state topic
param show SDLOG_* # what the logger records and whenCommon engineering mistakes
Using a state topic as an event
An overwritten message is lost; use a queued topic for events.
Assuming a topic is published at a constant rate
Some topics publish on change only; check with uorb top.
Confusing timestamp and timestamp_sample
The latter is the measurement time; use it for fusion.
Logging too few topics
The cause of a failure is often in a topic nobody logged.
Logging everything at full rate on a slow card
Dropouts in the log; select profiles and check log health.
Failure modes
| Failure mode | How it shows up | Likely cause |
|---|---|---|
| Missed command | A one-time command never acted on | Overwritten in a queue-1 topic or not subscribed during the burst |
| Stale data used | Controller reacts to old state | Subscriber checks update flag incorrectly or publisher stopped |
| Log gaps | Holes in the flight log | Logging bandwidth exceeds card write rate |
| No data on the companion | ROS 2 topic empty | Topic not in the uXRCE-DDS configuration |
Debugging approach
- Use
uorb topto see whether a topic is publishing and at what rate. - Check
logger statusfor dropouts. - Look at the
.msgdefinition for queue depth and fields. - Compare timestamps between topics to find stale or delayed data.
Practical exercises
- List five topics in your PX4 version and classify each as state or event, from its definition.
- Compute the sampling age for a 100 Hz topic polled at 30 Hz.
- Decide which topics to log for a VIO integration test and justify each.
- In SITL, measure the rate of ten topics with
uorb topand tabulate them.
Interview questions
Write an answer in your own words, then reveal the model answer. Nothing is sent anywhere.
Question 1
What are the semantics of a uORB topic?
Model answer
Typed publish/subscribe with latest-value semantics by default: subscribers track their own position, and unread messages are overwritten unless the topic has a queue depth above one.
Question 2
Why do events need queued topics?
Model answer
With latest-value semantics a burst between reads overwrites earlier messages and events are silently lost; a queue preserves up to .
Question 3
How would you find out what the estimator publishes and how fast?
Model answer
Use uorb top for the rates, listener to view messages, and the .msg definition for fields; the logger records them for post-flight analysis.
References and further reading
Primary papers, official documentation and standards. Each claim above that is specific to a tool or version points here.