3. 导航控制器:解析L1导航算法,理解固定翼如何‘看’向目标点并生成横向加速度指令

各位同学,欢迎来到第三讲。

上一章我们聊了TECS,那是固定翼的“油门和升降舵”的配合艺术。今天咱们来拆解另一个核心模块——导航控制器。说白了,就是飞机怎么“看”向目标点,然后自己决定该往哪边拐弯。

在ArduPilot里,固定翼的横向导航用的是L1导航算法。这个名字听起来挺唬人,其实核心思想很简单:让飞机像被一根虚拟的橡皮筋拉着,始终指向目标航线。我当年第一次看到这个算法时,心里想的是:“这不就是高中物理里的向心力公式吗?”嗯,还真就是那么回事。

3.1 为什么不用纯PID跟踪航线?

你可能会问:“直接用PID控制航向角偏差不行吗?”

行,但效果不好。我早期在调试一个飞翼时试过纯PID跟踪,结果飞机在航线附近来回震荡,像喝醉了酒。原因很简单:PID只盯着当前误差,没有“前瞻性”。飞机快到目标点了才开始猛打舵,必然过冲。

L1算法高明在哪?它引入了一个虚拟目标点,这个点永远在航线前方。飞机不是追着当前点跑,而是追着“未来的自己”该在的位置。你想想看,这就像开车时你盯着远处弯道的切点,而不是眼前的路沿石。

3.2 L1算法的核心逻辑

咱们直接上干货。L1算法的输入只有两个:

  • 飞机当前位置与目标航线的侧偏距(cross-track error)
  • 飞机当前的地速向量(ground speed vector)

输出也只有一个:横向加速度指令(lateral acceleration command)。

算法流程分三步:

  1. 在航线上找一个“L1参考点”——这个点位于航线前方,距离飞机约等于L1距离(通常取飞机当前地速的某个倍数,比如2秒的飞行距离)。
  2. 计算飞机到L1参考点的视线向量——说白了就是“飞机当前指向L1点的方向”。
  3. 用这个视线向量与飞机速度向量的夹角,生成横向加速度——公式很简单:a_cmd = 2 * V^2 / L1 * sin(η),其中η就是那个夹角。

嗯,这里要注意:V是地速,不是空速。为什么?因为横向加速度是相对于地面的,风的影响必须考虑进去。我见过有人直接用空速算,结果大侧风时飞机拐弯半径完全不对。

核心公式:

a_cmd = 2 * V^2 / L1 * sin(η)

其中:

  • V:地速(m/s)
  • L1:前瞻距离(m),通常取 V * 2
  • η:飞机速度向量与视线向量的夹角(rad)

3.3 参数调优:L1距离怎么设?

这是实际工程中最头疼的问题。L1距离设大了,飞机拐弯很“肉”,响应慢;设小了,飞机像惊弓之鸟,来回摆动。

我个人的习惯是:先按2秒地速设一个基础值。比如巡航速度15m/s,L1就设30米。然后看实际飞行效果:

  • 如果飞机在航线附近有轻微震荡,说明L1偏小,适当增大10%~20%。
  • 如果飞机过弯后回正很慢,说明L1偏大,减小10%~20%。

另外,ArduPilot里还有一个L1周期参数L1_PERIOD),它控制着L1距离与速度的比例关系。默认是20秒,我建议不要轻易改。我曾经在一个小翼展的飞翼上试过改成15秒,结果飞机在顺风转弯时直接螺旋了——因为顺风时地速突然增大,L1距离跟着变大,但转弯半径没跟上。

避坑指南:

我曾经在调试一架2米翼展的飞翼时,发现飞机在航线末端总是“甩尾”。查了半天,原来是L1距离设得太小,导致飞机在接近目标点时提前转弯。后来我把L1距离从1.5秒改到2.5秒,问题解决。记住:L1距离不是越小越好,它决定了飞机的“预判能力”

3.4 代码层面的实现

咱们来看看ArduPilot里L1算法的核心代码(简化版):

// 计算L1参考点位置
Vector2f L1_point = get_L1_reference_point(segment, aircraft_pos);

// 计算视线向量
Vector2f sight_vector = L1_point - aircraft_pos;

// 计算速度向量与视线向量的夹角
float eta = wrap_PI(atan2(sight_vector) - heading);

// 计算横向加速度
float V = ground_speed;
float L1_distance = V * L1_period;  // L1_period 默认20秒
float a_cmd = 2.0f * V * V / L1_distance * sinf(eta);

// 限制最大加速度(防止舵面饱和)
a_cmd = constrain_float(a_cmd, -max_lat_accel, max_lat_accel);

你看,核心代码就这么几行。但实际工程中,边界情况处理才是大头:

  • 飞机刚起飞时地速很小,L1距离会变得非常短,这时候要加一个最小L1距离限制(我一般设10米)。
  • 当飞机正好在航线上时,η=0,横向加速度为0,飞机直飞。但如果此时有侧风,飞机会被吹偏,所以L1算法天然有抗风能力——因为地速向量已经包含了风的影响。

3.5 用SVG画一张L1算法逻辑图

光说可能不够直观,我画了一张图帮你理解整个流程:

目标航线 飞机当前位置 地速向量 V L1参考点 视线向量 η 侧偏距 a_cmd = 2·V²/L1·sin(η)

这张图里,飞机已经偏离了航线(有侧偏距)。L1参考点选在航线前方,飞机需要调整航向,让速度向量指向L1点。夹角η越大,需要的横向加速度就越大。

3.6 实际飞行中的表现

L1算法在ArduPilot里已经非常成熟了。我测试过从1.5kg的小飞翼到25kg的测绘机,效果都很稳定。但有几个场景需要特别注意:

场景 现象 解决方法
大侧风飞行 飞机“漂移”严重,航线跟踪误差大 增大L1_PERIOD(如25秒),让飞机更“前瞻”
顺风转弯 转弯半径突然变大,容易冲出航线 限制最大横向加速度,或减小L1_PERIOD
低速飞行(如着陆) L1距离过小,飞机抖动 设置最小L1距离(如10米)

警告:

千万不要在飞行中动态调整L1_PERIOD参数!我见过有人想通过GCS实时改参数来优化转弯效果,结果飞机在转弯时参数突变,直接进入震荡模式。正确的做法是:先在地面仿真,或者用SITL(软件在环仿真)验证参数,再上真机

3.7 小结

L1导航算法的精髓,就是用一个虚拟的前瞻点,让飞机始终“看向”未来。它不需要复杂的路径规划,也不需要精确的模型参数,靠一个简单的几何关系就能实现平滑的航线跟踪。

我个人觉得,L1算法是ArduPilot里最优雅的设计之一。它把复杂的导航问题,简化成了一个高中物理公式。你想想看,一个公式就能让飞机在风中稳稳地飞出一条直线,是不是很神奇?

嗯,今天就到这里。下一章我们聊聊更进阶的内容——如何用L1算法实现“绕圈”和“盘旋”模式。到时候你会发现,同一个算法,换个参数就能玩出不同花样。


专注资料整理