4、主从选举机制:基于优先级的选举、基于健康度的选举、基于Raft的共识选举
说到冗余飞控,有个问题绕不开:谁说了算?
三套飞控同时在线,各自算各自的。万一结果不一样,听谁的?总不能三套一起输出,舵机得疯掉。所以必须有个主从选举机制,选出一个老大,其他当小弟。小弟们可以提意见,但最终决策权在老大手里。
我这些年做飞控系统,见过不少选举方案。说白了,就三大类:基于优先级、基于健康度、基于Raft共识。咱们一个一个聊。
4.1 基于优先级的选举:简单粗暴,但够用
这是最原始的办法。出厂前就给每套飞控定好优先级:1号最高,2号次之,3号最低。上电后,优先级最高的直接当主控。
听起来很合理对吧?但有个坑——优先级高的那套万一坏了呢?
我曾经在一个项目中遇到过这种情况:1号飞控的IMU(惯性测量单元)飘了,但它优先级最高,死活不肯让位。结果飞机在天上画起了龙。后来我们加了条规则:优先级高不等于永远当主,得定期报健康状态。
- 每套飞控有固定优先级(1 > 2 > 3)
- 上电时,优先级最高的自动成为主控
- 主控故障或失联时,次高优先级接替
- 主控恢复后,是否夺回?看策略——我建议不夺回,避免频繁切换
4.2 基于健康度的选举:谁状态好谁上
这个就聪明多了。每套飞控实时计算自己的健康度评分,分数最高的当选主控。
健康度怎么算?我一般用这几个维度:
| 维度 | 权重 | 说明 |
|---|---|---|
| 传感器自检 | 30% | IMU、GPS、气压计是否正常 |
| CPU负载 | 20% | 负载过高说明计算压力大 |
| 通信延迟 | 20% | 与其他飞控的同步延迟 |
| 历史故障 | 15% | 最近10秒内是否出现过异常 |
| 电源稳定性 | 15% | 电压波动是否在允许范围内 |
每套飞控每隔100ms广播一次自己的健康度。其他飞控收到后,对比一下。如果发现自己分数最高,就主动宣称自己是主控。
解决办法?加个滞回比较器。比如当前主控的健康度必须比备选低10%以上,才允许切换。说白了,就是给切换加个死区。
4.3 基于Raft的共识选举:最可靠,但最复杂
如果你做的是高安全等级的飞控(比如载人无人机),我强烈建议用Raft。Raft是分布式系统里公认的共识算法,用在飞控上,说白了就是让三套飞控通过投票决定谁当主。
Raft的核心流程,我简化一下:
- 选举阶段:每套飞控都是候选者,给自己投票,然后拉票
- 投票阶段:收到拉票请求的飞控,检查对方的日志是否比自己新
- 当选阶段:获得多数票(三余度就是2票)的飞控成为主控
- 心跳阶段:主控定期发心跳,备选收到后重置选举超时
这里有个关键点:日志新旧。Raft里不是谁健康谁当主,而是谁的日志最完整谁当主。为什么?因为主控要负责同步状态给备选,日志不完整会导致数据丢失。
// 候选者发起选举
if (election_timeout_expired) {
current_term++;
vote_for = self;
votes_received = 1;
send_request_vote_to_peers();
}
// 收到投票请求
if (request.term > current_term) {
// 对方任期更新,我变成追随者
current_term = request.term;
vote_for = request.candidate_id;
send_vote(true);
} else if (request.term == current_term &&
!voted_in_this_term &&
request.last_log_index >= last_log_index) {
// 日志足够新,投票
vote_for = request.candidate_id;
send_vote(true);
}
我在实际项目中用Raft时,踩过一个坑:选举超时时间设置。三套飞控如果超时时间一样,会同时发起选举,谁也拿不到多数票。后来我让每套飞控的超时时间随机化(比如150ms±50ms),这样总有人先发起选举。
4.4 三种方案对比
| 方案 | 优点 | 缺点 | 适用场景 |
|---|---|---|---|
| 基于优先级 | 实现简单,延迟低 | 无法感知健康状态 | 双余度、低成本系统 |
| 基于健康度 | 动态适应,灵活 | 分数震荡,需滞回 | 三余度、中等安全等级 |
| 基于Raft | 强一致性,高可靠 | 实现复杂,资源消耗大 | 载人、高安全等级 |
4.5 我的建议
如果你刚开始做冗余飞控,我建议从基于健康度的方案入手。它比优先级灵活,又比Raft简单。等系统跑稳定了,再考虑升级到Raft。
嗯,这里要注意:无论用哪种方案,切换逻辑一定要做硬件在环测试。我曾经在仿真里跑得好好的,一上真机就出问题——因为仿真里没有考虑通信延迟。你想想看,三套飞控之间通信延迟如果超过50ms,选举结果可能完全不一样。
最后说一句:选举机制只是冗余飞控的一部分。选出了主控,还得保证主控和备选之间的状态同步。这个咱们下一章再聊。