Files
ParkingRobot/docs/decisions.md
T

12 KiB

技术决策

只记录长期有效的方案状态;实验临时参数和失败尝试不在此保存。

已经实施

1. 分离 CommonUsage、Shared、M层和C层

  • CommonUsage 保持独立通用底盘库,不反向依赖项目控制层。
  • Shared 只保存M/C共享模型、数学、校验和底盘适配,不建立独立程序集。
  • MedullaAdapter 管硬件,MultiWheelC 管动作和控制。
  • 原因:避免硬件通信、控制算法和旧底盘库相互反向耦合。
  • 依据:三个 .csprojAGENTS.md

2. Shared统一SI单位和真实车体系命令

  • Shared使用m、m/s、rad、rad/s,车体系X前Y左、逆时针为正。
  • 对外底盘命令统一为 Twist2D;旧版mm/deg接口只在 MultiWheelChassisAdapter 边界转换。
  • 原因:减少不同层之间的单位和符号歧义,为后续单车/车队刚体速度分配保留统一模型。

3. 显式β运动坐标系,不根据速度分量猜测模式

  • 切换流程固定为停车、预对齐舵轮、ActivateMotionFrame(β),运行阶段统一调用 SendBodyTwist()
  • β=0表示车头方向,β=90°表示车体左侧作为虚拟前向;支持任意固定β。
  • 实际四轮始终使用真实布局参与解算,β只改变表达坐标系。
  • β不是改变目标刚体运动的额外自由度;它用于为同一 BodyTwist 选择本运动段更易满足舵角、最小转舵和非奇异条件的主要滚动方向。
  • β不增加车辆物理运动能力,也不改变同一刚体速度最终要求的轮子滚动轴线;当前主要价值是让真实车体系 BodyTwist 能稳定接入方向型旧 SendMotion,并使虚拟GCP角远离±90°表达奇异区。若以后改为 BodyTwist 直接到四轮的完整逆解,β可以退化为底盘内部的等效解选择,不应成为车队控制器的核心概念。
  • β可参与运动前的候选方向规划,但不能代替真实舵轮限位检查:±120°保护必须对完整四轮解算结果逐轮检查,并同时考虑“舵角±180°、轮速反向”的等效解。
  • 限制:运动中不切换β;纯自转要求回到真实车体系并采用专用舵轮准备。
  • 依据:PrepareWheelsForwardTrajectoryTrackingMovementMultiWheelChassisAdapter

4. 保留前后GCP作为旧底盘几何边界

  • 控制层输出前后虚拟GCP方向;MultiWheelChassis.SendMotion 由两条法线求ICR,再计算每个真实轮子的切线方向和速度比例。
  • GCP是刚体控制点,不是物理轮轴中心;ControlPointRadius 必须在前馈、运动学和旧解算中保持一致。
  • 原因:复用已经存在的机械限位、等效舵角、速度斜坡和差速舵轮分配逻辑。

5. 轨迹采用弧长参数化而非时间参数化

  • 轨迹保存点序、累计弧长、车体中心位姿、曲率和有符号参考速度。
  • 实际周期 deltaTime 只进入控制器、滤波器和命令变化率,不作为轨迹索引。
  • 原因:执行进度由车辆空间位置决定,调度周期波动不会直接跳过时间采样点。

6. 正负参考速度表达前进和倒车

  • 轨迹Yaw始终是车头方向;正速度前进、负速度倒车。
  • Stanley曲率前馈、横向/航向修正和终点行驶方向显式考虑速度符号。
  • 同一测试曲线要求速度同号,不在滚动中直接切换前进/倒车。
  • 依据:TrajectoryPointTestTrajectoryFactoryStanleyLateralController

7. 默认状态采用Detour位姿与轮组平面速度组合

  • 位姿和Omega来自经过校验/滤波的Detour。
  • 车体系Vx、Vy来自 GetCarSpeed(true),分别使用同一时间常数低通滤波。
  • 轮组Vw同样滤波,但仅用于Detour跳变期间的短时位姿预测、运动合理性和动态航向创新阈值,不替换控制输出中的Detour Omega。
  • 原因:位置依赖SLAM,控制平面速度优先使用响应更直接的电机/舵角反馈;轮组Vw对短时运动趋势有用,但动态精度尚不足以直接作为闭环角速度。
  • 依据:ParkingVehicleStateProviderFactoryWheelFeedbackVehicleStateProvider

