完善状态估计、车队协调与舵轮辨识日志

This commit is contained in:
2026-08-24 18:39:41 +08:00
parent 0ab409cd2a
commit 95c0b19a26
40 changed files with 5983 additions and 95 deletions
+23 -9
View File
@@ -89,19 +89,33 @@ MovementTest / MotionPlanExecutor
`TrajectoryTrackingMovement` 默认从 `PilotDefinition.Conf` 读取车辆级参数,同时保留少量动作级覆盖字段;横向控制器可通过 `LateralControllerFactory` 替换,纵向控制器当前固定创建为 `PidLongitudinalController`
## 车队纯计算调用
## 车队组件与尚未贯通的执行
```text
FleetState
→ FleetController
→ PathTrackingCore.Compute()
→ GcpKinematics.ToBodyTwist()
→ FleetMotionCommand(参考点为车队原点)
→ FleetKinematics.Decompose(FleetLayout, command)
→ FleetMemberCommand[](各成员真实车体系Twist
夹紧且静止时的成员世界位姿快照
→ FleetLayoutCapture.Capture()
→ 初始FleetPoseInWorld + 不可变FleetLayout
成员状态样本 FleetMemberStateSample[]
→ FleetStateEstimator.Estimate()
→ FleetState + FleetMemberLayoutError[]
→ FleetCoordinator.ExecuteCycle()
→ FleetController(虚拟中心轨迹闭环和固定β_fleet)
→ 相对布局误差统一速度缩放
→ FleetKinematics.Decompose()
→ FleetMemberCommandCorrector
→ FleetMemberCommand[]
车队动作主要滚动方向β_fleet
→ FleetPreparationCoordinator(换算每车β_i并等待全员Ready)
→ FleetMemberAgent(本车停车准备、舵轮到位、激活、Execute/Stop
```
这条链已经覆盖虚拟中心轨迹闭环和确定性刚体速度分解,但尚未接入车队状态估计、通信/时间对齐、相对布局纠偏、共同能力限幅、安全降级和成员底盘发送
`FleetLayoutCapture` 只负责固定布局的几何计算:车队原点X/Y取成员车体中心的算术平均,车队Yaw取主车Yaw,再把各成员世界位姿反变换为 `VehicleLayout.PoseInFleet`。它不读取通信或Detour,也不负责静止/夹紧确认、时间对齐和布局激活
上述类目前是可以独立构造和测试的组件,并没有正式的车队任务运行入口把两条链串起来。缺少的外层需要负责布局原子激活、成员状态实际采集与时间对齐、准备/激活状态机、每周期协调、安全门控、成员命令分发、任务完成与取消。`FleetCoordinator` 生成零速或故障结果不等于实车已经停车;只有运行层把结果送到各车 `FleetMemberAgent.Execute()``Stop()` 后才会影响底盘。
实际部署为每车独立电脑,因此主车还需要状态/命令通信,从车需要本地命令超时看门狗。无线串口初始化可以后接,但消息契约、任务号、心跳/有效期和本地失联停车语义必须在运行层接入前明确。
## 状态数据流
+11 -6
View File
@@ -97,6 +97,8 @@
- `MultiWheelC.Tests/FleetKinematicsTests.cs` 已覆盖整体平移、绕车队中心旋转、绕成员车旋转和停止四个数学场景。
- `MultiWheelC/Fleet/FleetState.cs` 保存车队虚拟中心的世界位姿、同一点的世界系/车队系速度、状态采样时间和速度有效性;`FleetPoseInWorld.Yaw` 定义车队 `+X` 方向,两份速度只是同一物理速度的不同坐标表达。
- `FleetState.SampleTimestampSeconds` 采用主车/协调器生成聚合快照时的本机单调时间。成员本机时钟和Detour `tick` 的同步属于未来接收/状态估计层职责,不阻塞使用人工构造 `FleetState` 开发纯车队控制器。
- 当前无法直接获得被搬运车辆中心,因此 `FleetLayoutCapture.Capture()` 已确定用成员车体中心X/Y的算术平均定义车队原点,用指定主车Yaw定义车队朝向;主车缺失时拒绝采集,不做隐式降级。
- 布局采集只返回采集时刻的 `FleetPoseInWorld` 与不可变 `FleetLayout`,不读取Detour/通信,也不负责夹紧、静止、时间对齐或原子激活。6个布局采集数学场景已通过。
### 14. 原地自转保留绝对航向与轮组相对角两种反馈模式
@@ -109,22 +111,25 @@
- `PathTrackingContext` 只携带受控刚体的车体系速度、速度有效性、轨迹投影和周期控制量,不依赖 `VehicleState``FleetState`
- `PathTrackingCore` 集中实现投影连续性、保护/终点策略、曲率预瞄、横纵向控制和GCP分配;`ParkingGeometricController``FleetController` 分别组合该核心,负责各自的状态适配和输出边界,不通过继承复制控制流程。
- `FleetController` 第一版只闭环车队虚拟中心,并将GCP结果转换成车队原点处的 `FleetMotionCommand`;成员速度继续由 `FleetKinematics.Decompose()` 确定性分解。
- `FleetController` 第一版只闭环车队虚拟中心,并支持固定 `β_fleet`:实际纵向速度沿β投影,GCP结果从运动坐标系旋转到车队坐标系后形成车队原点处的 `FleetMotionCommand`;成员速度继续由 `FleetKinematics.Decompose()` 确定性分解。
- `FleetStateEstimator` 已根据固定 `FleetLayout` 和时间对齐目标时刻反算、融合车队中心,并输出每车 `FleetMemberLayoutError`;成员样本的实际采集和跨电脑时间处理仍属于外层接收链。
- `FleetCoordinator` 已串联状态估计、虚拟中心控制、布局误差警告区间内的统一速度缩放、刚体分解和 `FleetMemberCommandCorrector` 小范围纠偏;越过停止阈值时返回故障和零速成员命令,但尚无正式运行层把该结果送到实车。
- `FleetPreparationCoordinator` 已按 `beta_i = beta_fleet - theta_i` 生成成员准备目标,并通过任务号和全员Ready形成统一激活屏障;`FleetMemberAgent` 已封装本车停车准备、舵轮到位确认、激活、命令校验和底盘执行。两者尚未接入同一个车队任务生命周期,也未接入跨电脑通信。
- 控制算法的可替换性继续由 `ILateralController``ILongitudinalController` 组合注入;状态源、通信、底盘发送和成员协调不进入纯核心。
- `MultiWheelC.Tests` 已覆盖8个Stanley前进/倒车符号场景、6个车队控制周期场景和4个刚体分解场景;统一构建与打包通过。
- `MultiWheelC.Tests` 已覆盖8个Stanley前进/倒车符号场景、8个车队控制周期场景、6个布局采集场景和4个刚体分解场景;统一构建与打包通过。
## 已经确认但尚未实施
- 路线顺序:先完成单车闭环和停车功能验证,再正式实施多车通信、编队和协同控制。来源:`README.md`
- 当前已完成车队布局模型、虚拟中心状态模型、虚拟中心轨迹控制和纯运动学分解,尚未形成可运行的多车链路:布局采集/激活、车队状态估计、通信、成员纠偏和安全协调仍未接入业务流程
- 布局生命周期区分夹紧前后的语义:夹紧前的预设布局只用于引导车辆就位;车辆夹紧且静止后,应同步读取成员位姿,选择车队参考系并创建新的不可变 `FleetLayout`,再由上层协调器原子激活。共同搬运期间的相对位姿变化属于状态误差,不能通过修改 `FleetLayout` 吸收;松开车辆后清除激活布局。具体采集和激活接口尚未实施。
- 当前多车的布局、状态估计、中心控制、刚体分解、成员纠偏、β准备屏障和本车执行代理均已有代码组件,但尚未形成可运行的多车链路。仍缺少车队任务运行入口、布局原子激活、成员状态实际采集/时间对齐、跨电脑通信、命令分发和可实际触发停车的安全执行链
- 布局生命周期区分夹紧前后的语义:夹紧前的预设布局只用于引导车辆就位;车辆夹紧且静止后,应同步取得同一世界坐标系下的成员位姿,调用 `FleetLayoutCapture` 创建新的不可变布局,再由上层协调器原子激活。共同搬运期间的相对位姿变化属于状态误差,不能通过修改 `FleetLayout` 吸收;松开车辆后清除激活布局。实际数据采集和激活接口尚未实施。
- 多车共同搬运不能只闭环车队中心:整体位姿误差与成员相对布局误差必须分开估计和约束,否则成员误差可能相互抵消而使平均中心看似正确。
- 计划采用分层职责:车队控制器产生参考点 `FleetTwist`,分配层依据成员 `VehicleLayout` 计算每车真实车体系 `BodyTwist`,单车层继续负责β变换、GCP和本车四轮解算。
- 第一版采用确定性的虚拟刚体速度分配,不先引入QP/HQP:若成员在车队系中的固定布局为位置 `(x_i,y_i)`、朝向 `theta_i`,则成员中心在车队系中的速度为 `(Vx-omega*y_i, Vy+omega*x_i, omega)`,再通过 `R(-theta_i)` 转到本车体系后交给 `SendBodyTwist()`。QP/HQP只在需要同时调整车队参考速度、处理成员能力差异、松弛约束或严格任务优先级时再引入。
- “按状态最差车辆协调速度”采用车队共同可行性和统一缩放表达:普通能力受限时由所有成员约束确定共同速度比例;任一成员报警、通信超时、状态不可用或刚体误差越界时整队停车。时间戳、心跳、命令有效期和本地超时停车属于第一版安全契约,延迟预测补偿可以后续增加。
- “按状态最差车辆协调速度”第一步已经对成员相对布局误差实现警告阈值至停止阈值之间的统一速度缩放。成员报警、通信超时、夹紧异常、状态持续不可用等整队停车条件仍需由真实运行层统一执行;时间戳、心跳、命令有效期和从车本地超时停车属于第一版安全契约,延迟预测补偿可以后续增加。
- 虚拟车队使用固定在车队坐标系中的对称前后GCP,把横向控制结果转换成车队原点 `FleetTwist`;这些点不是物理轮轴,也不直接参与单车四轮解算。横向控制器与GCP到Twist转换必须使用同一控制点半径;具体车辆级配置值和实车验证仍待完成。
- 每辆成员车都应作为反馈来源,但反馈职责必须分层:成员Detour位姿用于融合车队整体位姿和检查相对布局,单车轮速/舵角用于确认命令执行偏差,电机电流、扭矩或力传感信息用于负载与内力监控。相对位姿接近目标并不能证明没有内力,因此不能只依靠刚性连接或位姿误差判断负载均衡。
- 第一版不把每车β作为复杂优化变量:车队动作先明确主要滚动方向 `beta_fleet`(如正常0°、斜行45°、横移90°),成员按固定布局朝向换算 `beta_i = beta_fleet - theta_i`,并用180°等效和有符号速度选择方便的本地表示。β是单车执行坐标系,不改变刚体分配得到的真实车体系 `BodyTwist`,也不会让各车命令数值相同;仅允许在全车停车时准备和激活,全部成员舵轮到位后通过同步屏障释放非零命令。只有出现复杂布局、整段方向变化、限位余量或频繁反号问题时,才增加轨迹级β候选搜索。
- 第一版不把每车β作为复杂优化变量:`FleetController` 已支持固定的车队主要滚动方向 `beta_fleet`(如正常0°、斜行45°、横移90°)及其控制坐标转换;`FleetPreparationCoordinator` 已按布局换算成员 `beta_i`,并用180°等效轴保持在方便的本地表示范围。β是单车执行坐标系,不改变刚体分配得到的真实车体系 `BodyTwist`,也不会让各车命令数值相同。当前缺的是把停车预对齐、全员Ready和统一激活接入真实运行链;只有出现复杂布局、整段方向变化、限位余量或频繁反号问题时,才增加轨迹级β候选搜索。
- 旧版参考项目采用固定双车布局:各车由 `carWorld ∘ layout⁻¹` 反推车队中心,再对位置和圆周航向求平均;路径控制器以该虚拟中心跟踪轨迹。同时它可按 `fleetTarget ∘ layout_i` 生成每车理想位姿,并叠加Detour布局纠偏和邻车两腿检测纠偏,因此并非只控制平均中心。来源:`原版停车机器人/parkingrobot/ClumsyPilot/PilotDefinition.cs``ChassisController.cs`
- 旧版 `SetOriginBias(layoutX, layoutY, layoutTh)` 是把各车真实轮子统一表达在车队虚拟坐标系中,属于固定编队布局变换。旧版联动显式区分常规、蟹行和绕车队中心旋转三类模式;蟹行角可由动作或遥控给出任意值(`FleetCrabWalk` 默认45°),并在运动前以零速度对齐舵轮、运行时使用180°等效和轮速反号,但没有根据整段轨迹和每车约束自主求解β的统一规划过程。给定简单蟹行动作时,它与新版固定β可能产生相同的实际轮子姿态和车辆运动。
- 旧版自动 `FleetCurveWalk``FleetCrabWalk` 会先以零速度下发初始GCP角,等待成员新鲜、布局正确、命令可行、舵轮到位和从车应用新序列后才开始运动;原地旋转通过 `RotateWheelsAligned``FleetMotionReleased` 做整队释放。普通手动入口仍有 `SendMotion` 本车舵轮未对齐时速度置零的门控,但不保证与自动动作相同的车队级同步屏障。
+13 -1
View File
@@ -36,6 +36,17 @@
`FleetState.SampleTimestampSeconds` 表示主车/协调器生成该车队状态快照时的本机单调时间,不是Detour全局时间。各成员电脑的本机时钟和Detour `tick` 当前不能直接互相比较;未来接收层应另行保存来源时间并完成新鲜度和时间对齐。
### `FleetLayoutCapture`
文件:`MultiWheelC/Fleet/FleetLayoutCapture.cs`
- `FleetMemberPose`:用于布局采集的车号和成员世界位姿输入。
- `FleetLayoutCaptureResult`:同时返回采集时刻的 `FleetPoseInWorld` 和固定的 `FleetLayout`;车队当前世界位姿不存入布局。
- `Capture(members, leaderVehicleId)`:车队原点X/Y取成员车体中心的算术平均,Yaw取主车Yaw,并通过 `inverse(FleetPoseInWorld) ∘ VehiclePoseInWorld` 得到每车 `PoseInFleet`
- 空成员、非法或重复车号、非有限位姿、主车不存在均拒绝采集;主车缺失时不使用其他车辆降级代替。
该接口是纯几何计算,调用者必须在外部保证成员位姿处于同一世界坐标系,并完成夹紧、静止、数据新鲜度和时间对齐检查;布局的存储与原子激活也不属于该类。
## 轨迹契约
文件:`MultiWheelC/Trajectory/`
@@ -133,7 +144,7 @@ Vβ = cos(β)·Vx_body + sin(β)·Vy_body
状态暂时不可用时,外层调用 `PauseForUnavailableState()` 保留当前轨迹与投影连续性;明确失败或取消分别使用 `Fail()``Cancel()`
`ParkingGeometricController` 是单车适配层,负责读取 `IVehicleStateProvider` 并通过 `GcpCommandExecutor` 发送实体底盘命令。`FleetController` 是车队虚拟中心适配层,使用 `FleetState.FleetPoseInWorld``TwistAtFleetOriginInFleet` 调用同一核心,再将GCP结果转换为车队原点处的 `FleetMotionCommand`
`ParkingGeometricController` 是单车适配层,负责读取 `IVehicleStateProvider` 并通过 `GcpCommandExecutor` 发送实体底盘命令。`FleetController` 是车队虚拟中心适配层,使用 `FleetState.FleetPoseInWorld``TwistAtFleetOriginInFleet` 调用同一核心。构造参数 `motionDirectionInFleetRadians` 定义固定的 `β_fleet`:核心按该方向投影实际纵向速度,GCP结果先解释为运动坐标系Twist,再通过 `R(β_fleet)` 转换成车队坐标系下、车队原点处的 `FleetMotionCommand``β_fleet=0` 保持常规前向语义;当前控制器不负责运行中切换β
当前速度闭环和执行边界的语义并不完全相同:纵向PID与Stanley实际速度分母使用 `Vβ`(Stanley也可按配置改用参考速度),而 `GcpMotionCommand.SpeedMetersPerSecond` 和旧版 `SendMotion.speed` 表示带行驶方向符号的车体中心平移速度模长。正常圆弧理想跟踪时 `Vy=0`,两者相等;只有横向误差共同转角产生非零 `Vy` 时,模长与 `Vβ` 才相差余弦因子。当前最大命令速度仍限制最终发送的模长。
@@ -198,6 +209,7 @@ Vrear = (Vx, Vy - ωR)
## M/C IO与MCU边界
- C层 `PilotDefinition` 和M层 `DiverCartDefinition` 使用 `[AsUpperIO]`/`[AsLowerIO]` 对齐夹臂命令、驱动使能、位置反馈和车号等字段。
- M层 `WheelSpeedDiagnosticLogger` 每次记录生成 `_can.csv``_snapshot.csv`:前者按CAN回调时刻保存八电机速度/位置与四舵角事件,后者按最多50Hz保存目标/实际舵角、目标角速度、PID/前馈/合成差速、限幅前后电机命令、速度/位置/电流反馈及各事件的本机单调时间、序号和数据年龄。MATLAB辨识时可使用 `TargetTh` 作为参考、`TotalDiff``Sent*` 作为执行输入、`ActualTh` 作为输出;左右轮公共/差速通道由方向统一后的左右命令和反馈在分析侧组合。
- `DiverCartDefinition.CommunicationInit()` 默认通过Windows `COM4``1,000,000 baud` 打开MCU桥;`MCUPort` 是可配置初始化参数。
- MCU内部配置为逻辑端口0CAN `500,000 bit/s`;逻辑端口13:串口 `9,600 bit/s``MCURoutine.BatteryPortIndex = 3` 指MCU桥逻辑端口,不等同于Windows `COM3`
- CAN命令/反馈范围集中在 `MCURoutine.cs`:驱动命令 `0x2010x20A`,速度/位置反馈 `0x2810x28A`,状态 `0x1810x18A`,舵角 `0x18B0x18E`,远程帧 `0x7010x70A`
+9 -7
View File
@@ -1,6 +1,6 @@
# 当前进展
更新日期:2026-08-21。这里只保存当前状态,不作为完整开发历史。
更新日期:2026-08-24。这里只保存当前状态,不作为完整开发历史。
## 已完成/已接入
@@ -21,7 +21,7 @@
- 停车控制参数集中到 `Configuration/PilotConfig.ParkingControl.cs`
- `PathTrackingContext` 已解除对单车 `VehicleState` 的依赖;`PathTrackingCore` 统一单车与车队的投影、保护/终点策略、横纵向控制和GCP分配,`ParkingGeometricController` 保留单车状态读取与实体命令执行职责。
- `MultiWheelC.Tests` 已提供不依赖实车的Stanley前进/倒车横向符号回归,8个场景通过;该项目不进入正式解决方案和打包脚本。
- `Shared/Fleet` 已加入不可变 `FleetLayout`、成员/车队命令模型和确定性 `FleetKinematics``MultiWheelC/Fleet`加入虚拟中心 `FleetState` 和复用 `PathTrackingCore` 的纯计算 `FleetController`。6个车队控制周期场景和4个刚体分解场景通过
- `Shared/Fleet` 已加入不可变 `FleetLayout`、成员/车队命令模型和确定性 `FleetKinematics``MultiWheelC/Fleet`具备 `FleetLayoutCapture``FleetStateEstimator`、固定 `β_fleet``FleetController``FleetMemberCommandCorrector``FleetCoordinator``FleetPreparationCoordinator``FleetMemberAgent`。这些组件覆盖布局采集、车队中心/成员误差估计、中心轨迹闭环、统一速度缩放、刚体分解、小范围成员纠偏、成员β准备屏障和本车命令执行边界,但尚未由正式车队任务运行入口贯通
- 本次建立工作区/项目AGENTS导航和 `docs/` 按需知识库。
以上表示代码入口存在,不表示全部实车工况已经验收。
@@ -32,14 +32,15 @@
- 暂时冻结普通运动跳变阈值和30°/s、40°/s²自转参数,等待Detour接口语义后再决定是否实施自转结束后的条件化仅位置连续化或调整航向恢复策略。
- Detour对接最小问题已整理到 `docs/detour-information-checklist.md`,不要求取得源码。
- 验证非零β运动系,当前已有45°蟹行直线入口;曲线蟹行仍需设计实验。
- 多车共同搬运已完成布局模型、虚拟中心状态、虚拟中心轨迹闭环和纯刚体速度分解;下一步处理夹紧后布局采集/原子激活、车队状态估计、通信和安全协调,并把成员命令接入各车 `SendBodyTwist()`。QP/HQP不作为第一版前置条件。
- 多车共同搬运的核心算法和本车执行组件已基本具备,当前重点不再是增加孤立算法文件,而是建立完整车队任务运行链:布局激活→β准备→全员Ready→统一激活→周期状态估计与协调→安全门控→成员命令分发→完成/故障/取消。没有这层调用者时,`FleetCoordinator` 的零速输出或任何独立安全判定都不会自动让实车停车。QP/HQP不作为第一版前置条件。
- β在多车中定位为单车执行坐标系而非车队核心优化量:常规、斜行和横移动作先确定车队主要滚动方向,各车按布局朝向换算本地β,停车预对齐并经车队同步屏障统一释放。轨迹级β搜索只作为机械余量或复杂方向变化下的后续增强。
## 阻塞/待确认
- Clumsy/Medulla正式宿主、插件部署和配置持久化说明未纳入仓库。
- 完整停车业务流程和验收指标未确认。
- 多车通信协议、统一时间轴、车队参考点选取、夹紧后布局采集方法、刚体误差阈值和故障降级策略未确认;已确认运行布局应在夹紧后生成不可变快照并由上层整体激活。
- 多车通信协议、统一时间轴、成员状态实际采集方式、布局原子激活接口、刚体误差实车阈值、夹紧/报警状态来源和故障降级策略未确认;车队参考点和纯几何采集方法已经确定,运行布局应在夹紧后生成不可变快照并由上层整体激活。
- 实际部署为每车独立电脑。主车需要成员状态接收和命令分发,从车必须具备本地命令超时停车;仅依赖主车广播停止不能覆盖通信中断场景。
- 最新实车实验数据对控制周期与舵轮滞后的结论尚未沉淀为可复核结果。
- Detour `l_step` 精确定义、显式重定位/坐标重置状态和部署端MDCS恢复策略待确认;当前不能把 `l_step<4` 当作唯一有效性条件。
- Detour `getCartLocation()` 的位姿坐标系、`tick` 采样/解算/发布语义、是否已有独立连续里程计或定位状态接口,以及部署版本和实际里程计/SLAM配置待确认。
@@ -52,6 +53,7 @@
2. 在Detour信息返回前不继续全局放宽状态估计边界,也不提高自转角速度/角加速度;现有偶发定位不可用保持安全停车。
3. 为轮组里程计自转CSV补充请求角度、内部积分角、完成/超时/手动停止原因,按固定目标角重复验证误差和重复性;绝对航向任务继续保留Detour模式,不用轮组积分冒充世界航向。
4. 为轨迹插值/投影、坐标变换、状态跳变候选和终点策略继续补充不依赖宿主的数学回归测试。
5. 设计车队建立生命周期:预设布局引导就位,夹紧静止后同步采集成员位姿,创建并原子激活新的 `FleetLayout`,松开后清除;车队参考系和采样同步方法需先明确
6. 建立车队状态与执行边界:将时间对齐后的成员状态聚合为 `FleetState`,把 `FleetKinematics` 的成员命令接入各车 `SendBodyTwist()`;通信、成员纠偏和底盘发送不塞回 `PathTrackingCore`,也不直接启用 `#if false` 旧多车代码
7. 接入通信前定义车队状态时间对齐、心跳/命令有效期、共同速度缩放、成员故障整队停车和舵轮准备同步屏障
5. 先建立车队任务运行入口,把布局原子激活`FleetPreparationCoordinator``FleetCoordinator` 和成员执行结果串成明确的生命周期;不要再增加没有运行消费者的独立安全判定器
6. 定义最小通信数据契约:成员状态、成员准备/执行状态、任务号、主车命令、心跳和命令有效期。无线串口初始化可后接,但运行层不能假设主车能直接调用另一台电脑上的 `FleetMemberAgent`
7. 接入成员状态实际来源和主车接收时间轴,形成 `FleetMemberStateSample[]`;再把 `FleetCoordinator` 输出按车号分发到各车 `FleetMemberAgent.Execute()`
8. 在真实执行链内实现安全门控:可恢复状态下持续下发零速并保留任务;硬故障时锁存任务失败、整队停止;每辆从车独立实现命令超时停车。随后补充无通信模拟的端到端测试,再进行低速双车实车验证。