第2章 PX4固件体系结构
PX4固件是一套完整的无人机飞行控制软件栈,运行在NuttX实时操作系统之上。理解其内部架构是进行二次开发、算法移植和故障排查的基础。本章将从操作系统层、软件分层架构、源码组织和板级支持四个层面,深入剖析PX4固件的体系结构。
2.1 NuttX实时操作系统基础
PX4选择NuttX作为底层实时操作系统(RTOS),这是理解PX4运行机制的前提。NuttX是一个开源的嵌入式实时操作系统,遵循POSIX标准,具有体积小、实时性强、可裁剪的特点。
2.1.1 NuttX概览与特性
NuttX由Gregory Nutt于2007年创建,目前由Apache基金会维护。其核心特性包括:
• POSIX兼容:支持标准的POSIX API,便于移植和开发
• 可配置的实时调度:支持多级优先级、抢占式调度、时间片轮转
• 微内核架构:只保留最小必要的内核功能,其余以模块形式提供
• 虚拟文件系统(VFS):统一的文件、设备、网络接口
• 网络协议栈:支持TCP/IP、UDP、Socket等标准网络接口
表2-1 NuttX与其他嵌入式RTOS对比
| 特性 | NuttX | FreeRTOS | Zephyr | ChibiOS |
|---|---|---|---|---|
| POSIX兼容 | 完整支持 | 不支持 | 部分支持 | 部分支持 |
| 调度策略 | 优先级抢占+RR | 优先级抢占 | 优先级抢占+RR | 优先级抢占+RR |
| 文件系统 | VFS+NuttFS/FAT | 无内置 | VFS+多后端 | HAL抽象 |
| 网络栈 | 内置TCP/IP | 需第三方 | 内置多协议 | 内置多协议 |
| 硬件支持 | ARM/RISC-V/x86 | ARM/多平台 | ARM/RISC-V/x86 | ARM为主 |
| 主要用户 | PX4 | ArduPilot/通用 | Zephyr生态 | ArduPilot |
2.1.2 NuttX任务调度机制
理解NuttX的任务调度机制对于理解PX4固件的实时性至关重要。NuttX采用基于优先级的抢占式调度算法,支持时间片轮转(Round-Robin)。
**任务优先级:**NuttX支持256个优先级等级(0-255),数字越小优先级越高。在PX4中,典型的优先级分配如下:
表2-2 PX4任务优先级分配
| 优先级范围 | 任务类型 | 典型模块 | 调度特点 |
|---|---|---|---|
| 0-49 | 系统内核任务 | Idle、中断处理 | 最高优先级,不可抢占 |
| 50-99 | 实时控制任务 | 姿态控制、电机输出 | 确定性执行,严格实时 |
| 100-179 | 导航与估计任务 | EKF2、Navigator、Commander | 准实时,允许较低频率 |
| 180-223 | 通信任务 | MAVLink、uORB传输 | 较低优先级,容忍延迟 |
| 224-255 | 背景任务 | 日志记录、参数保存 | 最低优先级,空闲时执行 |
**时间片轮转:**当多个任务具有相同优先级时,NuttX使用时间片轮转调度。默认时间片为20ms,可在配置中调整。这意味着同优先级的任务会轮流获得CPU时间,避免某个任务长时间占用处理器。
**中断处理:**NuttX的中断响应延迟可控制在微秒级别。飞控关键的中断源(如IMU数据就绪中断、定时器中断)被分配最高优先级,确保实时响应。
2.1.3 NuttX在PX4中的配置
PX4对NuttX进行了定制配置,主要通过板级配置文件进行。以Pixhawk 4(STM32F765)为例,其NuttX配置位于:
# 板级NuttX配置目录
boards/px4/fmu-v5/nuttx-config/
├── nsh/
│ └── rcS # NSH启动脚本
├── include/
│ └── board.h # 板级头文件
├── Kconfig # 内核功能选择
└── scripts/
└── Make.defs # 编译选项
关键配置参数包括:
# Kconfig 片段:PX4的NuttX内核配置
CONFIG_SCHED_RR_TICK=20000 # 时间片 20ms
CONFIG_TASK_NAME_SIZE=24 # 任务名称最大长度
CONFIG_MAX_TASKS=64 # 最大任务数
CONFIG_MM_REGIONS=2 # 内存区域数
CONFIG_START_YEAR=2020 # 系统时钟起始年
CONFIG_USEC_PER_TICK=1000 # 每 Tick 的微秒数
CONFIG_NFILE_DESCRIPTORS=64 # 文件描述符数量
CONFIG_DEV_SERIAL_CONSOLE=y # 串口控制台
PX4在NuttX基础上增加了自己的抽象层(Platform Layer),将NuttX的原生API封装为更高层的接口,使得PX4的业务逻辑不直接依赖NuttX API,从而支持未来可能的操作系统迁移。
2.1.4 NuttX Shell(NSH)
NuttX提供了一个内置的命令行Shell——NSH(NuttShell)。在PX4中,NSH是调试和诊断的重要工具。可以通过USB串口或MAVLink Shell访问。
常用NSH命令:
表2-3 PX4常用NSH调试命令
| 命令 | 功能 | 示例 |
|---|---|---|
| top | 查看任务运行状态和CPU占用 | top |
| listener | 监听uORB主题数据 | listener sensor_combined |
| uorb top | 查看uORB主题发布频率 | uorb top |
| perf | 查看性能计数器 | perf |
| param show | 查看参数值 | param show MC_ROLLRATE_P |
| ver all | 查看固件版本信息 | ver all |
| dmesg | 查看系统启动日志 | dmesg |
| ps | 查看进程列表 | ps |
| dumpfile | 导出文件内容 | dumpfile /fs/microsd/log.ulg |
以下是一个NSH调试的典型会话示例:
# 通过USB串口连接后,查看IMU原始数据
nsh> listener sensor_accel
TOPIC: sensor_accel 0
sensor_accel
timestamp: 123456789 (0.005s ago)
topic_instance: 0
device_id: 393226 (0x0006000A)
x: 0.0153 y: -0.0012 z: -9.7892
temperature: 38.5000
errors: 0
# 查看当前所有运行任务及其CPU占用
nsh> top
PID PRI POLY SCHD TYPE NPX STATE NAME CPU(%) STACK
0 0 FIFO 0 TCB 0 Running Idle 23.5 2048
10 180 FIFO 0 TCB 0 Waiting init 0.0 2048
20 250 FIFO 0 TCB 0 Ready hp_default 5.2 4096
25 246 FIFO 0 TCB 0 Waiting rate_ctrl 15.3 2048
30 245 FIFO 0 TCB 0 Waiting att_ctrl 3.1 2048
2.2 PX4软件分层架构
PX4固件采用经典的分层架构设计,从底层硬件到上层应用,共分为五个层次。这种设计使得各层职责清晰、接口明确,便于独立开发和测试。
2.2.1 五层架构概览
从下到上,PX4的软件架构可以分为以下五层:
表2-4 PX4软件分层架构
| 层次 | 名称 | 职责 | 典型组件 |
|---|---|---|---|
| 第5层 | 应用层 | 飞行任务管理、用户交互 | Commander、Navigator、Mavlink |
| 第4层 | 控制层 | 飞行控制算法 | 姿态控制、位置控制、速率控制 |
| 第3层 | 估计层 | 状态估计与融合 | EKF2、姿态估计器、空速估计 |
| 第2层 | 驱动层 | 硬件设备抽象 | IMU驱动、GPS驱动、PWM输出 |
| 第1层 | 平台层 | 操作系统与硬件抽象 | NuttX、HAL、uORB总线 |
2.2.2 uORB消息总线
uORB(micro Object Request Broker)是PX4固件架构的核心组件,它实现了模块间的解耦通信。所有模块通过uORB主题(Topic)交换数据,而不是直接调用彼此的函数。这种设计模式类似于ROS的话题(Topic)机制,也为后续与ROS2集成提供了天然的桥接基础。
发布**-****订阅模型:**uORB采用经典的发布-订阅(Publish-Subscribe)模型。一个模块可以发布(publish)数据到某个主题,其他模块可以订阅(subscribe)该主题来获取数据。发布者和订阅者之间完全解耦,不需要知道对方的存在。
以下是uORB消息定义的示例。每个uORB主题由一个.msg文件定义,编译时自动生成C/C++结构体和注册代码:
# msg/sensor_combined.msg
# 传感器组合数据 - 融合后的IMU数据
uint64 timestamp # 时间戳(微秒)
float32[3] gyro_rad # 陀螺仪数据(rad/s)
float32 gyro_integral_dt # 陀螺仪积分时间
int32 accelerometer_timestamp_relative # 加速度计相对时间戳
float32[3] accelerometer_m_s2 # 加速度计数据(m/s²)
float32 accelerometer_integral_dt # 加速度计积分时间
uint8 CLIPPING_X = 1
uint8 CLIPPING_Y = 2
uint8 CLIPPING_Z = 4
uint8 accelerometer_clipping # 加速度计剪切标志
uint8 gyro_clipping # 陀螺仪剪切标志
以下是在PX4模块中发布和订阅uORB数据的典型代码:
// 发布示例:在传感器驱动中发布sensor_combined数据
#include <uORB/Publication.hpp>
#include <uORB/topics/sensor_combined.h>
class IMUDriver : public ModuleBase
{
private:
uORB::Publication<sensor_combined_s> _sensor_pub{ORB_ID(sensor_combined)};
void publishData()
{
sensor_combined_s data{};
data.timestamp = hrt_absolute_time(); // 获取当前时间戳
// 填充陀螺仪数据
data.gyro_rad[0] = _gyro_x;
data.gyro_rad[1] = _gyro_y;
data.gyro_rad[2] = _gyro_z;
// 填充加速度计数据
data.accelerometer_m_s2[0] = _accel_x;
data.accelerometer_m_s2[1] = _accel_y;
data.accelerometer_m_s2[2] = _accel_z;
_sensor_pub.publish(data); // 发布到uORB总线
}
};
// 订阅示例:在控制模块中订阅sensor_combined数据
#include <uORB/Subscription.hpp>
#include <uORB/topics/sensor_combined.h>
class AttitudeController : public ModuleBase
{
private:
uORB::Subscription _sensor_sub{ORB_ID(sensor_combined)};
void run()
{
sensor_combined_s sensor_data;
// 检查是否有新数据
if (_sensor_sub.update(&sensor_data)) {
// 使用陀螺仪数据进行姿态控制
float gyro_x = sensor_data.gyro_rad[0];
float gyro_y = sensor_data.gyro_rad[1];
float gyro_z = sensor_data.gyro_rad[2];
// 使用加速度计数据进行姿态补偿
float accel_x = sensor_data.accelerometer_m_s2[0];
float accel_y = sensor_data.accelerometer_m_s2[1];
float accel_z = sensor_data.accelerometer_m_s2[2];
// … 控制算法实现 …
}
}
};
2.2.3 核心uORB主题概览
PX4定义了数百个uORB主题,覆盖了从传感器数据到控制指令的所有数据流。以下是最重要的核心主题:
表2-5 PX4核心uORB主题
| 主题名称 | 数据内容 | 发布者 | 订阅者 |
|---|---|---|---|
| sensor_combined | 融合后的IMU数据 | 传感器驱动 | EKF2、控制器 |
| sensor_gps | GPS定位数据 | GPS驱动 | EKF2、Navigator |
| vehicle_attitude | 飞行器姿态(四元数) | EKF2 | 控制器、MAVLink |
| vehicle_local_position | 本地坐标系位置 | EKF2 | 位置控制、Navigator |
| vehicle_global_position | 全球坐标系位置 | EKF2 | Navigator、MAVLink |
| vehicle_status | 飞行状态机 | Commander | 几乎所有模块 |
| vehicle_command | 飞行指令 | MAVLink、ROS2 | Commander、Navigator |
| actuator_outputs | 执行器输出 | 混控器 | PWM驱动 |
| vehicle_control_mode | 控制模式标志 | Commander | 所有控制器 |
| battery_status | 电池状态 | 电池驱动 | Commander、MAVLink |
2.2.4 模块化设计原则
PX4的每个功能模块都是一个独立的线程(Task),通过uORB进行数据交换。这种设计带来了以下优势:
• 解耦:模块间没有直接的函数调用依赖,便于独立测试和替换
• 可扩展:新增模块只需注册新的uORB主题,不影响现有代码
• 实时性:每个模块可以设置独立的优先级和栈大小
• 可调试性:每个模块可以独立启动、停止和调试
每个模块通常继承ModuleBase模板类,这提供了统一的生命周期管理接口:
// PX4模块标准框架
#include <px4_platform_common/module.h>
#include <px4_platform_common/posix.h>
class MyModule : public ModuleBase
{
public:
MyModule();
~MyModule() override;
// ModuleBase接口方法
static int task_spawn(int argc, char *argv[]); // 创建任务
static int custom_command(int argc, char *argv[]); // 自定义命令
static int print_usage(const char *reason = nullptr); // 打印用法
// 主循环
void run() override;
private:
uORB::Subscription _sub{ORB_ID(vehicle_status)};
uORB::Publication<my_output_s> _pub{ORB_ID(my_output)};
bool _should_exit{false};
};
void MyModule::run()
{
// 主循环,直到收到退出信号
while (!_should_exit) {
my_output_s output{};
output.timestamp = hrt_absolute_time();
// 业务逻辑…
_pub.publish(output);
px4_usleep(10000); // 睡眠10ms,即以100Hz运行
}
}
2.2.5 数据流示例:姿态控制链路
为了更直观地理解PX4的uORB数据流,我们以多旋翼姿态控制为例,追踪从传感器到电机输出的完整数据流:
• 1. IMU驱动读取原始数据,发布到 sensor_combined 主题
• 2. EKF2模块订阅 sensor_combined,结合GPS等数据进行状态估计,发布 vehicle_attitude(四元数姿态)
• 3. 姿态控制器(mc_att_control)订阅 vehicle_attitude 和 manual_control_input,计算力矩指令,发布 vehicle_torque_setpoint
• 4. 混控器(control_allocator)订阅力矩指令,根据电机配置计算各电机输出,发布 actuator_motors
• 5. PWM驱动订阅 actuator_motors,输出PWM信号控制电调
整个数据流从传感器到电机输出的总延迟通常在1-2ms以内,这得益于uORB的高效实现和NuttX的实时调度。
2.3 源码目录结构与编译系统
PX4的源码采用清晰的目录组织,基于CMake构建系统。熟悉这套结构是进行源码级开发的基础。
2.3.1 顶层目录结构
PX4-Autopilot/
├── boards/ # 板级配置(每个硬件平台一个子目录)
│ ├── px4/ # Pixhawk系列板卡
│ │ ├── fmu-v5/ # Pixhawk 4(STM32F765)
│ │ ├── fmu-v6x/ # Pixhawk 6X(STM32H753)
│ │ └── …
│ └── sitl/ # 软件在环仿真板级配置
├── msg/ # uORB消息定义(.msg文件)
├── src/ # 源码主目录
│ ├── drivers/ # 硬件驱动
│ ├── lib/ # 公共库(算法、数学库)
│ ├── modules/ # 核心功能模块
│ ├── platforms/ # 平台适配层
│ └── systemcmds/ # 系统命令
├── ROMFS/ # 只读文件系统(启动脚本、混控配置)
├── Tools/ # 开发工具和脚本
├── test/ # 测试代码
└── CMakeLists.txt # 顶层CMake配置
2.3.2 src/modules目录详解
src/modules/是PX4固件的核心,包含了所有重要的飞行控制模块:
表2-6 PX4核心模块概览
| 模块名称 | 功能描述 | 关键输入 | 关键输出 |
|---|---|---|---|
| ekf2 | 扩展卡尔曼滤波器 | sensor_combined, sensor_gps | vehicle_attitude, vehicle_local_position |
| commander | 飞行状态机管理 | vehicle_command, battery_status | vehicle_status, vehicle_control_mode |
| navigator | 自主导航任务处理 | vehicle_global_position, mission | position_setpoint_triplet |
| mc_att_control | 多旋翼姿态控制 | vehicle_attitude, manual_control_input | vehicle_torque_setpoint |
| mc_pos_control | 多旋翼位置控制 | vehicle_local_position, position_setpoint_triplet | vehicle_thrust_setpoint |
| mc_rate_control | 多旋翼角速率控制 | vehicle_angular_velocity | vehicle_torque_setpoint |
| fw_att_control | 固定翼姿态控制 | vehicle_attitude | actuator_controls |
| control_allocator | 执行器分配(混控) | vehicle_torque_setpoint | actuator_motors, actuator_servos |
| mavlink | MAVLink协议处理 | 多个uORB主题 | 串口/UDP输出 |
| logger | 飞行日志记录 | 几乎所有uORB主题 | ULog文件 |
2.3.3 CMake构建系统
PX4使用CMake作为构建系统,配合Ninja实现快速编译。理解构建系统有助于添加新模块、修改编译配置和调试编译问题。
**构建命令格式:**make []
表2-7 PX4常用构建命令
| 命令 | 说明 | 输出 |
|---|---|---|
| make px4_fmu-v5_default | 编译Pixhawk 4固件 | .px4固件文件 |
| make px4_fmu-v6x_default | 编译Pixhawk 6X固件 | .px4固件文件 |
| make px4_sitl_default | 编译SITL仿真版本 | 可执行文件 |
| make px4_sitl gazebo-classic | 编译SITL并启动Gazebo | 仿真环境 |
| make px4_fmu-v5_default upload | 编译并上传到飞控 | 硬件上运行 |
| make clean | 清理构建产物 | — |
| make tests | 运行单元测试 | 测试报告 |
2.3.4 添加自定义模块
开发自定义模块是PX4二次开发的常见需求。以下是添加一个自定义模块的完整步骤:
**Step 1: **创建模块目录和源文件
# 创建模块目录
mkdir -p src/modules/my_controller
cd src/modules/my_controller
**Step 2: **编写模块代码(MyController.hpp)
#pragma once
#include <px4_platform_common/module.h>
#include <px4_platform_common/module_params.h>
#include <uORB/Subscription.hpp>
#include <uORB/Publication.hpp>
#include <uORB/topics/vehicle_attitude.h>
#include <uORB/topics/vehicle_torque_setpoint.h>
class MyController : public ModuleBase, public ModuleParams
{
public:
MyController();
~MyController() override = default;
static int task_spawn(int argc, char *argv[]);
static int custom_command(int argc, char *argv[]);
static int print_usage(const char *reason = nullptr);
void run() override;
// 参数定义(自动绑定到PX4参数系统)
DEFINE_PARAMETERS(
(ParamFloatpx4::params::MY_GAIN_P) _param_my_gain_p,
(ParamFloatpx4::params::MY_GAIN_I) _param_my_gain_i,
(ParamFloatpx4::params::MY_GAIN_D) _param_my_gain_d
)
private:
uORB::Subscription _att_sub{ORB_ID(vehicle_attitude)};
uORB::Publication<vehicle_torque_setpoint_s> _torque_pub{ORB_ID(vehicle_torque_setpoint)};
};
**Step 3: **编写CMakeLists.txt(模块构建配置)
# src/modules/my_controller/CMakeLists.txt
px4_add_module(
MODULE modules__my_controller # 模块唯一标识
MAIN my_controller # 命令行名称
STACK_MAIN 4096 # 主栈大小
STACK_MAX 2048 # 子线程栈大小
COMPILE_FLAGS
-Os # 优化大小
SRCS
MyController.cpp # 源文件
DEPENDS
px4_workqueue # 依赖库
)
提示:
添加新模块后,还需要在目标板级的default.cmake文件中启用该模块:drivers/my_controller CONFIG_MODULES_MY_CONTROLLER YES
2.4 板级支持包(BSP)与硬件抽象层
PX4通过板级支持包(Board Support Package,BSP)和硬件抽象层(Hardware Abstraction Layer,HAL)实现对不同硬件平台的支持。这种设计使得同一套飞控代码可以运行在不同的硬件上,也可以以SITL方式运行在普通计算机上。
2.4.1 BSP目录结构
每个硬件平台都有对应的BSP目录,以Pixhawk 4(fmu-v5)为例:
boards/px4/fmu-v5/
├── default.px4board # 默认构建配置(启用哪些模块)
├── bootloader.px4board # Bootloader构建配置
├── nuttx-config/ # NuttX内核配置
│ ├── include/
│ │ └── board.h # 板级头文件(引脚定义、时钟配置)
│ └── Kconfig # 内核配置选项
├── src/
│ ├── board_config.h # 板级硬件配置头文件
│ ├── board_identity.c # 板级身份识别
│ ├── init.c # 板级初始化
│ ├── led.c # LED控制
│ ├── spi.c # SPI总线配置
│ └── timer_config.c # 定时器配置(PWM输出)
└── CMakeLists.txt # 板级构建配置
2.4.2 硬件抽象层(HAL)
PX4的硬件抽象层位于src/platforms/目录,它封装了NuttX的原生API,为上层模块提供统一的接口。主要包括:
• px4_platform_common:提供模块基类、日志、参数系统、锁等基础设施
• px4_workqueue:工作队列抽象,支持任务调度和定时触发
• px4_log:统一日志接口,支持多级别日志输出
• hrt(High Resolution Timer):高精度时间戳接口,精度为微秒级
以下是PX4 HAL中常用的基础接口示例:
// 高精度时间戳
#include <drivers/drv_hrt.h>
hrt_abstime now = hrt_absolute_time(); // 获取当前时间戳(微秒)
hrt_abstime elapsed = hrt_elapsed_time(&start_time); // 计算经过时间
// 日志输出
#include <px4_platform_common/log.h>
PX4_INFO(“Module started successfully”); // 信息级别
PX4_WARN(“Sensor data timeout!”); // 警告级别
PX4_ERR(“Failed to initialize driver: %d”, ret); // 错误级别
PX4_DEBUG(“Debug value: %f”, value); // 调试级别(可编译时禁用)
// 参数系统
#include <px4_platform_common/module_params.h>
// 在类中声明参数
DEFINE_PARAMETERS(
(ParamFloatpx4::params::MC_ROLLRATE_P) _param_mc_rollrate_p,
(ParamIntpx4::params::MPC_XY_VEL_MAX) _param_mpc_xy_vel_max
)
// 访问参数值
float kp = _param_mc_rollrate_p.get();
int max_vel = _param_mpc_xy_vel_max.get();
2.4.3 设备驱动框架
PX4的设备驱动位于src/drivers/目录,按传感器类型组织。每个驱动通常继承自I2CSPI驱动基类,以简化硬件访问:
// 典型的I2C/SPI传感器驱动框架
#include <drivers/device/spi.h>
#include <lib/drivers/accelerometer/PX4Accelerometer.hpp>
#include <lib/drivers/gyroscope/PX4Gyroscope.hpp>
class ICM42688P : public device::SPI, public I2CSPIDriver
{
public:
ICM42688P(const I2CSPIDriverConfig &config);
~ICM42688P() override;
static I2CSPIDriverBase *instantiate(const I2CSPIDriverConfig &config, int runtime_instance);
static void print_usage();
void RunImpl(); // 周期性调用的主函数
private:
int init() override; // 初始化传感器
int probe() override; // 探测设备是否存在
PX4Accelerometer _px4_accel; // 加速度计数据处理器
PX4Gyroscope _px4_gyro; // 陀螺仪数据处理器
// 寄存器访问
uint8_t RegisterRead(Register reg);
void RegisterWrite(Register reg, uint8_t value);
};
2.4.4 启动脚本与系统初始化
PX4的启动过程由ROMFS中的启动脚本控制。启动脚本使用NSH语法,定义了系统启动时加载哪些模块及其参数:
# ROMFS/px4fmu_common/init.d-posix/rcS
# SITL启动脚本示例
# 加载板级配置
set VEHICLE_TYPE mc # 设置载体类型为多旋翼
set MIXER quad_x # 使用X型四旋翼混控
# 启动核心模块
dataman start # 数据管理器
param load # 加载参数
commander start # 飞行状态机
navigator start # 导航模块
ekf2 start # 状态估计
mc_att_control start # 多旋翼姿态控制
mc_pos_control start # 多旋翼位置控制
mc_rate_control start # 多旋翼角速率控制
control_allocator start # 执行器分配
# 启动通信模块
mavlink start -x -u 14556 -r 4000000 # MAVLink UDP
mavlink boot_complete # 通知启动完成
2.4.5 SITL与真实硬件的差异
理解SITL与真实硬件的差异对于开发者非常重要。两者在架构层面的主要区别如下:
表2-8 SITL与真实硬件对比
| 维度 | 真实硬件(Pixhawk) | SITL****仿真 |
|---|---|---|
| 操作系统 | NuttX RTOS | Linux/macOS 原生进程 |
| 传感器数据 | 真实硬件驱动读取 | 仿真器模拟生成 |
| PWM输出 | 硬件PWM信号 | 虚拟执行器接口 |
| 通信接口 | 串口/CAN/I2C/SPI | UDP/TCP网络 |
| 时间基准 | 硬件定时器 | 系统时钟 |
| 文件系统 | SD卡(FAT32) | 主机文件系统 |
| 实时性 | 确定性保证 | 非确定性(受主机负载影响) |
尽管SITL在实时性方面不如真实硬件,但它的代码路径与真实硬件相同——所有的控制算法、uORB消息流、参数系统都是同一套代码。因此,在SITL中验证的算法可以直接移植到真实硬件上,只需调整参数即可。
2.5 本章小结
本章深入剖析了PX4固件的体系结构。我们了解了NuttX RTOS的实时调度机制、NSH调试命令,PX4的五层软件架构和uORB消息总线的发布-订阅模型,以及SITL与真实硬件的架构差异。这些知识是后续学习传感器驱动、控制算法和导航逻辑的基础。从下一章开始,我们将进入具体的功能模块,首先从地面站和参数配置开始。
openEuler 是由开放原子开源基金会孵化的全场景开源操作系统项目,面向数字基础设施四大核心场景(服务器、云计算、边缘计算、嵌入式),全面支持 ARM、x86、RISC-V、loongArch、PowerPC、SW-64 等多样性计算架构
更多推荐


所有评论(0)