Files
ParkingRobot/参考文档/多车.txt
T

271 lines
8.3 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
结论:`MultiWheelC\Fleet` 当前的数学链路作为“第一版组件”是成立的,现有 Fleet 数学测试共47个场景全部通过,没有发现明显的坐标系或符号错误。但它还不是可以直接上双车实车的完整工程方案,`FleetStateEstimator` 的等权平均尤其需要增加鲁棒性。
## 正负平均为0是不是问题
不一定,很多时候这正是期望结果。
假设两辆车反算出的车队中心分别为:
```text
车辆1候选中心:+20mm
车辆2候选中心:-20mm
```
平均得到:
```text
车队中心:0mm
```
但代码随后还会计算每辆车相对于这个中心的布局误差:
```text
车辆1相对误差:+20mm
车辆2相对误差:-20mm
```
所以并不是误差消失了,而是被分成了:
```text
公共分量:车队整体中心运动
相对分量:成员之间的队形变形
```
这正好符合当前架构:
- 公共分量交给 `FleetController` 控制车队中心;
- 相对分量交给 `FleetCoordinator` 减速,以及 `FleetMemberCommandCorrector` 小幅纠偏。
如果两辆车反算结果都是 `+20mm`:
```text
平均中心:+20mm
成员相对误差:接近0
```
这表示整个车队共同移动了20mm,而队形没有变,也符合物理意义。
## 当前不是“无条件直接平均”
当前 [FleetStateEstimator.cs](/D:/Users/Desktop/入职培训/停车机器人/MyParking/MultiWheelC/Fleet/FleetStateEstimator.cs:277) 实际执行的是:
1. 将成员状态对齐到统一时刻。
2. 每辆车根据固定布局反算候选车队中心。
3. 检查任意两辆车反算的中心位置差和航向差。
4. 差异超过阈值,直接返回状态不可用。
5. 只有所有候选结果基本一致,才平均:
- X/Y算术平均;
- Yaw圆周平均。
6. 根据融合后的中心重新计算每辆车的布局误差。
所以如果:
```text
车辆1+200mm
车辆2-200mm
```
两者相差400mm,只要超过 `_maximumPositionDisagreementMeters`,代码会在平均前拒绝本周期状态,不会把它们平均成0后继续运行。
Yaw也不是普通平均。例如:
```text
+179°和-179°
```
圆周平均会得到接近 `±180°`,而不是错误地得到 `0°`。
## 当前平均真正的问题
它隐含了一个假设:
> 所有成员定位精度相同、可信度相同,而且没有异常值。
对你目前的 Detour 情况,这个假设不够可靠。
假如真实车队中心是0,而:
```text
车辆1定位正常:0mm
车辆2发生小范围跳变:+60mm
```
当前等权平均会得到:
```text
估计中心:+30mm
```
如果60mm还没有超过候选差异阈值,这个错误会进入车队中心控制。
当前估计器存在三个主要限制:
- 所有成员等权,没有利用定位质量、数据年龄和历史稳定性;
- 单个异常成员超过阈值时,会使整个车队状态不可用,不能隔离坏成员;
- 它是单帧估计,没有利用上一周期车队中心和轮速预测判断哪辆车更可信。
而且你目前主要是双车。两辆车互相矛盾时不存在“多数票”:
```text
车1说中心在A
车2说中心在B
```
只看这两个当前观测,无法判断谁正确。必须引入:
- 上一周期车队状态;
- 轮速运动预测;
- 每辆车定位健康状态;
- 数据新鲜度;
- 连续多帧确认。
## 更成熟、适合你的方案
我建议采用:
> 带时间预测和异常门控的鲁棒加权 SE(2) 融合。
不需要现在就上复杂的因子图或完整EKF。
### 第一步:保留当前反算方法
继续让每辆车计算:
```text
候选车队位姿
= 成员实际世界位姿
× 成员固定布局位姿的逆
```
这部分当前是正确的,不需要推翻。
### 第二步:增加上一状态预测
根据上一周期车队中心和轮组速度预测:
```text
PredictedFleetPose
```
然后每辆车的候选中心分别与预测值比较:
```text
位置创新
航向创新
```
这样双车出现分歧时,可以判断:
```text
车1与预测连续
车2突然跳变
→ 暂时拒绝车2,而不是两车平均或全队立即失败
```
### 第三步:成员单独门控
每个成员分别检查:
- 状态是否可用;
- 数据是否过期;
- 相对预测的位置创新是否合理;
- 相对预测的航向创新是否合理;
- 是否连续多帧异常;
- 后续是否连续多帧恢复。
不要只做当前这种“成员之间两两比较”。
### 第四步:对通过门控的候选加权融合
权重可以先用简单工程等级:
```text
健康且新鲜 → 权重1.0
轻度退化或较旧 → 较低权重
正在异常确认 → 权重0
```
以后 Detour 如果能提供协方差,再改成按协方差加权。
对残差使用 Huber 一类鲁棒损失会让正常小误差仍按最小二乘处理,而异常大残差的影响被压低;这是成熟估计库采用的标准做法,[GTSAM官方文档](https://gtsam.org/doxygen/a04439.html)也明确给出了 Huber 在迭代重加权最小二乘中的权重形式。
### 第五步:输出融合健康等级
建议以后区分:
```text
Healthy
所有有效成员一致,正常融合
Degraded
有一个成员被拒绝,暂时依赖剩余成员和预测,整队限速
Unavailable
所有成员都不可信,或双车分歧且无法判断谁正确
短时保持轮速预测,随后停车
```
## 更严格的数学形式
成熟版本可以直接求一个最符合全部刚体观测的车队位姿:
\[
T_f^*=
\arg\min_{T_f}
\left[
w_p\|\log(T_{pred}^{-1}T_f)\|^2+
\sum_i w_i\,\rho\left(
\|\log((T_fT_{layout,i})^{-1}T_{actual,i})\|^2
\right)
\right]
\]
它表示:
- `T_f`:要求解的车队实际中心;
- `T_layout,i`:第i辆车的固定布局;
- `T_actual,i`:第i辆车当前测量位姿;
- `T_pred`:根据历史和轮速得到的预测中心;
- `w_i`:成员可靠性;
- `ρ`Huber等鲁棒损失。
这是“鲁棒刚体拟合”,比单纯平均更完整,同时利用位置和航向。普通最小二乘刚体配准本身就是成熟方法;鲁棒损失是在异常观测下限制单个数据影响的标准扩展。[刚体点集最小二乘原始问题说明](https://ntrl.ntis.gov/NTRL/dashboard/searchResults/titleDetail/PB91135772.xhtml)
如果将来各车能提供可信协方差,但不同SLAM估计之间的相关性未知,可以考虑 Covariance Intersection;它专门处理未知交叉相关性的估计融合。[Julier与Uhlmann的SLAM融合论文](https://www.sciencedirect.com/science/article/abs/pii/S0921889006001436) 但你目前拿不到Detour协方差,所以现在直接上CI没有足够输入。
## 对当前项目的建议
当前先不要推翻 `FleetStateEstimator`。合理的推进顺序是:
1. 保留现有布局反算、时间对齐、圆周Yaw平均和成员误差计算。
2. 增加“上一车队状态+轮速”的中心预测。
3. 把两两一致性检查改成“每成员相对预测的独立门控”。
4. 对通过门控的成员做加权圆周平均或小规模Huber融合。
5. 允许单个成员短时降级,不要一帧异常就让整个估计不可用。
6. 双车无法判断谁正确时,短时间用预测,仍无法恢复再停车。
7. 最后再考虑完整的SE(2)鲁棒最小二乘,不需要一开始引入GTSAM或QP。
对整个 `MultiWheelC\Fleet` 的当前评价是:
- 布局定义、刚体速度分解、中心控制、相对误差纠偏、最差成员统一减速和全员Ready屏障,结构上没有明显问题;
- 当前最大算法缺口就是车队中心融合还不够鲁棒;
- 最大工程缺口仍是运行入口、通信、成员超时看门狗、报警汇总和零速命令的实际下发;
- `FleetMemberAgent` 目前还缺少独立自动化测试;
- 各种阈值目前只在测试构造中出现,尚未通过双车实车数据标定。
所以,平均本身不是错误;“只做等权平均,并在冲突时整队不可用”才是需要下一阶段改进的部分。
将 FleetMemberReport 转成 FleetMemberStateSample 和 FleetMemberSafetyStatus
将准备命令映射到 FleetMemberAgent
将成员速度命令映射成 FleetCommand
ShouldStop 时广播 Stop 并让主车本地停车;
命令序号、报告序号和任务编号检查;
M层报警和底盘执行失败映射到 FailureCode
无线端口初始化;
报文序列化、分包、校验和接收循环;
主车本地单调时钟和报文接收时间记录。