Files

104 lines
5.2 KiB
Markdown
Raw Permalink Normal View History

# 多车联动(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 调用。
```text
从车 --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 反推:
```text
Transform2D(fleetCenter, layoutSlot) = carWorldPose
⇒ fleetCenter = Transform2D(carWorld, -layoutSlot) // 实现见 InferFleetCenterFromCar
```
- 多台有效车:对各车反推的中心取平均(理论上应一致,差异可作互检)。
- 零台有效车:无世界系中心 → **手动模式**仍可通过互识别保持编队;**自动模式**门控拒绝(见 §5)。
## 4. 互识别接口(插件实现)
基类 `MultiWheelPilotDefinition` 提供虚方法:
```csharp
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`
1. 判断 master/slave、手动/自动是否启用
2. 读取本车 SLAM(若 `PosAvailable`
3. 主车:计算 fleet 命令;从 notification 同步
4. `GetLayoutPose` → 本车布局位姿(由 `TestCarSyncDistance`/`TestCarSyncTh` 推导)
5. `DetectNeighborBias`(可选)→ 互识别补偿
6. 有有效中心时 SLAM `posBias` 补偿
7. `SendMotion(fleetVx, FrontTh, RearTh, localCompensate*)`
8. masterregister 汇总 + notify 各从车(按 `Ip:Port`,跳过自身 `CarNum`
## 7. 配置文件
见 [RunAndDeploy.md](./RunAndDeploy.md)`clumsyconsole.json`soTag/port/detour)、`clumsy.json`msConf slot/主车端点)、`detour.json`shareObjectTag/DetourPort)。
修复与迁移记录见 [BugFixes.md](./BugFixes.md)。