8. 横向控制可替换,纵向控制暂保持PID

  • ILateralController 是Stanley/LQR/MPC等的稳定扩展点;TrajectoryTrackingMovement.LateralControllerFactory 可注入实现。
  • 默认横向为Stanley,默认纵向为 PidLongitudinalController
  • 当前没有单独的控制器工厂文件,避免为手动替换增加不必要结构。

9. 低速和终点采用单向收敛

  • 起步区域使用小幅释放速度;终点前读取更低速度并进入单向低速逼近。
  • 到达或越过终点后只停车,不生成反向修正速度。
  • 完成同时检查剩余弧长、终点欧氏距离、车头航向和β方向实际速度。
  • 原因:停车机器人终点附近反复前后修正风险高,优先保证运动方向稳定和可预测。
  • 依据:ParkingGeometricController.ResolveTerminalApproachSpeed()HasReachedEnd()

10. 对已观察的舵轮响应加入有限前馈与预瞄

  • M层差速转舵角速度前馈已接入,当前默认增益0.9、速度上限0.03m/s;实现位于 MotorRoutine.CalculateDiffSteerRateFeedforward()
  • Stanley曲率前馈预瞄已接入,当前车辆默认时间0.15s、最大距离0.12m。
  • 两者均是可配置补偿,不替代底层PID、真实周期和机械响应验证。

11. 车辆级参数集中到 PilotConfig,动作只做必要覆盖

  • 停车控制参数集中在 Configuration/PilotConfig.ParkingControl.cs,动作默认读取 PilotDefinition.Conf
  • 组合运动段可以覆盖自身完成条件;实验轨迹速度描述实验本身,车辆级最大命令速度仍负责最终限制。

12. Detour阶跃采用任务坐标连续化与安全停车分级处理

  • Detour原始世界观测与当前任务控制位姿通过 controlFromDetour 隔离;疑似阶跃先进入候选确认,确认期间使用轮组 Vx/Vy/Vw 短时预测。
  • 仅对幅值受限且连续确认的小坐标偏移自动更新变换;大幅、不一致或超过确认窗口的变化使状态不可用,由动作安全停车。
  • 完整轨迹状态继续要求位置和航向均可靠;原地自转只依赖独立验证的航向,位置单独异常不再终止正在进行的自转,航向异常仍触发安全停止。
  • 近似原地自转期间禁止自动吸收坐标偏移,避免把旋转定位劣化写入任务坐标系;目标航向到达并停止驱动后,才在既有幅值和确认窗口内处理位置恢复,未恢复时禁止进入下一运动段。
  • l_step 当前只作为诊断和后续健康分级依据,不单独决定状态有效性。
  • 依据:DetourVehicleStateProviderWheelFeedbackVehicleStateProviderMultiWheelRotateInPlace

