2026-06-14 11:19:15 +08:00
|
|
|
|
# StandardScene 开发指南
|
|
|
|
|
|
|
|
|
|
|
|
## 1. 项目定位
|
|
|
|
|
|
|
2026-06-26 15:00:53 +08:00
|
|
|
|
`StandardScene` 是一个由 `SimpleLite.exe`(CycleGUI 应用)宿主加载的场景插件库,已拆分为「基座 + 4 个卫星」共 5 个插件 DLL(基座输出 `StandardScene.dll`),不是独立 EXE。仓库主要面向 AGV/AMR 场内调度与联动控制,覆盖:
|
2026-06-14 11:19:15 +08:00
|
|
|
|
|
|
|
|
|
|
- 搬运任务与环线任务
|
|
|
|
|
|
- 区域流控与交通互锁
|
|
|
|
|
|
- 充电策略与充电桩管理
|
|
|
|
|
|
- 门禁联动与安全信号
|
|
|
|
|
|
- HTTP / MQTT / Modbus 等外围接口
|
|
|
|
|
|
|
|
|
|
|
|
## 2. 技术与运行方式
|
|
|
|
|
|
|
|
|
|
|
|
| 项目项 | 说明 |
|
|
|
|
|
|
| --- | --- |
|
|
|
|
|
|
| 语言 | `C#` |
|
2026-06-26 15:00:53 +08:00
|
|
|
|
| 框架 | `net8.0-windows` |
|
|
|
|
|
|
| 工程类型 | `Library`(基座 + 4 卫星,共 5 个插件 DLL) |
|
|
|
|
|
|
| 宿主 | `SimpleLite.exe`(CycleGUI 应用) |
|
|
|
|
|
|
| 界面技术 | 由 WinForms 迁移到 CycleGUI(宿主同栈);`DeliveryViewer` 已迁移 |
|
2026-06-14 11:19:15 +08:00
|
|
|
|
| 关键入口 | `MissionType`、`CarType`、`WebApi.cs` |
|
|
|
|
|
|
|
|
|
|
|
|
### 本机依赖
|
|
|
|
|
|
|
2026-06-26 15:00:53 +08:00
|
|
|
|
各 `.csproj` 的 `HintPath` 指向以下依赖(宿主产物需先构建 Simple 解决方案):
|
2026-06-14 11:19:15 +08:00
|
|
|
|
|
2026-06-26 15:00:53 +08:00
|
|
|
|
- `D:\MDCS\Dependencies\Commons\CommonUsage.dll`、`MDCSToolBox.dll`、`CycleGUI.dll`
|
|
|
|
|
|
- `..\Simple\SimpleLite\bin\Debug\SimpleLite.dll`、`LessokajiWeaverUtilities.dll`
|
|
|
|
|
|
- `..\Simple\SimpleCore\bin\Debug\netstandard2.0\SimpleCore.dll`
|
2026-06-14 11:19:15 +08:00
|
|
|
|
|
|
|
|
|
|
### 构建与运行
|
|
|
|
|
|
|
2026-06-26 15:00:53 +08:00
|
|
|
|
> 必须先构建宿主依赖,否则会出现 `SimpleCore` 版本不匹配等编译错误。
|
|
|
|
|
|
|
|
|
|
|
|
1. 先构建宿主:`dotnet build Simple\SimpleLite\SimpleLite.csproj`(会一并构建 `SimpleCore` 项目)
|
|
|
|
|
|
2. 打开 `StandardScene.sln`,编译 `Debug|x64` 或 `Release|x64`
|
|
|
|
|
|
3. 编译后 `Directory.Build.targets` 会把 5 个插件 DLL(+ PDB + `*.scene.json`)复制到 `build\plugins`
|
|
|
|
|
|
4. 将 `build\plugins` 部署到 `SimpleLite.exe` 工作目录下的 `plugins\`,运行 `SimpleLite.exe`
|
2026-06-14 11:19:15 +08:00
|
|
|
|
|
|
|
|
|
|
## 3. 目录结构
|
|
|
|
|
|
|
|
|
|
|
|
| 路径 | 作用 |
|
|
|
|
|
|
| --- | --- |
|
|
|
|
|
|
| `CarTypes\` | 各车型与协议适配 |
|
|
|
|
|
|
| `Chained\` | 搬运任务、链式调度、环线任务 |
|
|
|
|
|
|
| `Charge\` | 充电策略、充电桩管理 |
|
|
|
|
|
|
| `ChargeStationType\` | 具体充电桩类型 |
|
|
|
|
|
|
| `InterLock\` | 区域互锁、交通控制 |
|
|
|
|
|
|
| `Scheduler\` | 心跳、安全、区域流控等后台 Mission |
|
|
|
|
|
|
| `ExtendDevice\Door\` | 门禁设备接入与联动 |
|
|
|
|
|
|
| `Model\` | 任务、配置、地图等数据模型 |
|
|
|
|
|
|
| `TCP\` / `Utils\` | TCP、JSON、Web API、Modbus 工具 |
|
|
|
|
|
|
| `Commons.cs` | 通用字段、标签、选车、路径辅助 |
|
|
|
|
|
|
| `WebApi.cs` | 对外 HTTP 接口 |
|
|
|
|
|
|
|
|
|
|
|
|
## 4. 运行时架构
|
|
|
|
|
|
|
|
|
|
|
|
运行链路通常是:
|
|
|
|
|
|
|
|
|
|
|
|
1. 宿主启动并扫描 `build\plugins`
|
|
|
|
|
|
2. 加载 `StandardScene.dll`
|
|
|
|
|
|
3. 通过特性反射识别 `MissionType` 与 `CarType`
|
|
|
|
|
|
4. 启动具体 Mission
|
|
|
|
|
|
5. Mission 调用 `SimpleLib`、`TrafficControl`、`SegmentPlan` 等核心能力
|
|
|
|
|
|
6. 车辆状态、交通状态、充电状态在运行时持续联动
|
|
|
|
|
|
|
|
|
|
|
|
## 5. 核心模块理解
|
|
|
|
|
|
|
|
|
|
|
|
### `Scheduler`
|
|
|
|
|
|
|
|
|
|
|
|
这是最适合入门的目录。
|
|
|
|
|
|
|
|
|
|
|
|
- `HeartBeatMission.cs`:最小线程式 Mission
|
|
|
|
|
|
- `RegionalTrafficControlMission.cs`:事件订阅型 Mission
|
|
|
|
|
|
- `SecuritySignalMission.cs`:安全信号类任务
|
|
|
|
|
|
|
|
|
|
|
|
### `Chained`
|
|
|
|
|
|
|
|
|
|
|
|
主业务调度的核心区域。
|
|
|
|
|
|
|
2026-06-26 15:00:53 +08:00
|
|
|
|
- `ChainedDeliveryMission.cs`:搬运任务总控(旧版 `AbstractChainedDeliveryMission.cs` 已删除)
|
2026-06-14 11:19:15 +08:00
|
|
|
|
- `TransportMission.cs`:常规运输 Mission
|
|
|
|
|
|
- `AbstractLoopMission.cs`:环线任务骨架
|
|
|
|
|
|
- `LoopMission.cs`:环线业务实例
|
|
|
|
|
|
|
|
|
|
|
|
### `Charge`
|
|
|
|
|
|
|
|
|
|
|
|
负责能量与充电协同。
|
|
|
|
|
|
|
|
|
|
|
|
- `AbstractChargeLogicMission.cs`
|
|
|
|
|
|
- `StandardChargeMission.cs`
|
|
|
|
|
|
- `ChargeStationDataService.cs`
|
|
|
|
|
|
- `ChargeStationManagementExample.cs`
|
|
|
|
|
|
|
|
|
|
|
|
### `CarTypes`
|
|
|
|
|
|
|
|
|
|
|
|
负责车型与协议适配。
|
|
|
|
|
|
|
|
|
|
|
|
- `VDA5050Car.cs`
|
|
|
|
|
|
- `Forklift.cs`
|
|
|
|
|
|
- `Kiva.cs`
|
|
|
|
|
|
- `MultiVehicleCar.cs`
|
|
|
|
|
|
- `MasterMQTTCommunication.cs`
|
|
|
|
|
|
|
|
|
|
|
|
### `WebApi.cs`
|
|
|
|
|
|
|
|
|
|
|
|
对外暴露 HTTP 能力,常见路由包括:
|
|
|
|
|
|
|
|
|
|
|
|
- `/car/createTask`
|
|
|
|
|
|
- `/car/getAllCars`
|
|
|
|
|
|
- `/car/goSite`
|
|
|
|
|
|
- `/map/getMap`
|
|
|
|
|
|
- `/task/getTask`
|
|
|
|
|
|
- `/mission_reflection/get_mission_list`
|
|
|
|
|
|
|
|
|
|
|
|
## 6. 配置文件
|
|
|
|
|
|
|
|
|
|
|
|
| 文件 | 作用 |
|
|
|
|
|
|
| --- | --- |
|
|
|
|
|
|
| `Config\traffic.json` | 交通互锁 / 区域配置 |
|
|
|
|
|
|
| `Config\ChargeStations.json` | 充电桩定义 |
|
|
|
|
|
|
| `Config\ChargeStrategyConfig.json` | 充电策略 |
|
|
|
|
|
|
| `Config\AlarmConfigs.json` | 报警配置 |
|
|
|
|
|
|
| `DoorConfig.json` | 门禁配置 |
|
|
|
|
|
|
| `tasklist.json` | 环线任务配置 |
|
|
|
|
|
|
| `simple.json` | 宿主基础配置 |
|
|
|
|
|
|
|
|
|
|
|
|
除了 JSON 文件,本仓库还大量使用 `fields` 与 `tags` 作为轻量配置入口,尤其是站点与车辆行为控制。
|
|
|
|
|
|
|
|
|
|
|
|
## 7. 快速开始案例
|
|
|
|
|
|
|
|
|
|
|
|
### 案例 A:新增一个最小 Mission
|
|
|
|
|
|
|
|
|
|
|
|
最推荐的新手入门案例,直接参考 `Scheduler\HeartBeatMission.cs`。
|
|
|
|
|
|
|
|
|
|
|
|
```csharp
|
|
|
|
|
|
using System.Threading;
|
|
|
|
|
|
using Newtonsoft.Json;
|
2026-06-26 15:00:53 +08:00
|
|
|
|
using SimpleLite.RCS;
|
2026-06-14 11:19:15 +08:00
|
|
|
|
using SimpleCore;
|
|
|
|
|
|
|
|
|
|
|
|
namespace StandardScene.Scheduler
|
|
|
|
|
|
{
|
|
|
|
|
|
[MissionType(Name = "Hello Mission", editor = typeof(HelloMission))]
|
|
|
|
|
|
[I18N.DocumentTranslation(Name = "Hello Mission", locale = "en")]
|
|
|
|
|
|
public class HelloMission : Mission
|
|
|
|
|
|
{
|
|
|
|
|
|
[JsonIgnore] private bool _started;
|
|
|
|
|
|
[JsonIgnore] private Thread _thread;
|
|
|
|
|
|
|
|
|
|
|
|
public static Mission Create()
|
|
|
|
|
|
{
|
|
|
|
|
|
return new HelloMission();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public override void Execute()
|
|
|
|
|
|
{
|
|
|
|
|
|
if (_started) return;
|
|
|
|
|
|
_started = true;
|
|
|
|
|
|
status.status = "已启动";
|
|
|
|
|
|
|
|
|
|
|
|
_thread = new Thread(() =>
|
|
|
|
|
|
{
|
|
|
|
|
|
int count = 0;
|
|
|
|
|
|
while (_started)
|
|
|
|
|
|
{
|
|
|
|
|
|
Thread.Sleep(1000);
|
|
|
|
|
|
count++;
|
|
|
|
|
|
status.status = $"tick:{count}";
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
_thread.Start();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public void Stop()
|
|
|
|
|
|
{
|
|
|
|
|
|
_started = false;
|
|
|
|
|
|
status.status = "已停止";
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
#### 关键提醒
|
|
|
|
|
|
|
2026-06-26 15:00:53 +08:00
|
|
|
|
当前工程已是 SDK 风格 `.csproj`(`net8.0-windows`),目录下的 `.cs` 文件会被自动包含,无需再手工添加 `<Compile Include>`。新增任务/车型/驱动后,记得补上对应特性(`[MissionType]`、`[CarType]`、`[DoorType]` 等)与静态 `Create()`,否则宿主反射不到。
|
2026-06-14 11:19:15 +08:00
|
|
|
|
|
|
|
|
|
|
#### 验证方式
|
|
|
|
|
|
|
2026-06-26 15:00:53 +08:00
|
|
|
|
1. 编译解决方案并把插件部署到宿主 `plugins\`
|
|
|
|
|
|
2. 运行 `SimpleLite.exe`
|
2026-06-14 11:19:15 +08:00
|
|
|
|
3. 启动 `Hello Mission`
|
|
|
|
|
|
4. 观察 `status.status` 是否变成 `tick:1`、`tick:2`
|
|
|
|
|
|
|
|
|
|
|
|
### 案例 B:配置区域流控
|
|
|
|
|
|
|
|
|
|
|
|
该案例对应 `Scheduler\RegionalTrafficControlMission.cs`。
|
|
|
|
|
|
|
|
|
|
|
|
给区域内站点添加字段:
|
|
|
|
|
|
|
|
|
|
|
|
```text
|
|
|
|
|
|
Region1 = 1
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
含义是:
|
|
|
|
|
|
|
|
|
|
|
|
- 站点属于 `Region1`
|
|
|
|
|
|
- `Region1` 最多允许 1 台车进入
|
|
|
|
|
|
|
|
|
|
|
|
#### 实验步骤
|
|
|
|
|
|
|
|
|
|
|
|
1. 给同一区域内多个站点加上 `Region1=1`
|
|
|
|
|
|
2. 启动“区域流量监控” Mission
|
|
|
|
|
|
3. 让两台车先后进入该区域
|
|
|
|
|
|
4. 观察第二台车是否被阻止
|
|
|
|
|
|
5. 查看 Mission 状态中的区域统计与拦截次数
|
|
|
|
|
|
|
|
|
|
|
|
## 8. 开发工作流建议
|
|
|
|
|
|
|
|
|
|
|
|
1. 先判断功能属于 `Scheduler`、`Chained`、`Charge`、`CarTypes` 还是 `WebApi.cs`
|
|
|
|
|
|
2. 找最接近的现有类作为模板
|
|
|
|
|
|
3. 明确配置入口是 JSON、`fields` 还是 `tags`
|
|
|
|
|
|
4. 补齐日志、状态与停止逻辑
|
|
|
|
|
|
5. 确认文件已加入工程
|
|
|
|
|
|
6. 编译后在宿主里验证是否能被识别
|
|
|
|
|
|
|
|
|
|
|
|
## 9. 调试建议
|
|
|
|
|
|
|
|
|
|
|
|
优先观察这些点:
|
|
|
|
|
|
|
|
|
|
|
|
- `status.status`
|
|
|
|
|
|
- `Diagnosis.Post` / `Diagnosis.Log`
|
|
|
|
|
|
- `car.status.pendingLocks`
|
|
|
|
|
|
- `car.status.holdingLocks`
|
|
|
|
|
|
- 站点 / 车辆的 `fields` 与 `tags`
|
|
|
|
|
|
- `WebApi.cs` 中的实际路由
|
|
|
|
|
|
|
|
|
|
|
|
推荐调试方式:
|
|
|
|
|
|
|
2026-06-26 15:00:53 +08:00
|
|
|
|
- 以 `SimpleLite.exe` 作为外部程序启动调试
|
2026-06-14 11:19:15 +08:00
|
|
|
|
- 或先运行宿主,再附加进程
|
|
|
|
|
|
|
|
|
|
|
|
## 10. 常见坑
|
|
|
|
|
|
|
|
|
|
|
|
### 新增 Mission 看不到
|
|
|
|
|
|
|
|
|
|
|
|
优先检查:
|
|
|
|
|
|
|
|
|
|
|
|
- 是否加了 `MissionType`
|
|
|
|
|
|
- 是否有静态 `Create()`
|
2026-06-26 15:00:53 +08:00
|
|
|
|
- 是否复制到了 `build\plugins` 并部署到宿主 `plugins\`
|
|
|
|
|
|
- 卫星插件是否已在 `active-scenes.json` 中启用对应场景
|
2026-06-14 11:19:15 +08:00
|
|
|
|
|
|
|
|
|
|
### 区域流控不生效
|
|
|
|
|
|
|
|
|
|
|
|
优先检查:
|
|
|
|
|
|
|
|
|
|
|
|
- 字段名是否以 `Region` 开头
|
|
|
|
|
|
- 字段值是否能解析为整数
|
|
|
|
|
|
- Mission 是否已启动
|
|
|
|
|
|
|
|
|
|
|
|
### 任务不执行
|
|
|
|
|
|
|
|
|
|
|
|
优先检查:
|
|
|
|
|
|
|
|
|
|
|
|
- 车辆是否在线
|
|
|
|
|
|
- 路径是否可达
|
|
|
|
|
|
- 是否被互锁、流控或门控拦截
|
|
|
|
|
|
- 是否已有标签将车辆标记为忙碌或充电中
|