1. 项目背景与需求分析
在无人机航迹规划系统中,备降点(Rally Point)是一个至关重要的安全机制。这个功能的设计初衷是为了在紧急情况下(如电量不足、通信中断或系统故障)为无人机提供额外的降落选择。传统实现中,当触发返航(RTL)时,飞控系统会自动选择距离当前位置最近的备降点作为降落目标。
但在实际项目开发中,我们发现这种默认行为存在潜在风险。例如在城区巡检场景中,最近的备降点可能位于人群密集区域,而预设的Home点反而是经过严格安全评估的起降场地。因此需要修改APM飞控的默认逻辑,使无人机在无人工干预时优先返回Home点,仅当收到明确指令时才使用备降点。
2. APM飞控备降点机制解析
2.1 数据结构与存储
APM飞控使用AP_Rally库管理备降点数据,核心数据结构如下:
cpp复制struct RallyLocation {
int32_t lat; // 纬度(度*1e7)
int32_t lng; // 经度(度*1e7)
int16_t alt; // 海拔高度(米)
uint8_t alt_frame:4; // 高度参考系
uint8_t alt_frame_valid:1;// 高度参考系有效性标志
};
该结构采用紧凑存储设计:
- 经纬度使用int32_t存储,精度达到0.0000001度(约1cm级精度)
- 高度使用int16_t,支持-32768~32767米范围
- 位域技术节省存储空间,单个备降点仅需12字节
2.2 核心算法流程
备降点选择的核心逻辑位于calc_best_rally_or_home_location()函数:
cpp复制Location AP_Rally::calc_best_rally_or_home_location(
const Location ¤t_loc,
float rtl_home_alt_amsl_cm) const
{
// 默认返回Home点
Location return_loc { AP::ahrs().get_home() };
return_loc.set_alt_cm(rtl_home_alt_amsl_cm, Location::AltFrame::ABSOLUTE);
// 查找最近集结点
RallyLocation ral_loc;
if (find_nearest_rally_point(current_loc, ral_loc)) {
Location loc = rally_location_to_location(ral_loc);
// 决策逻辑
if (!_rally_incl_home ||
(current_loc.get_distance(loc) < current_loc.get_distance(return_loc))) {
return_loc = rally_location_to_location(ral_loc);
}
}
return return_loc;
}
当前实现存在三个关键判断条件:
_rally_incl_home参数:是否将Home点纳入备降点系统- 距离比较:无条件选择最近点
_rally_limit_km:备降点最大有效距离
3. 二次开发方案设计
3.1 需求明确化
经过项目评估,我们确定以下改进需求:
- 默认情况下RTL必须返回Home点
- 仅当收到特定MAVLink指令时才允许使用备降点
- 保留原有备降点管理功能
- 新增备降点激活状态标志
3.2 代码修改方案
3.2.1 新增控制参数
在AP_Rally.h中添加状态标志:
cpp复制class AP_Rally {
private:
bool _rally_override_active; // 新增:是否允许使用备降点
};
3.2.2 修改决策逻辑
重构calc_best_rally_or_home_location()函数:
cpp复制Location AP_Rally::calc_best_rally_or_home_location(
const Location ¤t_loc,
float rtl_home_alt_amsl_cm) const
{
Location return_loc { AP::ahrs().get_home() };
return_loc.set_alt_cm(rtl_home_alt_amsl_cm, Location::AltFrame::ABSOLUTE);
// 仅当显式激活时才考虑备降点
if (_rally_override_active) {
RallyLocation ral_loc;
if (find_nearest_rally_point(current_loc, ral_loc)) {
Location loc = rally_location_to_location(ral_loc);
if (is_valid(loc)) {
return_loc = loc;
}
}
}
return return_loc;
}
3.2.3 新增MAVLink接口
添加指令处理函数:
cpp复制void AP_Rally::handle_mavlink_command(const mavlink_message_t &msg)
{
switch (msg.msgid) {
case MAVLINK_MSG_ID_RALLY_OVERRIDE:
_rally_override_active = (msg.payload64[0] > 0);
break;
}
}
4. 实现细节与关键技术
4.1 地理空间计算优化
原生的get_distance()方法采用Haversine公式计算球面距离:
cpp复制float Location::get_distance(const Location &loc2) const
{
float dlat = radians(loc2.lat - lat);
float dlng = radians(loc2.lng - lng);
float a = sinf(dlat/2) * sinf(dlat/2) +
cosf(radians(lat)) * cosf(radians(loc2.lat)) *
sinf(dlng/2) * sinf(dlng/2);
return 2 * EARTH_RADIUS * asinf(sqrtf(a));
}
在实际测试中发现,当备降点数量超过20个时,遍历计算会成为性能瓶颈。我们引入以下优化:
- 预先计算备降点的直角坐标(x,y,z)
- 使用平方距离比较进行初步筛选
- 仅对候选点进行精确距离计算
4.2 安全边界处理
新增以下安全检查:
- 备降点最小间隔距离(防止设置过近)
- 地形高度验证(避免设置在山体侧面)
- 空域合法性检查(符合当地法规)
cpp复制bool AP_Rally::is_valid(const Location &loc) const
{
// 基础检查
if (loc.lat == 0 && loc.lng == 0) return false;
// 地形检查
float terrain_alt;
if (!AP::terrain()->height_amsl(loc, terrain_alt)) {
return false;
}
// 高度差检查(确保高于地形10米)
return (loc.alt - terrain_alt) > 10.0f;
}
5. 测试方案与验证
5.1 单元测试设计
使用ArduPilot的测试框架添加测试用例:
cpp复制TEST(RallyTest, PriorityOverride)
{
AP_Rally rally;
Location home(35.1234567, 139.1234567, 50.0f);
Location rally1(35.1234667, 139.1234667, 50.0f); // 距离home点约14m
// 测试默认行为
Location result = rally.calc_best_rally_or_home_location(home, 5000);
EXPECT_EQ(result, home);
// 测试激活备降点
rally.set_override(true);
result = rally.calc_best_rally_or_home_location(home, 5000);
EXPECT_NE(result, home);
}
5.2 实飞测试流程
-
基础功能验证:
- 设置3个备降点(距离Home点100m、200m、300m)
- 在中间位置触发RTL,确认返回Home点
-
激活测试:
- 发送MAVLink激活指令
- 触发RTL,确认返回最近备降点
-
边界测试:
- 在备降点限制距离外触发
- 无效备降点测试
6. 部署与性能评估
6.1 内存占用分析
修改前后内存对比:
| 项目 | 原版本 | 修改后 |
|---|---|---|
| 代码段 | 12KB | 13KB |
| 数据段 | 256B | 264B |
| 每个备降点 | 12B | 12B |
6.2 处理时间测试
使用Pixhawk 4硬件测试(100次平均):
| 备降点数量 | 原版本(ms) | 优化后(ms) |
|---|---|---|
| 5 | 1.2 | 0.8 |
| 20 | 4.7 | 2.1 |
| 50 | 11.3 | 4.9 |
7. 实际应用建议
-
参数配置规范:
bash复制# 禁用自动备降点 param set RALLY_INCL_HOME 0 # 设置最大有效距离(米) param set RALLY_LIMIT_KM 2 -
地面站集成建议:
- 在QGC界面添加备降点激活按钮
- 状态面板显示当前备降点状态
-
异常处理策略:
- 通信中断时自动取消备降点激活
- 记录备降点使用日志
在工业巡检项目中,我们通过这种改进方案成功将意外降落率降低了78%。关键经验是:安全关键系统必须坚持"显式优于隐式"的设计原则,自动决策必须为人工控制留有覆盖通道。