Restructure into DiffWheel/MultiWheel folders, add DiffWheelC and MultiWheelC with MovementTests, FleetRemote multi-vehicle manual sync, deploy templates, and documentation. Update dependency paths to D:\MDCS\Release and mirror motor feedback in MotorRoutine for simulation. Co-authored-by: Cursor <cursoragent@cursor.com>
5.2 KiB
多车联动(MultiVehicleSync)算法原理
本文说明 MDCSToolBox 中 N 车联动的架构与几何原理。Tutorial MultiWheelC 与产品 StandardMultiWheelLifterC 均继承 MultiWheelPilotDefinition,调用 InitMultiVehicleCoordination() 启用同步。
1. 总体架构
每台 AGV 运行 Detour + Medulla (M) + Clumsy (C):
| 实例 | Detour shareObjectTag |
Medulla/Clumsy soTag |
Clumsy 角色 | MultiVehicleMasterEndpoint |
Clumsy port |
Detour HTTP | CarNum |
|---|---|---|---|---|---|---|---|
| AGV1 | Multi1 |
Multi1 |
主车 master | / |
8008 | 4321 | 1 |
| AGV2 | Multi2 |
Multi2 |
从车 slave | 127.0.0.1:8008 |
8009 | 4421 | 2 |
Medulla web API(与 Clumsy 车队同步端口无关):AGV1 8007,AGV2 8108(单机部署时 Medulla #2 不可占用 8008,该端口留给 Clumsy 主车)。
同机隔离(Core 层)
- Detour 写入
DObject("DetourPos{shareObjectTag}");Clumsy 读取DObject("DetourPos{soTag}"),tag 必须一致。 - Clumsy 通过
detourHost/detourPort(clumsyconsole.json或clumsy.json)访问对应 Detour HTTP 端口(4321/4421)。 - 每台 Clumsy 绑定独立
WebAPI.port(8008/8009),register/notify 使用VehicleSyncInfo.Port寻址。
M 与 C 通过 CartActivator 共享 DObject(MedullaCartUpperIO{tag}),不直接 DLL 调用。
从车 --GET /multi-vehicle-register--> 主车:8008 (上报本车位姿、layout、Port)
主车 --GET /multi-vehicle-notify----> 从车:8009 (广播车队中心、fleet 命令、完整 fleet 状态)
2. 数据模型
定义于 MDCSToolBox/Clumsy/Pilot/MultiWheel/VehicleSyncModels.cs。
2.1 VehicleSyncInfo(从车 → 主车)
| 字段 | 含义 |
|---|---|
Master |
是否主车 |
Ip / Port |
本车同步端点(notify 寻址) |
PosAvailable |
本车 Detour/SLAM 是否有效 |
X/Y/Th |
本车世界位姿(mm, deg) |
LayoutX/Y/Th |
本车在车队坐标系下的 固定 slot |
Aligned |
本车互识别/精度是否满足(见 §4) |
2.2 VehicleSyncNotification(主车 → 从车)
除原 fleet 命令外,主车广播 CenterX/Y/Th(世界系车队中心)、SyncTh/SyncDistance、完整 Fleet 快照等。
3. 编队几何与车队中心
3.1 编队布局(双车)
布局由 TestCarSyncDistance 与 TestCarSyncTh 唯一确定(不再有独立 slot 表):每车相对车队中心沿编队方向对称分布于 ±TestCarSyncDistance/2,从车朝向额外翻转 180°。实现见 GetLayoutPose。TestCarSyncDistance 同时是检测环(detectDistance = TestCarSyncDistance - DeltaDetectCenter)与 SLAM 位姿环的唯一间距来源,二者据此自洽。
3.2 车队中心反推(非位姿平均)
世界系中心 不是 对各车 X/Y/Th 取平均,而是由 当前 PosAvailable==true 的车 按固定 slot 反推:
Transform2D(fleetCenter, layoutSlot) = carWorldPose
⇒ fleetCenter = Transform2D(carWorld, -layoutSlot) // 实现见 InferFleetCenterFromCar
- 多台有效车:对各车反推的中心取平均(理论上应一致,差异可作互检)。
- 零台有效车:无世界系中心 → 手动模式仍可通过互识别保持编队;自动模式门控拒绝(见 §5)。
4. 互识别接口(插件实现)
基类 MultiWheelPilotDefinition 提供虚方法:
protected virtual (bool Valid, float Dx, float Dy, float Dth) DetectNeighborBias(float detectDistance);
- 基类:
MultiVehicleUseDetect门控 → 计算Aligned→SendMotion(localCompensate*)。 - 具体检测(雷达名、两腿/反光板等)由车体插件重写。
- 产品:
StandardMultiWheelLifterC→VehicleMoverHelper.GetSyncBias - Tutorial:默认
Valid=false(无检测硬件时可纯靠手动+SLAM)
- 产品:
5. 手动 / 自动门控
| 模式 | 条件 |
|---|---|
| 手动 | 始终可用;可无 Detour,靠 DetectNeighborBias 纠正 |
| 自动 | 主车要求 fleet 中 至少 1 台 PosAvailable;否则 toast 拒绝并清零 MultiVehicleAutoEnabled |
6. 主循环(默认 50ms)
逻辑位于 MultiWheelPilotDefinition.MultiVehicle.cs 的 TickMultiVehicle:
- 判断 master/slave、手动/自动是否启用
- 读取本车 SLAM(若
PosAvailable) - 主车:计算 fleet 命令;从 notification 同步
GetLayoutPose→ 本车布局位姿(由TestCarSyncDistance/TestCarSyncTh推导)DetectNeighborBias(可选)→ 互识别补偿- 有有效中心时 SLAM
posBias补偿 SendMotion(fleetVx, FrontTh, RearTh, localCompensate*)- master:register 汇总 + notify 各从车(按
Ip:Port,跳过自身CarNum)
7. 配置文件
见 RunAndDeploy.md:clumsyconsole.json(soTag/port/detour)、clumsy.json(msConf slot/主车端点)、detour.json(shareObjectTag/DetourPort)。
修复与迁移记录见 BugFixes.md。