- 嵌入式
- 物联网
- 机器人
- 自动驾驶
- 智能硬件
【免费下载链接】PX4-Autopilot
PX4 Autopilot Software
导读
PositionSetpointTriplet(全局位置设定点三元组)是 PX4 自动驾驶仪中连接"任务决策层"(Navigator)与"姿态/位置控制层"(Flight Mode Manager、固定翼模式管理器等)的核心 uORB 消息。它以 WGS84 坐标承载"前一个、当前、下一个"三个航点设定点,为位置控制器提供路径前瞻与平滑过渡所需的上下文信息。本文基于 PositionSetpointTriplet 消息定义,结合 消息源码、依赖消息定义 以及 Navigator、FlightTaskAuto、FixedWingModeManager 等模块的实际实现,完整讲解该消息的字段结构、生产-消费链路与典型工作流程,读完你将能够理解 PX4 航点导航的数据流全貌,并掌握在 MAVLink 地面站数据中解读position_setpoint_triplet主题的方法。
消息概览:一个三元组,三段路径
PositionSetpointTriplet的设计意图非常直白——消息头注释即点明其用途:
Global position setpoint triplet in WGS84 coordinates. This are the three next waypoints (or just the next two or one).
即:全局位置设定点三元组,使用 WGS84 坐标系,描述接下来最多三个航点(任务末期可能只有两个甚至一个)。之所以用"三个"而非"一个",是因为仅凭单一设定点无法让控制器预判航段间的转弯衔接;给出previous、current、next三段上下文后,位置控制器才能在进入新航段之前就规划平滑的过渡轨迹。
该消息的 uORB 主题名为position_setpoint_triplet,字段结构如下(消息定义):
| 字段 | 类型 | 说明 |
|---|---|---|
timestamp | uint64 | 系统启动以来的时间,单位微秒(microseconds),由发布方在发布瞬间写入 |
previous | PositionSetpoint | 前一个位置设定点(已通过/正在离开的航点) |
current | PositionSetpoint | 当前位置设定点(正在前往的航点) |
next | PositionSetpoint | 下一个位置设定点(用于路径前瞻) |
三元组本身不含任何经纬度字段——所有空间信息都封装在嵌套的PositionSetpoint结构体中。因此,要真正读懂PositionSetpointTriplet,必须先掌握其依赖消息PositionSetpoint。
依赖消息:PositionSetpoint 的完整字段语义
PositionSetpointTriplet中三个成员的类型均为PositionSetpoint,该消息在 msg/PositionSetpoint.msg 中定义,其文件头注释特别说明"此文件仅作为 position_setpoint_triplet 三元组的依赖使用"(this file is only used in the position_setpoint triple as a dependency),进一步印证了两者是一体的数据契约。
设定点类型枚举(type)
type字段用于告诉位置控制器当前设定点属于哪种飞行动作,直接影响控制器行为:
| 值 | 名称 | 含义 |
|---|---|---|
| 0 | SETPOINT_TYPE_POSITION | 位置设定点,常规导航 |
| 1 | SETPOINT_TYPE_VELOCITY | 速度设定点 |
| 2 | SETPOINT_TYPE_LOITER | 盘旋(loiter)设定点 |
| 3 | SETPOINT_TYPE_TAKEOFF | 起飞设定点 |
| 4 | SETPOINT_TYPE_LAND | 降落设定点,高度必须被忽略,持续下降直至着陆 |
| 5 | SETPOINT_TYPE_IDLE | 怠速设定点,不执行动作,关闭电机或保持怠速(多旋翼) |
其中SETPOINT_TYPE_LAND的"高度必须忽略"约束非常关键:固定翼降落时控制器依据的是下滑道/着陆逻辑而非设定点高度,多旋翼则直接以当前位置为落点持续下降。从 FixedWingModeManager.cpp 的实现可以看到,当current.type为SETPOINT_TYPE_LAND时,固定翼模式管理器会据此切入降落逻辑分支。
盘旋(Loiter)相关字段
多旋翼与固定翼都支持盘旋动作,PositionSetpoint提供了一组完整的盘旋几何描述:
| 字段 | 类型/单位 | 说明 |
|---|---|---|
loiter_radius | float32[m],范围 [0, INF] | 盘旋长轴半径 |
loiter_minor_radius | float32[m],范围 [0, INF] | 盘旋短轴半径(用于非圆形盘旋形状,如"8"字) |
loiter_direction_counter_clockwise | bool | 盘旋方向,默认顺时针,置真则逆时针 |
loiter_orientation | float32[rad],范围 [-π, π] | 长轴相对真北的方位角 |
loiter_pattern | uint8 | 盘旋图案,LOITER_TYPE_ORBIT=0(圆形)、LOITER_TYPE_FIGUREEIGHT=1(形似数字 8) |
从源码看,固定翼模式管理器在生成盘旋轨迹时会直接读取_pos_sp_triplet.current.loiter_radius来计算曲率(见 FixedWingModeManager.cpp),可见该字段是盘旋几何的"源头输入"。
位置、速度与姿态设定
| 字段 | 类型/单位 | 说明 |
|---|---|---|
valid | bool | 该设定点是否有效,无效设定点必须被消费者忽略 |
vx/vy/vz | float32[m/s] | NED 坐标系下的局部速度设定点 |
lat/lon | float64[deg] | 纬度 / 经度(WGS84) |
alt | float32[m] | 高度,AMSL(海拔) |
yaw | float32[rad],范围 [-π, π) | 偏航角(仅在悬停时使用),NaN 表示交由飞行任务决定 |
course | float32[rad] | 期望航迹角(bearing,对地),NaN 表示未使用 |
到达判据与巡航参数
| 字段 | 类型/单位 | 说明 |
|---|---|---|
acceptance_radius | float32[m] | 水平到达半径:进入此半径即视为到达该航点 |
alt_acceptance_radius | float32[m] | 垂直到达半径,仅固定翼制导使用,NaN 表示交由制导逻辑自行选择 |
cruising_speed | float32 | 期望巡航速度(软约束,非硬限制) |
gliding_enabled | bool | 指示飞行器在具备滑翔能力时进入滑翔(仅固定翼) |
cruising_throttle | float32 | 期望巡航油门(软约束,非硬限制),仅对地面车(rover)生效 |
值得注意的是alt_acceptance_radius与cruising_throttle的"平台限定"语义:前者只有固定翼制导会读取(Navigator::get_altitude_acceptance_radius 中专门针对固定翼返回该值,且SETPOINT_TYPE_LAND前会使用更严格的NAV_FW_ALT_L_RAD);后者则只有 rover 控制器消费,多旋翼/固定翼会将其忽略(固定翼模式下甚至会显式写回 NaN)。
生产者:Navigator 如何构建并发布三元组
position_setpoint_triplet的唯一生产者是Navigator模块(src/modules/navigator),它负责将航点任务(mission)、返航(RTL)、起飞、降落、预精着陆等"高层意图"翻译成控制器可消费的三元组。
发布通道与内部缓冲
在 navigator.h 中可以看到三个关键成员:
uORB::Publication<position_setpoint_triplet_s> _pos_sp_triplet_pub{ORB_ID(position_setpoint_triplet)}—— 发布句柄(第 390 行);_pos_sp_triplet—— 任务模式使用的三元组缓冲(第 411 行);_reposition_triplet与_takeoff_triplet—— 分别用于"非任务直接位置指令"(如地面站 REPOSITION)与"非任务直接起飞指令"的独立三元组缓冲(第 412-413 行),避免与任务三元组互相污染;_pos_sp_triplet_updated—— 标记三元组内容已更新、待发布(第 433 行)。
实际发布动作收敛在Navigator::publish_position_setpoint_triplet()(navigator_main.cpp 第 1336-1341 行):
void Navigator::publish_position_setpoint_triplet() { _pos_sp_triplet.timestamp = hrt_absolute_time(); _pos_sp_triplet_pub.publish(_pos_sp_triplet); _pos_sp_triplet_updated = false; }发布前统一由hrt_absolute_time()刷新timestamp,随后将整个三元组一次性发布到 uORB。各飞行模式(mission、RTL、takeoff、land、loiter 等,见 navigator 目录 下的 mission.cpp、rtl_direct.cpp、takeoff.cpp 等文件)在更新完自己的三元组缓冲后调用set_position_setpoint_triplet_updated()置位,由 Navigator 主循环统一触发发布。
航点任务的滚动更新逻辑
三元组的价值在航点任务中体现得最充分。mission.cpp 的处理流程大致如下(第 203-314 行):
- 取出当前三元组缓冲,复制
current作为"旧当前点"留档; - 把当前执行中的任务项通过
mission_item_to_position_setpoint()转换成current; - 尝试获取后续任务项写入
next;如果没有更多航点了,将next.valid置为false(第 268、290 行),表示"三元组到此为止"——这正是消息头注释所说"或只有两个、一个"的情形; - 当检测到
current与"旧当前点"不一致(即已切到新航段)时,把旧当前点搬入previous(第 298-299 行),保证previous始终是刚离开的航点。
由此形成典型的"滚动窗口":previous → current → next像一个沿任务路径前移的三格滑窗,控制器随时可以拿到完整的"来路、当下、去路"三段信息。mission_item_to_position_setpoint是任务项(含高度、速度、类型、到达半径等)向PositionSetpoint字段的转换桥,也是任务参数与消息字段一一对应的落点。
消费者:谁在读取三元组
position_setpoint_triplet主题被多个子系统订阅,构成"一生产者、多消费者"的典型 uORB 拓扑:
| 消费者模块 | 用途 |
|---|---|
| FlightTaskAuto(多旋翼自动任务) | 将三元组转成轨迹设定点,构建平滑航段 |
| FixedWingModeManager(固定翼模式管理器) | 依据current.type与current.loiter_radius等生成固定翼制导输入 |
| Ackermann/Differential/Mecanum AutoMode 等(地面车) | 自动驾驶模式下跟踪航点 |
| Gimbal 云台 | 随航点同步云台指向 |
| MAVLink 流、UTM_GLOBAL_POSITION.hpp、EXTENDED_SYS_STATE.hpp | 打包进遥测流下发给地面站 |
| RoverLandDetector | 地面车着陆检测参考 |
多旋翼:从三元组到轨迹设定点
以多旋翼的自动飞行任务为例,FlightTaskAuto.cpp 每次迭代都会拉取最新三元组并做健壮性校验(第 409-422 行):
const position_setpoint_triplet_s &position_setpoint_triplet = _position_setpoint_triplet_sub.get(); if (!position_setpoint_triplet.current.valid || !PX4_ISFINITE(position_setpoint_triplet.current.alt)) { // Best we can do is to just set all waypoints to current state _triplet_previous = _triplet_current = _triplet_next = _position; ... }current.valid与高度的有限性检查是消费侧的第一道防线:一旦当前设定点无效或高度非有限值,任务直接退化为"悬停在当前位置",绝不向控制器传播非法设定点。校验通过后,任务生成轨迹时会把_triplet_previous / _triplet_current / _triplet_next组织成航点数组(Vector3f waypoints[] = {_triplet_previous, _position_setpoint, _triplet_next},第 196 行),用于航段内轨迹插值——previous与next在此真正参与平滑转弯的生成,这正是三元组设计的核心价值。
固定翼:按类型分发制导逻辑
FixedWingModeManager.cpp 依据current.type分发不同制导模式:SETPOINT_TYPE_TAKEOFF转入起飞逻辑并随后改写为SETPOINT_TYPE_POSITION(第 409-415 行),SETPOINT_TYPE_LAND进入降落制导(第 429 行),SETPOINT_TYPE_IDLE则维持怠速状态。同时,current.loiter_radius被直接用于盘旋轨迹曲率计算(第 1070-1071 行)。可见同一个三元组在不同机型上被"按需解读",消息字段的语义注释(如"仅固定翼使用")与各消费者的实现严格对应。
典型工作流程:一次三段式航点任务的数据流
将生产、消费串起来,一次简单三段航点任务(WP1 → WP2 → WP3)中的数据流如下:
- 航段 WP1→WP2:Navigator 发布
previous=无效(或起点) / current=WP1 / next=WP2;FlightTaskAuto 校验current.valid后向 WP1 飞行,同时以 WP2 为前瞻目标预规划转弯。 - 进入 WP2:Navigator 检测到
current变化,将旧 current(WP1)搬入previous,新任务项 WP2 写入current,后续任务项 WP3 写入next(mission.cpp 第 298-314 行);再次发布后,控制器平滑地从 WP1 航段过渡到 WP2 航段。 - 航段 WP2→WP3:三元组变为
previous=WP1 / current=WP2 / next=WP3,控制器持续获得三段上下文用于轨迹平滑。 - 任务收尾:WP3 是最后一个航点,
next.valid=false,三元组退化为previous / current / 无效next,控制器据此知道不再有后续航段,可进入终点收敛逻辑。
整个过程中,Navigator 只负责"填数"并发布,控制器只负责"读数"并制导,二者通过position_setpoint_triplet主题解耦——这正是 PX4 uORB 消息机制在该场景下的典型应用。
实用要点
- 在地面站遥测中定位该主题:MAVLink 的
POSITION_TARGET_GLOBAL_INT、UTM_GLOBAL_POSITION等流即由 mavlink streams 从该主题打包而来,飞行日志中可通过position_setpoint_triplet主题回放各航段设定点变化。 - 判定"当前有效航点"的口径:消费者统一以
current.valid && PX4_ISFINITE(current.alt)为有效判据;调试时若发现任务异常停滞,应优先检查current.valid与alt是否被正确填充。 - 区分任务三元组与直控三元组:
_pos_sp_triplet(任务)、_reposition_triplet(地面站直接拖动)、_takeoff_triplet(直接起飞)在 navigator.h 中是三个独立缓冲,避免模式切换时的交叉污染,分析日志时注意区分来源。 - 字段的平台相关性:
cruising_throttle仅 rover 使用、alt_acceptance_radius仅固定翼使用、SETPOINT_TYPE_LAND下高度必须忽略——这些语义约束都由消费者侧代码强制执行,编写基于该消息的扩展模块时务必遵守。
延伸阅读
- PositionSetpointTriplet 消息文档(含原始定义)
- 消息定义 与 依赖消息定义
- 生产者实现:navigator.h、navigator_main.cpp、mission.cpp
- 消费者实现:FlightTaskAuto.cpp、FixedWingModeManager.cpp、input_mavlink.cpp
- 嵌入式
- 物联网
- 机器人
- 自动驾驶
- 智能硬件
【免费下载链接】PX4-Autopilot
PX4 Autopilot Software
相关推荐
PX4-Autopilot uORB 消息 InputRc 深度解析:遥控输入通道、信号质量与数据流
PX4 Autopilot uORB 消息 InputRc 深度解析:遥控输入通道、信号质量与数据流 导读 InputRc 是 PX4 Autopilot 中承
嵌入式物联网机器人自动驾驶智能硬件PX4 FollowTargetStatus 消息解析:跟随目标飞行任务的航向、轨道与云台状态观测
PX4 FollowTargetStatus 消息解析:跟随目标飞行任务的航向、轨道与云台状态观测 本篇技术指南围绕 PX4 Autopilot 仓库中的 Fo
嵌入式物联网机器人自动驾驶智能硬件PX4 MissionResult 消息深度解读:UORB 任务执行状态的全链路剖析
PX4 MissionResult 消息深度解读:UORB 任务执行状态的全链路剖析 PX4 通过 uORB 消息 mission_result 将任务(Mis
嵌入式物联网机器人自动驾驶智能硬件
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考