需要处理,而且对横向误差、航向误差和速度估计都会有明显影响。检测本身不难,困难的是区分: ```text 单帧错误定位 持续性的定位重定位/地图修正 车辆真实的快速运动 ``` 对你这种低速停车机器人,可以先采用一套偏安全、容易验证的处理。 ## 定位跳变会造成什么影响 假设Detour在50ms内突然跳了10cm: \[ v=\frac{0.1}{0.05}=2m/s \] 实际车辆可能只有 `0.3m/s`,但差分速度会产生 `2m/s` 的尖峰。 对控制器还有三个直接影响: - 横向位置跳10cm,横向误差可能瞬间变化10cm。 - 航向跳5°,航向误差会瞬间变化5°。 - 全局轨迹投影可能跳到另一条临近或相交的轨迹线段。 Stanley在低速时尤其敏感: \[ \delta = e_\theta+ \arctan\left(\frac{k e_y}{v+\varepsilon}\right) \] 低速时分母较小,横向误差突然变大,会产生很大的转向指令。因此不能完全不处理。 ## 不建议直接低通掉定位跳变 不要简单地对Detour位置做强低通: ```text 错误位置跳变 → 低通缓慢跟过去 ``` 这样虽然曲线看起来平滑,但控制器会在一段时间内使用滞后、虚构的位置,可能更加危险。 更好的做法是: ```text 检测跳变 → 暂时不把该帧用于速度差分和控制 → 观察后续定位 → 判断是单帧异常还是持续重定位 ``` ## 第一层:运动学合理性检查 将当前Detour位姿和上一次接受的位姿比较。 位置变化: \[ \Delta p=\sqrt{\Delta x^2+\Delta y^2} \] 航向变化: \[ \Delta\theta= |\operatorname{ShortestAngleDifference}| \] 允许的最大变化量可以按照车辆物理能力计算: ```csharp var maximumAllowedDistance = maximumLinearSpeedMetersPerSecond * deltaTimeSeconds + positionJumpMarginMeters; var maximumAllowedHeadingChange = maximumAngularSpeedRadiansPerSecond * deltaTimeSeconds + headingJumpMarginRadians; ``` 然后判断: ```csharp var positionJump = displacementMeters > maximumAllowedDistance; var headingJump = headingChangeRadians > maximumAllowedHeadingChange; ``` 你当前小车最高约 `1.2m/s`,假设Detour更新周期为50ms: ```text 物理最大位移约为: 1.2 × 0.05 = 0.06m ``` 初期可以额外留出约 `0.03~0.05m` 的定位余量。不过这些阈值最终应根据实际Detour数据确定,不建议永久写死。 ## 第二层:不要立即接受异常帧 检测到一个异常帧时,不要立刻改变车辆状态: ```text 上一正常位置 A 异常位置 B 下一帧又回到 A 附近 ``` 这种情况说明B很可能是单帧异常,应直接丢弃。 如果后续连续若干帧都稳定在B附近: ```text A → B → B附近 → B附近 ``` 这更可能是Detour发生了持续性的重定位。 可以使用: ```text 连续2~3个新定位帧相互一致 ``` 作为重新接受定位的条件。 ## 第三层:重定位后必须重置速度估计 如果确认新的定位是持续有效的,不能用: ```text 新位置B - 旧位置A ``` 计算速度,因为A到B是定位修正,不是车辆真实运动。 正确处理是: ```csharp _velocityEstimator.Reset( newPose, currentTimestamp); ``` 这会: - 将新位姿作为新的差分起点。 - 清除之前的速度历史。 - 重置三个低通滤波器。 - 将速度暂时标记为无效或零。 - 等下一次正常Detour更新后重新开始估计。 ## 第四层:控制器应该如何响应 对于实车轨迹跟踪,建议状态分为: ```text Valid 正常定位,可以控制 Suspected 检测到疑似跳变 Reacquiring 正在确认新的定位 Stale 定位长时间没有更新 ``` 你的第一版不一定需要单独增加复杂枚举,但控制行为至少应该满足: ```text 正常: 继续轨迹跟踪 疑似单帧跳变: 不使用异常帧更新状态 短时间保持上一状态 连续异常或定位超时: 停车,不继续使用旧状态运动 确认重定位: 接受新位姿 重置速度估计 重新执行轨迹投影 确认稳定后恢复控制 ``` 停车机器人速度低、场地有限,定位连续异常时停车比盲目继续跟踪更合适。 ## 还需要限制轨迹投影进度 即使Detour跳变检测做了,轨迹投影也最好增加进度保护。 当前投影器在整条轨迹上找最近点,如果轨迹自交,车辆可能从: ```text 当前第20段 ``` 突然投影到: ```text 第80段 ``` 后续可以增加一个 `TrajectoryProgressTracker`: ```text 正常时只在上次线段索引附近搜索 例如 [previousIndex - 5, previousIndex + 20] 定位重定位后: 重新执行一次全局搜索 ``` 同时限制单周期允许的弧长进度变化: \[ |\Delta s| \leq v_{\max}\Delta t+\text{margin} \] 这样可以避免定位轻微波动导致轨迹进度突然跳段。 ## 在五个文件中的分工 ```text DetourVehicleStateProvider ├─ 检查数值有效性 ├─ 检查定位是否过期 ├─ 检测重复帧 ├─ 检测位置/航向跳变 ├─ 暂存疑似新定位 └─ 确认重定位后触发Reset VelocityEstimator2D ├─ 正常位姿差分 ├─ 真实时间差计算 ├─ 速度滤波 └─ 提供Reset() FirstOrderLowPassFilter └─ 提供Update()和Reset() VehicleState ├─ 保存位姿和速度 └─ 表示速度估计是否有效 IVehicleStateProvider └─ 向控制器返回有效状态或读取失败 ``` 因此定位跳变的主要逻辑放在 `DetourVehicleStateProvider`,而不是低通滤波器。 第一版建议先实现: 1. 非有限值检查。 2. 重复帧识别。 3. 基于最大速度和最大角速度的跳变检测。 4. 单帧异常拒绝。 5. 连续2~3帧确认重定位。 6. 重定位后重置速度估计。 7. 长时间定位无效时通知控制器停车。 这套方案足以保护当前Stanley和后续纵向控制,不需要现在就修改SLAM源码。 已经给 [DetourVehicleStateProvider.cs](/D:/Users/Desktop/入职培训/停车机器人/MyParking/MultiWheelC/StateEstimation/DetourVehicleStateProvider.cs:233) 增加了基于上一有效速度的预测残差检测。 现在采用两级判断: ```text 第一级:绝对物理运动边界 第二级:上一状态恒速预测残差 ``` 预测公式为: \[ x_{pred}=x_{last}+v_x\Delta t \] \[ y_{pred}=y_{last}+v_y\Delta t \] \[ \theta_{pred}= \theta_{last}+\omega\Delta t \] 实测残差为: \[ e_p= \sqrt{ (x_{measured}-x_{pred})^2+ (y_{measured}-y_{pred})^2 } \] 以及: \[ e_\theta= \operatorname{ShortestDifference} (\theta_{measured},\theta_{pred}) \] 对应实现在: - [IsPredictionResidualPlausible()](/D:/Users/Desktop/入职培训/停车机器人/MyParking/MultiWheelC/StateEstimation/DetourVehicleStateProvider.cs:536) - [PredictPoseInWorld()](/D:/Users/Desktop/入职培训/停车机器人/MyParking/MultiWheelC/StateEstimation/DetourVehicleStateProvider.cs:573) 默认阈值为: ```csharp 位置预测残差:0.04m 航向预测残差:5° ``` 没有采用最初考虑的30mm,是因为用现有数据离线统计后发现: | 位置残差阈值 | 触发次数 | 占有效更新比例 | |---:|---:|---:| | 30mm | 55次 | 1.24% | | 35mm | 28次 | 0.63% | | 40mm | 13次 | 0.29% | | 45mm | 7次 | 0.16% | | 50mm | 4次 | 0.09% | 30mm容易把正常Detour波动也判成异常;40mm仍能识别现有数据中约49mm和66mm的明显跳变,同时误触发风险更低。 当前判定逻辑: ```csharp if (!isWithinPhysicalBoundary || !isWithinPredictionResidual) { // 进入疑似重定位确认状态。 } ``` 另外同步修正了跳变恢复逻辑: - 发生预测残差跳变时,保存当时的预测位姿。 - 后续定位必须回到预测位姿附近,才能认为是单帧异常后的正常恢复。 - 不再使用较宽松的绝对物理范围立即放行。 - 持续远端定位仍需满足3次观测和0.25秒,才按重定位接管。 - 接管后重置速度估计,避免把坐标修正计算成车辆速度。 第一帧或重定位后的速度还没有建立时,不启用预测残差检测,只使用物理极限检查,避免没有速度基准时误判。 完整构建结果: - CommonUsage:0警告、0错误 - MedullaAdapter:0警告、0错误 - MultiWheelC:0警告、0错误