泽菲罗斯:稳定化与Ondas
陀螺仪到扑翼的桥梁的理想设计:Ondas 呼吸调制、与行程同步的前馈、锁相共振与气动弹性 PID 增益调制——以及对当前固件实际接线情况的诚实地图。
谱系:OrniFlight 与简化的 Ondas
Ondas 并非 PteronautOS 的发明。波调制族——呼吸-停顿节拍控制、冲程形状凶猛度、非对称停留,以及翼载荷与 PID 权限的气动弹性耦合——生存并演化于 OrniFlight 项目中,其 wiki 与模拟器承载了高级算法(包括 servo-efficiency table )。
PteronautOS 内嵌一个部分简化的实现:同样的数学呼吸几何,缩放至一颗 ESP8285、一个 MPU6050 与最多九个伺服器。OrniFlight 离线模拟连续气动弹性并探索整个包络族,而 PteronautOS 必须在 4 ms 节拍内、在 80 MHz 内核上、与 ExpressLRS 无线栈共享同一硅片作出决策。本文中的每个增益都存在于两个项目中;下面的固件常量是机载子集。
信号链路——从 泽菲罗斯 到 Ornithopter
从陀螺仪到扑翼的桥梁被刻意做短——四个文件、无动态分配、无队列:
MPU6050 raw (I2C, 1 kHz register reads)
▼
Zephyrus::update() Mahony AHRS → roll°, pitch°, yawRate °/s
▼ dual PID: roll→0°, pitch→0°, yawRate→0°/s
4 raw pitch terms exposed pitchPTerm · pitchITerm · pitchDTerm · pitchErrorRate
▼
ZephyrusFilter.h (250 Hz) copies terms onto ornithopter.gyroPitch*
▼
Ornithopter::_computeServoMixer() / _computeGearboxMixer()
▼ Ondas P → phase · PD → dwell · I → asymmetry · SSFF → next stroke
_f[] → funcMap → wing / crest-rudder / tail servos (µs)
四个原始项在俯仰 PID 计算出修正后立即写入 Zephyrus::update():
pitchPTerm = ZEPHYR_PID_PITCH_KP * pitchErr; // raw proportional
pitchITerm = _pidPitch.integrator; // accumulated error
pitchDTerm = ZEPHYR_PID_PITCH_KD * _pidPitch.lastDerivative; // low-pass filtered D
pitchErrorRate = _pidPitch.lastDerivative; // °/s, for SSFF
四者均受 NaN 陷阱保护(任一输入为 NaN 即全部清零),使损坏的 I²C 帧永远无法到达混控算术。Ornithopter 上的七个字段接收桥接数据:
| 字段 | Zephyrus 源 | 消费方 |
|---|---|---|
gyroPitchPTerm
|
pitchPTerm
|
Ondas P → 相位提前(节拍通道) |
gyroPitchITerm
|
pitchITerm
|
Ondas I → 冲程非对称(平衡通道) |
gyroPitchDTerm
|
pitchDTerm
|
Ondas D → 停留比(凶猛度通道) |
gyroPitchErrorRate
|
pitchErrorRate
|
SSFF 半冲程累积 |
gyroRudderCorrection
|
rudderCorrection
|
冠舵 µs 偏移(伺服与变速箱内核) |
gyroAileronCorrection
|
rollCorrection
× gearbox gain
|
变速箱:横滚 PID → V 尾副翼面 |
gyroElevatorCorrection
|
pitchCorrection
× gain ×
aeroGainScale
|
变速箱:俯仰 PID → 升降副翼/升降舵面 |
Ondas 调制——三通道呼吸
Ondas(葡萄牙语“波”)是一个三通道呼吸系统,将俯仰 PID 的原始 P、I、D 项映射到扑翼波形的三个正交维度。它是一个本体感受回路:陀螺仪对俯仰的感知直接塑造机翼运动,而机翼运动又改变陀螺仪感知到的俯仰。
节拍 — P → 相位提前
正俯仰误差(机头上仰)使振荡器相位提前,缩短当前半冲程;负误差使其延迟。理想定律缩放振荡器弹簧:
_osc.kGainMod = 1.0f + gyroPitchPTerm * aeroGainScale * cadenceGain * 0.00005f;
// clamped to [0.5, 2.0] — phase can at most double or halve
振荡器的 advance() 将其消费为 error = kGain · kGainMod · cadenceTarget − kDamp · cadence。调校范围 0–100,默认 20。
凶猛度 — PD 混合进入停留
P 与 D 项被混合为单一凶猛度信号,使波形的停留锐化或柔化:
ferocitySignal = (gyroPitchPTerm * ferocityPGain * 0.00015f
+ gyroPitchDTerm * ferocityDGain * 0.0003f) * aeroGainScale;
// clamped to [-0.5, 0.5], added to both stroke and return ferocity
当 ferocityPGain = 0(默认)时行为为纯 D——快速俯仰变化产生更锐利的冲程,而稳定飞行保持正弦。
平衡 — I 进入非对称
积分项移动冲程中心:持续的机头上仰偏置强化下冲程,持续的机头下俯偏置强化上冲程。
float iBias = gyroPitchITerm * aeroGainScale * balanceGain * 0.0001f;
// clamped to [-3.0, 3.0]; added to strokeFer, subtracted from returnFer
平衡在设高时是最不稳定的通道——理想调校指南保持其低值(5–15)并最后加入。凶猛度应用结合飞行员指令、Ondas 与 SSFF 偏置,在完整 [1.0, 8.0] 窗口内保持飞行员的权限:
strokeFer = pilot(stroke) + ferocitySignal + iBias + _ssffFerocityUpBias
returnFer = pilot(return) + ferocitySignal − iBias + _ssffFerocityDownBias
波形整形与 PD 混合
波形本身遵循 OrniFlight 冲程族:每半程使用各自的凶猛度,共享反转阈值保持左右机翼同相,而按配置文件的形状混合持续将平坦的停留/平台冲程转化为圆润的金字塔路径。下方的交互式探索器为任意下/上凶猛度对渲染指令几何——即混控器每个节拍所请求的同一条曲线。
力度同时控制半行程的特性与时机。内部上,WebUI 的 0–100 设置映射到 0–8。下行程力度越高,下行程在周期中的占比越短;回程力度越高,回程占比越短。剩余时间转移到另一半 — 零点处没有停顿。
每个配置文件的力度形状控件选择高力度特性。0% 时偏向有限平台/方形;100% 时偏向圆角金字塔路径。每一半仍使用自己的力度,因此低力度的一半保持拉长且正弦,而高力度的一半趋近于直接的对角线穿越。
下行程与回程偏移(±100)沿各自起止轴移动每个半行程的中心——与力度相同的逐半镜像。正值为前移:机翼更早达到峰值速度,增强推力。负值为后移:行程在末端消耗运动,减弱推力。该变形单调且保持端点,因此恰为不对称的方波↔三角波混合,绝非位置跳变。
油门推力形态耦合通过一个旋钮融合冲程驻留与前-后中心。全油门时冲程方形化,且两个半冲程前移——下降与上升的峰值速度都更早到来。怠速时两者保持中性。单一的攻击性标量共同驱动驻留与中心,使两翼与两个半冲程同步运动——是推力控制,而非滚转或俯仰。
副翼→skew 耦合前载一翼而延迟另一翼——在 skew 轴上的滚转力矩,是油门 skew 的镜像孪生。杆向左给左翼加 skew 并从右翼减去;向右则相反。可与方向舵幅度差动并用或替代之。
Slew 是对摇杆速率的瞬时加速或制动。给油会短暂 front-load 两个半冲程,收油会短暂 late-load 两个半冲程;低通滤波后的速率(τ = 0.10 s)注入冲击,摇杆回中后衰减。两种耦合:油门速率 slew(对称、推力)与副翼速率 slew(差动、横滚)。
Zephyrus 的 slew gain 将同样的瞬态思想用于方向舵:姿态快速变化时短暂增强方向舵修正(µs),低通滤波(τ = 0.12 s)并硬限幅 ±80 µs。它在不提高静态增益的情况下锐化对快速姿态变化的响应。
控制轴矩阵
方向舵摇杆在机翼混合器中没有任何偏航权限:其差动旋钮(振幅与凶猛度)产生与副翼偏移相同的左/右不对称——而这种不对称就是滚转。真正的偏航只存在于自主头冠舵(Zephyrus,仅陀螺仪)中。
| 控制输入 | 波形参数 | 飞行效果 |
|---|---|---|
| 副翼摇杆 | 偏移 (skew) — 差动,左/右 |
滚转 |
| 方向舵摇杆 | 振幅 + 凶猛度 — 差动,左/右 |
滚转 |
| 偏航 — Zephyrus 陀螺仪 | 头冠舵 | 偏航(自主) |
飞行操纵与 slew
整个周期
每一半拉伸至等宽
解读极端组合
7 / 1 组合明显产生短而尖的下行程和长的正弦回程。精确值和近最大值需要谨慎:当前时长法则使用力度 8 以下的剩余量。因此,8 / 0 仅将周期约 0.125% 分配给下行程,而即使 8 / 6 也仅分配约 0.5%。位置保持连续,但所需的速度和加速度可能在物理上无法达到。
锚定阻尼 (k₂)
振荡器的阻尼作为可调锚点暴露。基本定律是朝向节拍目标的阻尼弹簧:
kDamp = 10.0f + anchorGain; // anchorGain 0 → k₂=10 (tight)
error = kGain * kGainMod * cadenceTarget
- kDamp * cadence;
当 anchorGain = 0(默认)时阻尼紧绷——快速收敛到指令节拍。更高值在增益 100 时把 k₂ 推向 110,更紧地锁定节奏并抑制扰动。调校范围 0–100。
共振——锁相泵
共振是一个锁相锁定放大器:它将俯仰误差率乘以 sin(振荡器相位) 并累积——在修正最有效时恰好强化冲程,在会与机翼对抗时加以阻尼。
_resonanceAccum += gyroPitchErrorRate * sinf(_osc.phase)
* resonanceGain * 0.01f * dt;
_resonanceAccum *= expf(-dt / 0.15f); // leaky integrator, τ = 0.15 s
clamp(_resonanceAccum, -2.0f, 2.0f);
累积值被注入下一帧的冲程与回复凶猛度。当 resonanceGain = 0(默认)时整条路径禁用。泄漏衰减可防止持续扰动期间的失控累积。
SSFF——与行程同步的前馈
冲程同步前馈在理念上不同于任何 PID 项:它根据陀螺仪在当前半冲程中测得的值来修正下一个半冲程。在扑翼正弦的每个过零点(机翼反转),已完成半冲程的平均俯仰误差率成为对面半程凶猛度的偏置。
// zero-cross detected: finished one half-stroke, starting the next
meanError = _ssffAccumError / count;
bias = meanError * ssffGain * 0.00001f; // clamped ±2.0
// upstroke just ended → bias feeds the downstroke (power stroke)
// downstroke just ended → bias feeds the upstroke (recovery)
上偏置施加于下冲程(修正上一上冲程累积的误差);下偏置施加于上冲程。当 ssffGain 降为零时偏置被显式清除,因此 WebUI 禁用绝不会在波形中留下陈旧值。累加器为 32 位并每半冲程复位——在 250 Hz 下需约 24 天连续扑翼才会溢出,这并非实际担忧。
气动弹性 PID 增益调制
所有 Ondas 与 SSFF 调制都由一个知道扑翼机处于扑翼还是滑翔状态的系数缩放——气动弹性增益调制。在伺服(波形)内核中,选择器是带 50 µs 滞回的扑翼闸门:
aeroGainScale = isFlapping ? (aeroFlapCoeff * 0.01f)
: (aeroGlideCoeff * 0.01f);
在变速箱内核中,选择器是电机状态(armed && throttleNorm > 0.1f)。默认值:
| 系数 | 默认 | 范围 | 生效时 |
|---|---|---|---|
aeroGlideCoeff
|
40 | 0–100 | 机翼静止——滑翔,或变速箱电机关闭 |
aeroFlapCoeff
|
40 | 0–100 | 机翼扑动——或变速箱电机运转 |
缩放至 0–1 使 0–100 滑块成为陀螺仪对机翼的权限:100 时陀螺仪完全掌控调制,0 时关闭。按内核划分的权限:
| 权限 | 伺服(波形)内核 | 变速箱内核 |
|---|---|---|
| 冠舵 | 横滚 + 偏航结合 | 仅偏航(横滚/俯仰去往腿) |
| 机翼波形 | 完整 Ondas / SSFF 呼吸调制 | — |
| 腿副翼(V 尾) | — | 横滚 PID → 升降副翼混合的副翼侧 |
| 腿升降副翼/升降舵 | — | 俯仰 PID × aeroGainScale → 升降舵侧 |
变速箱 PID 修正在混合前钳制于 ±250 µs(ZEPHYR_GEARBOX_CLAMP_US);冠舵路径钳制于 ±200 µs。一帧延迟是固有的:aeroGainScale 在变速箱混控器中计算,但由下一个zephyrusUpdate() 消费——250 Hz 下 4 ms,对机械伺服器可忽略。
WebUI 面板与配置端点
当构建包含 Zephyrus 时,扑翼机面板显示两个稳定组。Ondas 与 SSFF 滑块(0–100):节拍 P→相位、凶猛度 D→停留、凶猛度 P→停留、平衡 I→非对称、锚点 k₂、共振、SSFF 增益。气动弹性组:滑翔系数与扑翼系数。所有值通过 POST /pteronautos/config 持久化,并经 GET /pteronautos/state 流回:
{
"ornithopter": {
"cadence_gain": 20.0, "ferocity_d_gain": 20.0, "balance_gain": 10.0,
"ferocity_p_gain": 0.0, "anchor_gain": 0.0, "resonance_gain": 0.0,
"ssff_gain": 0.0,
"aero_glide_coeff": 40.0, "aero_flap_coeff": 40.0,
"aero_gain_scale": 0.4
}
}
aero_gain_scale 为计算所得且只读。POST 接受部分更新并在服务器端将每个字段钳制到 [0, 100]。
调参指南
理想的飞行测试序列——每一步是一次飞行,而非拖动滑块:
- 将所有增益归零。仅手动飞行;在陀螺仪获得投票权之前,机架必须稳定且可预测。
- 启用 Zephyrus 的冠舵(横滚+偏航 PID)。在触碰波形之前,验证方向舵能抵抗轻微晃翼。
- 节拍(P→相位)从 10 起向上。过高 = 机翼抖动、相位搜索;过低 = 无效。合适 = 机翼感觉与俯仰“相连”。
- 凶猛度 D(D→停留)从 10 起。过高 = 波形在锐利与柔和间振荡;合适 = 快速俯仰变化锐化冲程,稳定飞行保持正弦。
- 凶猛度 P(可选)从 5 起——将 P 权限混入停留。
- 平衡(I→非对称)最后、低值。这是最不稳定的通道;仅 5–15。它对抗持续漂移,而从不针对瞬时颠簸。
- SSFF 从 5 起,仅在节拍与凶猛度稳定之后。过高 = 过度修正与半冲程颤振;合适 = 俯仰振荡幅度的可见阻尼。
- 气动弹性系数最后。先调滑翔(机翼静止),再调扑翼。让陀螺仪做一个权威的副驾驶,而非紧张的飞行员。
实现状态与未解决的不一致
如实地图,当前固件(Ornithopter.cpp @ 72c63020)。上文的理想定律是设计;代码包含完整的参数面、常量、WebUI 滑块与桥接垫片——但一个飞行测试脚手架块目前将大部分陀螺仪与伺服内核断开:
// Ornithopter.cpp:269-275 (inside the flapping branch)
#ifdef ZEPHYRUS_ENABLED
// STEP 7: ALL gyro values hard-zeroed (NaN guard test)
_osc.kGainMod = 1.0f; // cadence channel OFF
gyroRudderCorrection = 0.0f; // crest rudder OFF while flapping
gyroAileronCorrection = 0.0f;
gyroElevatorCorrection= 0.0f;
#endif
该块作为“STEP 7”NaN 守卫测试随 i18n 工作一起提交且从未回滚,意味着如今的伺服内核行为为:
- 节拍、凶猛度-PD、平衡、共振、SSFF——均以参数形式存在于桥接中,但其消费点(
kGainMod、ferocitySignal、iBias、resonanceBias)被钉为零或每帧复位(Ornithopter.cpp:282–284、311–313、354)。 - 冠舵稳定在扑翼分支内部被清零,因此方向舵修正目前仅在滑翔分支中生效——与飞行所需相反(大多数扰动在扑翼中途到来)。
- 变速箱内核是活着的例外。它读取
gyroAileronCorrection/gyroElevatorCorrection/gyroRudderCorrection并带钳制应用它们(第 436–451 行)——STEP-7 清零块只存在于伺服内核。
这不是对数学的批评——而是一个已知、已命名的状态:稳定模块已编译、已参数化、已桥接,正等待移除 STEP-7 脚手架并替换为真正的 NaN 策略(Validatio 守卫已为 MPU 数据提供干净路径)。在此之前,请将上文的 Ondas/SSFF/共振调校指南视为可飞行的规范,已对照 Zephyrus.cpp:729–737 与 OrnithopterWaveform.h 验证,但尚未升空。
权威设计记录仍是 STABILIZATION.md ;其姊妹项目 OrniFlight 承载着持续推进的 ONDAS 研究。