# StandardScene 开发指南 ## 1. 项目定位 `StandardScene` 是一个由 `SimpleLite.exe`(CycleGUI 应用)宿主加载的场景插件库,已拆分为「基座 + 4 个卫星」共 5 个插件 DLL(基座输出 `StandardScene.dll`),不是独立 EXE。仓库主要面向 AGV/AMR 场内调度与联动控制,覆盖: - 搬运任务与环线任务 - 区域流控与交通互锁 - 充电策略与充电桩管理 - 门禁联动与安全信号 - HTTP / MQTT / Modbus 等外围接口 ## 2. 技术与运行方式 | 项目项 | 说明 | | --- | --- | | 语言 | `C#` | | 框架 | `net8.0-windows` | | 工程类型 | `Library`(基座 + 4 卫星,共 5 个插件 DLL) | | 宿主 | `SimpleLite.exe`(CycleGUI 应用) | | 界面技术 | 由 WinForms 迁移到 CycleGUI(宿主同栈);`DeliveryViewer` 已迁移 | | 关键入口 | `MissionType`、`CarType`、`WebApi.cs` | ### 本机依赖 各 `.csproj` 的 `HintPath` 指向以下依赖(宿主产物需先构建 Simple 解决方案): - `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` ### 构建与运行 > 必须先构建宿主依赖,否则会出现 `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` ## 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` 主业务调度的核心区域。 - `ChainedDeliveryMission.cs`:搬运任务总控(旧版 `AbstractChainedDeliveryMission.cs` 已删除) - `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; using SimpleLite.RCS; 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 = "已停止"; } } } ``` #### 关键提醒 当前工程已是 SDK 风格 `.csproj`(`net8.0-windows`),目录下的 `.cs` 文件会被自动包含,无需再手工添加 ``。新增任务/车型/驱动后,记得补上对应特性(`[MissionType]`、`[CarType]`、`[DoorType]` 等)与静态 `Create()`,否则宿主反射不到。 #### 验证方式 1. 编译解决方案并把插件部署到宿主 `plugins\` 2. 运行 `SimpleLite.exe` 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` 中的实际路由 推荐调试方式: - 以 `SimpleLite.exe` 作为外部程序启动调试 - 或先运行宿主,再附加进程 ## 10. 常见坑 ### 新增 Mission 看不到 优先检查: - 是否加了 `MissionType` - 是否有静态 `Create()` - 是否复制到了 `build\plugins` 并部署到宿主 `plugins\` - 卫星插件是否已在 `active-scenes.json` 中启用对应场景 ### 区域流控不生效 优先检查: - 字段名是否以 `Region` 开头 - 字段值是否能解析为整数 - Mission 是否已启动 ### 任务不执行 优先检查: - 车辆是否在线 - 路径是否可达 - 是否被互锁、流控或门控拦截 - 是否已有标签将车辆标记为忙碌或充电中