第六章:PX4 的任务模型与调度思路
PX4飞控系统采用NuttX RTOS作为底层平台,构建了混合任务调度模型。系统核心模块主要通过WorkQueue工作队列机制运行,多个模块共享线程执行,实现高效资源利用;少量需要独立执行的模块仍采用Task模式。调度设计遵循三大原则:控制任务优先级最高、数据驱动执行、避免WorkQueue阻塞。这种架构既保证了IMU数据采集(400Hz-1kHz)和控制算法执行的实时性,又兼顾了MCU资源限制。
PX4 的任务模型与调度思路——任务、线程与 WorkQueue 在飞控系统中的角色
在前面的章节中,我们已经介绍了:
-
PX4 系统启动流程
-
rcS启动脚本 -
各个模块如何被启动
但一个核心问题仍然没有回答:
这些模块是如何被调度运行的?
无人机飞控系统属于 实时控制系统,需要保证:
-
IMU 数据高频稳定采集(400Hz–1kHz)
-
姿态控制算法周期稳定执行
-
飞行状态机实时响应
因此 PX4 必须具备一套高效且可控的 任务调度模型
本章将从工程角度介绍:
-
PX4 运行的操作系统基础
-
Task(独立任务)模型
-
WorkQueue 工作队列机制
-
优先级与实时性设计
-
当前 PX4 版本的调度架构
同时回答一个很多开发者关心的问题:
现代 PX4 还有 Task 吗?
答案是:
有,但大多数控制模块已经迁移到 WorkQueue
一、PX4 运行在什么系统之上
PX4 在硬件飞控(Pixhawk 系列)上通常运行在
NuttX RTOS 之上
NuttX 是一个 POSIX 风格的实时操作系统,其调度核心包括:
-
任务(Task)
-
线程(pthread)
-
优先级调度
-
实时策略(FIFO / Round Robin)
在 NuttX 中,调度单元基于 TCB(Task Control Block)
无论是:
-
task_create() -
pthread_create()
最终都由同一调度器管理
因此在 PX4 工程实践中:
Task 可以理解为一个独立执行单元,由 NuttX 调度器管理
二、PX4 模块(Module)的执行方式
PX4 的核心功能以 模块(Module) 的形式存在
源码路径:
src/modules/
例如常见模块:
commander
navigator
sensors
mc_att_control
ekf2
land_detector
logger
这些模块通常提供 CLI 命令:
module start
module stop
module status
例如:
commander start
模块启动后会进入自己的运行循环
例如典型结构:
while (!should_exit()) {
Run();
}
但问题是:
这些模块究竟是如何运行的?
PX4 提供两种执行方式:
-
独立 Task(任务)
-
WorkQueue 工作队列
三、PX4 的 Task(独立任务)
在 PX4 早期版本中,大量模块运行在 独立 Task 中
Task 的特点:
-
每个模块运行在 独立执行单元
-
具有 独立栈空间
-
可以设置 独立优先级
任务通常通过以下接口创建:
px4_task_spawn_cmd()
示例代码:
px4_task_spawn_cmd(
"commander",
SCHED_DEFAULT,
SCHED_PRIORITY_DEFAULT,
4096,
(px4_main_t)&run_trampoline,
argv);
1、Task 的底层实现
px4_task_spawn_cmd() 是 PX4 对任务创建接口的封装
源码路径:
platforms/common/px4_platform_common/tasks.cpp
在 NuttX 平台上,该函数最终调用:
task_create()
或
kthread_create()
也就是说:
PX4 创建的是 NuttX 的任务(task)
虽然接口风格参考 POSIX,但底层并不是 pthread_create()
2、Task 的优点
独立优先级
例如不同模块可以设置不同优先级:
EKF2
commander
navigator
logger
关键控制模块可以优先执行
任务之间互不阻塞
独立任务可以进行:
-
poll() -
sleep() -
阻塞 IO
不会影响其他模块运行
3、Task 的缺点
Task 模型也存在明显问题:
RAM 消耗较大
每个任务需要独立栈空间:
4KB
8KB
甚至更大
对于 MCU(如 STM32)来说,RAM 是非常宝贵的资源
上下文切换开销
多个任务运行时,RTOS 会产生:
-
context switch
-
cache miss
-
调度延迟
对于高频控制任务来说不理想
四、WorkQueue 工作队列模型
为了减少资源消耗,PX4 引入了 WorkQueue 调度机制
WorkQueue 的核心思想是:
多个模块共享一个线程运行
结构示意:
WorkQueue Thread
├── Module A
├── Module B
└── Module C
也就是说:
-
模块不再各自拥有线程
-
而是作为 WorkItem 被调度执行
1、WorkQueue 基类
PX4 提供一个核心基类:
ScheduledWorkItem
源码路径:
platforms/common/include/px4_platform_common/px4_work_queue/
主要文件:
ScheduledWorkItem.hpp
WorkItem.hpp
WorkQueue.hpp
模块只需继承该类:
class McAttControl :
public ModuleBase<McAttControl>,
public px4::ScheduledWorkItem
2、WorkQueue 调度示例
典型初始化方式:
McAttControl::McAttControl() :
ScheduledWorkItem(MODULE_NAME,
px4::wq_configurations::rate_ctrl)
{
ScheduleOnInterval(4000);
}
这里表示:
每 4000us 执行一次
即:
250Hz 控制循环
五、WorkQueue 的优先级设计
WorkQueue 不是统一优先级
PX4 定义了多个工作队列,每个队列拥有:
-
独立线程
-
独立优先级
例如:
rate_ctrl
hp_default
lp_default
典型用途:
| WorkQueue | 用途 |
|---|---|
| rate_ctrl | 控制回路 |
| hp_default | 高频任务 |
| lp_default | 低优先级任务 |
同一 WorkQueue 中的模块:
-
共享线程
-
共享栈
-
共享优先级
不同 WorkQueue 之间则具有不同优先级
六、WorkQueue 的触发方式
WorkQueue 任务通常由三种方式触发
1 定时调度
最简单方式:
ScheduleOnInterval()
例如:
400Hz
250Hz
100Hz
常见于控制算法
2 uORB 数据触发
现代 PX4 更常用的方式是:
uORB 回调机制
例如:
uORB::SubscriptionCallbackWorkItem _sensor_sub{
this,
ORB_ID(sensor_combined)
};
初始化:
_sensor_sub.registerCallback();
执行流程:
IMU driver publish
↓
uORB notify
↓
callback
↓
WorkQueue 调度 Run()
这样可以保证:
控制算法紧跟传感器更新频率执行
3 延迟执行
例如:
ScheduleDelayed()
适用于:
-
参数更新
-
状态检测
-
周期检查任务
七、当前 PX4 的 Task 与 WorkQueue 分布
现代 PX4(1.14 / 1.15)采用:
Task + WorkQueue 混合模型
大多数控制模块运行在 WorkQueue
而少数模块仍然使用独立 Task
1、WorkQueue 模块(多数)
例如:
sensors
mc_att_control
mc_rate_control
fw_att_control
land_detector
ekf2
这些模块具有:
-
高频运行
-
不允许阻塞
-
周期明确
因此适合 WorkQueue
2、独立 Task 模块(少数)
例如:
commander
navigator
mavlink
logger
micrortps
这些模块可能会:
-
进行 IO
-
阻塞等待
-
执行复杂状态机
因此需要独立任务
八、PX4 调度设计的核心思想
PX4 的调度架构遵循三个原则
1 控制任务优先级最高
例如:
IMU
Rate Control
Attitude Control
运行频率通常:
250Hz – 1000Hz
必须保证实时执行
2 数据驱动执行
PX4 的很多任务不是简单周期运行,而是:
数据驱动
例如:
IMU → attitude control
IMU 更新后立即触发控制算法
3 WorkQueue 任务避免阻塞
在 WorkQueue 中禁止:
sleep()
poll()
阻塞 IO
否则会阻塞整个队列
九、如何查看 PX4 运行中的任务
PX4 提供了一些非常有用的调试命令
查看系统任务:
top
可以看到:
-
PID
-
CPU 使用率
-
优先级
-
栈使用情况
查看工作队列:
work_queue status
查看模块状态:
mc_att_control status
监听 uORB 数据:
listener sensor_combined
这些命令在调试飞控系统时非常有用
十、总结
PX4 的调度架构经历了明显演进
早期 PX4:
大量使用 Task
现代 PX4:
WorkQueue 为主
Task 为辅
整体执行结构可以理解为:
Module
↓
WorkItem / Task
↓
Thread
↓
NuttX Scheduler
其中:
-
Task:独立任务
-
WorkQueue:共享线程任务
这种设计既保证了:
-
实时控制性能
又兼顾:
-
MCU 资源限制
是飞控系统工程设计中的一种经典调度架构
openvela 操作系统专为 AIoT 领域量身定制,以轻量化、标准兼容、安全性和高度可扩展性为核心特点。openvela 以其卓越的技术优势,已成为众多物联网设备和 AI 硬件的技术首选,涵盖了智能手表、运动手环、智能音箱、耳机、智能家居设备以及机器人等多个领域。
更多推荐


所有评论(0)