已经确认但尚未实施

  • 路线顺序:先完成单车闭环和停车功能验证,再正式实施多车通信、编队和协同控制。来源:README.md
  • 当前代码没有可以确认的完整多车分配方案:Shared/Fleet/FleetKinematics.cs 仍只有职责注释,VehicleLayoutFleetMotionCommand 目前只有模型定义、没有业务调用;不得把这些类型当成已经实现的功能。
  • 多车共同搬运不能只闭环车队中心:整体位姿误差与成员相对布局误差必须分开估计和约束,否则成员误差可能相互抵消而使平均中心看似正确。
  • 计划采用分层职责:车队控制器产生参考点 FleetTwist,分配层依据成员 VehicleLayout 计算每车真实车体系 BodyTwist,单车层继续负责β变换、GCP和本车四轮解算。
  • 虚拟车队可使用固定在车队坐标系中的前后GCP作为控制几何,例如位于 ±L_F;这些点只用于把横向控制结果转换成车队参考点 FleetTwist,不是物理轮轴,也不直接参与单车四轮解算。前后GCP方向仍随控制输出动态变化,且横向控制器与GCP到Twist转换必须使用同一 L_F。该方案尚未实施。
  • 每辆成员车都应作为反馈来源,但反馈职责必须分层:成员Detour位姿用于融合车队整体位姿和检查相对布局,单车轮速/舵角用于确认命令执行偏差,电机电流、扭矩或力传感信息用于负载与内力监控。相对位姿接近目标并不能证明没有内力,因此不能只依靠刚性连接或位姿误差判断负载均衡。
  • 每车β应由车队分配层基于整个运动段的速度方向、机械舵角和可行性集中选择;只允许在全车停车时准备和激活。所有成员确认舵轮到位后通过车队级同步屏障统一释放非零运动命令。
  • 旧版参考项目采用固定双车布局:各车由 carWorld ∘ layout⁻¹ 反推车队中心,再对位置和圆周航向求平均;路径控制器以该虚拟中心跟踪轨迹。同时它可按 fleetTarget ∘ layout_i 生成每车理想位姿,并叠加Detour布局纠偏和邻车两腿检测纠偏,因此并非只控制平均中心。来源:原版停车机器人/parkingrobot/ClumsyPilot/PilotDefinition.csChassisController.cs
  • 旧版 SetOriginBias(layoutX, layoutY, layoutTh) 是把各车真实轮子统一表达在车队虚拟坐标系中,属于固定编队布局变换;蟹行通过共同 frontTh/rearTh 表达。它与新版“每车按运动段独立选择纯旋转β”的职责不同,虽然两者可产生相同的实际轮子姿态和车辆运动。
  • 旧版自动 FleetCurveWalkFleetCrabWalk 会先以零速度下发初始GCP角,等待成员新鲜、布局正确、命令可行、舵轮到位和从车应用新序列后才开始运动;原地旋转通过 RotateWheelsAlignedFleetMotionReleased 做整队释放。普通手动入口仍有 SendMotion 本车舵轮未对齐时速度置零的门控,但不保证与自动动作相同的车队级同步屏障。
  • 旧版的全局与局部定位用途不同:自动模式的车队中心估计仍依赖Detour,与局部POS纠偏开关无关;邻车两腿检测只能提供相对间距和姿态信息,不能单独确定世界坐标中的车队中心。
  • 旧版单车几何控制器和原地自转直接读取 DetourInterface.getCartLocation(),未见当前新版的源时间对齐、跳变候选或任务坐标连续化;旧版宿主参考代码另有基于 l_step 和数据新鲜度减速/暂停并触发重定位的 RelocalizationManager。这只能说明旧版通过宿主安全状态机管理明显失效,不能据此认定Detour位姿天然连续;实车部署是否使用相同宿主版本和配置仍待确认。来源:mdcstoolbox/Clumsy/MotionControllers/AbstractGeometricController.cs原版停车机器人/parkingrobot/ClumsyPilot/Movements.csmdcstoolbox/Clumsy/HighLevelSecurity/RelocalizationManager.cs
  • 旧版的 MultiVehicleUseDetectMultiVehicleSyncUseDetour 是彼此独立且默认关闭的开关,并非强制二选一。两者同时开启时,常规/蟹行的 SendMotion() 会直接将检测补偿与POS补偿逐分量相加,没有互斥或状态级融合;这不等于每次运行必然冲突,但存在重复修正、相互对抗和放大噪声的结构风险。来源:原版停车机器人/parkingrobot/ClumsyPilot/PilotConfig.csPilotDefinition.cs
  • 旧版方案只作为设计参考,不直接移植:GetLayoutPoseForCar() 将成员写死为两侧镜像布局,车队几何通过 SetOriginBias(layout)ControlPointRadius=distance/2 进入各车底盘解算;当两类局部纠偏均关闭时,成员一致性仍可能依赖共同开环命令和被搬运物的机械约束。

待评估

  • 多车共同搬运时的车队参考点与固定GCP距离、任意成员布局、加权/异常值鲁棒的车队位姿估计、队形误差闭环,以及 FleetMotionCommand → 每车Twist2D 的具体分配与限幅算法。
  • 负载共享和内力监控可用信号、阈值、降级与停车策略;当前项目尚未建立可确认的力/扭矩闭环。
  • 正式轨迹规划层与 Trajectory2D 的接入格式;当前 TestTrajectoryFactory 仅用于实验。
  • 是否长期保留旧版GCP/SendMotion后端,或增加经过充分验证的“车体Twist直接到各轮”的新后端。
  • 蟹行遥控中按半轮距/半轴距缩放舵角的映射是否符合统一曲率语义;这是遥控手感策略,不应与坐标变换混为一谈。