<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="zh-Hans-CN">
	<id>https://wiki2.lessokaji.com/index.php?action=history&amp;feed=atom&amp;title=%E5%A6%82%E4%BD%95%E5%9F%BA%E4%BA%8ESimpleCore%E6%A0%B8%E5%BF%83%E5%BA%93%E8%BF%9B%E8%A1%8C%E8%B0%83%E5%BA%A6%E7%B3%BB%E7%BB%9F%E5%BC%80%E5%8F%91</id>
	<title>如何基于SimpleCore核心库进行调度系统开发 - 版本历史</title>
	<link rel="self" type="application/atom+xml" href="https://wiki2.lessokaji.com/index.php?action=history&amp;feed=atom&amp;title=%E5%A6%82%E4%BD%95%E5%9F%BA%E4%BA%8ESimpleCore%E6%A0%B8%E5%BF%83%E5%BA%93%E8%BF%9B%E8%A1%8C%E8%B0%83%E5%BA%A6%E7%B3%BB%E7%BB%9F%E5%BC%80%E5%8F%91"/>
	<link rel="alternate" type="text/html" href="https://wiki2.lessokaji.com/index.php?title=%E5%A6%82%E4%BD%95%E5%9F%BA%E4%BA%8ESimpleCore%E6%A0%B8%E5%BF%83%E5%BA%93%E8%BF%9B%E8%A1%8C%E8%B0%83%E5%BA%A6%E7%B3%BB%E7%BB%9F%E5%BC%80%E5%8F%91&amp;action=history"/>
	<updated>2026-05-16T16:12:07Z</updated>
	<subtitle>本wiki上该页面的版本历史</subtitle>
	<generator>MediaWiki 1.40.0</generator>
	<entry>
		<id>https://wiki2.lessokaji.com/index.php?title=%E5%A6%82%E4%BD%95%E5%9F%BA%E4%BA%8ESimpleCore%E6%A0%B8%E5%BF%83%E5%BA%93%E8%BF%9B%E8%A1%8C%E8%B0%83%E5%BA%A6%E7%B3%BB%E7%BB%9F%E5%BC%80%E5%8F%91&amp;diff=1007&amp;oldid=prev</id>
		<title>Artheru：​Initial bilingual draft (auto-published)</title>
		<link rel="alternate" type="text/html" href="https://wiki2.lessokaji.com/index.php?title=%E5%A6%82%E4%BD%95%E5%9F%BA%E4%BA%8ESimpleCore%E6%A0%B8%E5%BF%83%E5%BA%93%E8%BF%9B%E8%A1%8C%E8%B0%83%E5%BA%A6%E7%B3%BB%E7%BB%9F%E5%BC%80%E5%8F%91&amp;diff=1007&amp;oldid=prev"/>
		<updated>2026-05-16T11:26:47Z</updated>

		<summary type="html">&lt;p&gt;Initial bilingual draft (auto-published)&lt;/p&gt;
&lt;p&gt;&lt;b&gt;新页面&lt;/b&gt;&lt;/p&gt;&lt;div&gt;&amp;lt;languages/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 概述 / Overview ==&lt;br /&gt;
MDCS 的车队调度被分为两层：'''SimpleCore'''（核心算法库，包含交管、寻路、包络、可达性、DPS 等内核算法）与 '''SimpleComposer'''（基于 SimpleCore 的 UI 壳层，包含 CAD 工具、可视化、插件宿主）。本页面对开发者：你想自己写一个调度应用（或在 SimpleComposer 之外用 SimpleCore 内核）该如何开始。&lt;br /&gt;
&lt;br /&gt;
MDCS fleet management is split into two layers: '''SimpleCore''' (algorithm library — traffic control, pathfinding, envelopes, reachability, DPS) and '''SimpleComposer''' (a UI shell built on SimpleCore — CAD tool, visualisation, plugin host). This page targets developers writing their own scheduling app on top of SimpleCore, or extending SimpleComposer with a custom car / mission type.&lt;br /&gt;
&lt;br /&gt;
== 何时基于 SimpleCore 开发 / When to use SimpleCore directly ==&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! 场景 / Scenario !! 建议 / Recommendation&lt;br /&gt;
|-&lt;br /&gt;
| 集成进非 SimpleComposer 的现成系统 || 直接用 SimpleCore，把 UI 留给原系统&lt;br /&gt;
|-&lt;br /&gt;
| 给 SimpleComposer 加车型 / 业务 || 写插件在 SimpleComposer 上挂载，不必自己写调度&lt;br /&gt;
|-&lt;br /&gt;
| 算法研究（新交管 / 新寻路） || SimpleCore，作为算法宿主&lt;br /&gt;
|-&lt;br /&gt;
| 单工位单车 || 都不需要，写一个小循环够了&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== 核心抽象 / Core abstractions ==&lt;br /&gt;
=== Car 体系 / Car hierarchy ===&lt;br /&gt;
SimpleCore 把&amp;quot;车&amp;quot;按照 ''是否使用 MDCS 车载系统'' 分为两支：&lt;br /&gt;
SimpleCore splits &amp;quot;cars&amp;quot; into two branches by whether they use the MDCS on-vehicle stack:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! 类 / Class !! 文件 / File !! 用途 / Use&lt;br /&gt;
|-&lt;br /&gt;
| `AbstractCar` || `D:\src\Simple\SimpleCore\PropType\AbstractCar.cs:346` || 调度可见的车的最小契约 / minimal scheduling contract&lt;br /&gt;
|-&lt;br /&gt;
| `Car` || `D:\src\Simple\SimpleComposer\RCS\Car.cs:33` || SimpleComposer 中的&amp;quot;车&amp;quot;基类 / Composer-side base&lt;br /&gt;
|-&lt;br /&gt;
| `ClumsyCar : Car` || `D:\src\Simple\SimpleComposer\RCS\ClumsyCar.cs:34` || 跑 MDCS 车载（Medulla + Clumsy）的车 / runs full MDCS on-vehicle stack&lt;br /&gt;
|-&lt;br /&gt;
| 自评估 `Car`（自定义子类）/ Self-eval `Car` (custom subclass) || 各 vendor 适配代码 / vendor adapters || PLC / 磁导航 / 二维码 类无车载 PC 的车 / cars without on-board MDCS (PLC, magstrip, QR)&lt;br /&gt;
|-&lt;br /&gt;
| `AGVInterface` || `D:\src\Simple\SimpleCore\BasicProps\AGVInterface.cs` || 任务脚本调用的 API / API surface called by mission scripts&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== AGVInterface 与 Queue 机制 ===&lt;br /&gt;
`AGVInterface` 暴露给任务脚本（TopazScript）的核心方法是 `Queue(params Func&amp;lt;Task&amp;gt;[] actions)` —— ''超标量'' 异步流水线：&lt;br /&gt;
&lt;br /&gt;
The core method on `AGVInterface` exposed to mission scripts is `Queue(params Func&amp;lt;Task&amp;gt;[] actions)` — a &amp;quot;super-scalar&amp;quot; async pipeline:&lt;br /&gt;
&lt;br /&gt;
* 每个 Func 是一个 ''行 / row''，按提交顺序进入流水线。&lt;br /&gt;
* 同一行内的代码顺序执行。&lt;br /&gt;
* 上一行未完成前，下一行不会开始 —— 但下一行可在上一行最后一个 await 后立即 schedule，达成宏观流水。&lt;br /&gt;
* `WaitAsync(int pipe)` 让调用方等到指定行完成再继续。&lt;br /&gt;
&lt;br /&gt;
* Each Func is a '''row''' in the pipeline.&lt;br /&gt;
* Code within a row runs sequentially.&lt;br /&gt;
* The next row only starts after the previous row's last await, but its prelude can overlap, giving macro-level pipelining.&lt;br /&gt;
* `WaitAsync(int pipe)` lets the caller wait for a specific row.&lt;br /&gt;
&lt;br /&gt;
=== TryLock / Leave — 交管 / Traffic control ===&lt;br /&gt;
`TryLock(int siteID)` / `Leave(int siteID)` 是 SimpleCore 交管在 ''每个 mission 脚本里''的钩子。任务脚本在进入一个交管区前必须 `TryLock`；离开时 `Leave`。SimpleCore 的内核保证：&lt;br /&gt;
&lt;br /&gt;
`TryLock(siteID)` / `Leave(siteID)` are SimpleCore's traffic-control hooks ''per mission script''. Scripts must `TryLock` before entering a controlled segment and `Leave` on exit. SimpleCore's kernel guarantees:&lt;br /&gt;
&lt;br /&gt;
* 无死锁（DPS 算法，见 [[Special:MyLanguage/DPS调度算法详解|DPS调度算法详解]]）&amp;lt;br /&amp;gt;Deadlock freedom (via DPS — see the DPS page).&lt;br /&gt;
* 公平（按到达顺序授予锁）&amp;lt;br /&amp;gt;Fairness — locks granted in arrival order.&lt;br /&gt;
* 兼容性（同一锁可被声明 ''可兼容车型'' 一起持有）&amp;lt;br /&amp;gt;Compatibility — a lock can be held simultaneously by compatible car types.&lt;br /&gt;
&lt;br /&gt;
== 写一个 ClumsyCar 子类 / Subclassing ClumsyCar ==&lt;br /&gt;
ClumsyCar 用于车上跑完整 MDCS（Clumsy 自动驾驶 + Medulla 硬件抽象）的情况。最小子类骨架：&lt;br /&gt;
&lt;br /&gt;
ClumsyCar is the right base when the vehicle runs the full MDCS stack on-board. Minimal subclass:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;csharp&amp;quot;&amp;gt;&lt;br /&gt;
using SimpleComposer.RCS;&lt;br /&gt;
&lt;br /&gt;
namespace Vendor.Carts&lt;br /&gt;
{&lt;br /&gt;
    [CarType(Name = &amp;quot;MyCart&amp;quot;, Title = &amp;quot;我的车型 / MyCart&amp;quot;)]&lt;br /&gt;
    public class MyCart : ClumsyCar&lt;br /&gt;
    {&lt;br /&gt;
        public MyCart() : base()&lt;br /&gt;
        {&lt;br /&gt;
            conf = &amp;quot;configs/MyCart.config&amp;quot;;&lt;br /&gt;
            api_retries = 3;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        public override async Task actualSendScript(string script)&lt;br /&gt;
        {&lt;br /&gt;
            // 把 TopazScript 通过 HTTP 发到车载 Clumsy 适配器 / POST to on-board Clumsy adapter&lt;br /&gt;
            var url = $&amp;quot;http://{address}:30080/run&amp;quot;;&lt;br /&gt;
            var resp = await HttpClient.PostAsync(url, new StringContent(script));&lt;br /&gt;
            resp.EnsureSuccessStatusCode();&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        public override async Task keepAlive()&lt;br /&gt;
        {&lt;br /&gt;
            // 心跳 + 状态轮询 / heartbeat + status poll&lt;br /&gt;
            var status = await HttpClient.GetStringAsync($&amp;quot;http://{address}:30080/status&amp;quot;);&lt;br /&gt;
            UpdateStatusFromJson(status);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
参考样例（80 行可读完）：`D:\src\cookbook\adaption-reference\法睿兰达\CartAdapters\FY2208008\Scenes\AMRScene\ProjNameCar.cs`。&lt;br /&gt;
Reference (80 lines, easy to read end-to-end): `D:\src\cookbook\adaption-reference\法睿兰达\CartAdapters\FY2208008\Scenes\AMRScene\ProjNameCar.cs`.&lt;br /&gt;
&lt;br /&gt;
== 写一个自评估 Car 子类 / Subclassing Car for self-eval vehicles ==&lt;br /&gt;
自评估车（磁导航 / 色带 / PLC 控制 / 二维码 等）的车载没有 MDCS，调度只能发&amp;quot;高层意图&amp;quot;，由 ''SimpleCore 侧'' 的 AGV 接口翻译成厂商命令，再通过 RFID / Modbus / HTTP 下发。&lt;br /&gt;
&lt;br /&gt;
Self-evaluating vehicles (magnetic-strip, tape, PLC-controlled, QR-only) don't run MDCS on-board. The scheduler dispatches &amp;quot;high-level intents&amp;quot;, and a ''fleet-side'' `AGV : AGVInterface` translates them into vendor commands (RFID frames, Modbus, HTTP) and reads back `(x, y, th, siteID)` via `keepAlive()`.&lt;br /&gt;
&lt;br /&gt;
经典样例：`D:\src\cookbook\adaption-reference\苏州凌鸟\Scenes\AMRScene1\Cars\MNavCar.cs`（293 行，含双向导航 + RFID 命令队列 + 启发式约束容器 `MNavCarHeuristics`）。&lt;br /&gt;
&lt;br /&gt;
Canonical example: `D:\src\cookbook\adaption-reference\苏州凌鸟\Scenes\AMRScene1\Cars\MNavCar.cs` (293 lines — two-way navigation, RFID command queue, `MNavCarHeuristics` for no-go turns / forced reversals).&lt;br /&gt;
&lt;br /&gt;
骨架 / Skeleton:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;csharp&amp;quot;&amp;gt;&lt;br /&gt;
[CarType(Name = &amp;quot;MyMagCart&amp;quot;, Title = &amp;quot;磁导航车 / Magnetic-strip cart&amp;quot;)]&lt;br /&gt;
public class MyMagCart : Car&lt;br /&gt;
{&lt;br /&gt;
    public string address;&lt;br /&gt;
    public int rfidPort = 502;&lt;br /&gt;
&lt;br /&gt;
    public class AGV : AGVInterface&lt;br /&gt;
    {&lt;br /&gt;
        private readonly MyMagCart car;&lt;br /&gt;
        public AGV(MyMagCart c) { car = c; }&lt;br /&gt;
&lt;br /&gt;
        public override bool TryLock(int siteID, int route_id) { /* SimpleCore 内置 / inherit */ return base.TryLock(siteID, route_id); }&lt;br /&gt;
        public override bool Leave(int siteID) { return base.Leave(siteID); }&lt;br /&gt;
&lt;br /&gt;
        public void Go(double sx, double sy, int sid, double dx, double dy, int did, int routeId)&lt;br /&gt;
        {&lt;br /&gt;
            Queue(&lt;br /&gt;
              async () =&amp;gt;&lt;br /&gt;
              {&lt;br /&gt;
                  // 在锁拿到后才发指令 / send intent only after lock granted&lt;br /&gt;
                  if (!TryLock(did, routeId)) return;&lt;br /&gt;
                  car.SendRFIDGoCommand(did);&lt;br /&gt;
              },&lt;br /&gt;
              async () =&amp;gt;&lt;br /&gt;
              {&lt;br /&gt;
                  // 等到车真的到了 / wait until reported arrival&lt;br /&gt;
                  while (car.lastReportedSiteId != did) await Task.Delay(100);&lt;br /&gt;
                  Leave(sid);&lt;br /&gt;
              });&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    public override async Task actualSendScript(string script) { /* 自评估车通常不发 TopazScript */ }&lt;br /&gt;
    public override async Task keepAlive()&lt;br /&gt;
    {&lt;br /&gt;
        // Modbus / TCP 读位置并写入 (x, y, th, siteId) / poll position&lt;br /&gt;
        var (x, y, th, siteId) = await PollPLCAsync(address);&lt;br /&gt;
        UpdatePose(x, y, th); lastReportedSiteId = siteId;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 任务下发 / Mission dispatch flow ==&lt;br /&gt;
&lt;br /&gt;
  调度内核 → SegmentPlan.Compile() → TopazScript（一段脚本）&lt;br /&gt;
                ↓&lt;br /&gt;
       CarProgram.script  (放入 Car.status.programs.forecasted)&lt;br /&gt;
                ↓&lt;br /&gt;
   Car.actualSendScript(script)&lt;br /&gt;
                ↓ (ClumsyCar)               ↓ (self-eval)&lt;br /&gt;
      HTTP POST 到车载                直接在调度侧本地跑 SelfEvaluating(agv, script)&lt;br /&gt;
                ↓                             ↓&lt;br /&gt;
   车载 SelfEvaluating(agv, script)    AGV.Go / AGV.Queue 等映射到 RFID/Modbus 命令&lt;br /&gt;
                ↓&lt;br /&gt;
      Clumsy Movement 执行 → 物理运动&lt;br /&gt;
&lt;br /&gt;
== Reachability 与包络 / Reachability &amp;amp; envelope ==&lt;br /&gt;
SimpleCore 提供 ''可达性状态机''（见 [[Special:MyLanguage/可达性状态编程|可达性状态编程]]）与 ''包络声明''（见 [[Special:MyLanguage/使用手册 - Simple:包络如何定义|包络如何定义]]）。你的 Car 子类一般只需要：&lt;br /&gt;
&lt;br /&gt;
* 声明默认包络（无载货状态的车体包络）。&lt;br /&gt;
* 在带载 / 升叉 / 顶升等状态时声明 ''备用包络''，由 `HaveExtraEnvelope` 状态触发。&lt;br /&gt;
* 在不可达的路径段上声明 ''可达性规则''（例如：单向通道、最低剩余电量、强制掉头）。&lt;br /&gt;
&lt;br /&gt;
A Car subclass typically: (1) declares the empty envelope, (2) declares alternate envelopes triggered by carry / fork-up / jack-up states, (3) declares reachability rules on path segments (one-way, min battery, mandatory reverse-out).&lt;br /&gt;
&lt;br /&gt;
== 用作算法宿主：在 SimpleComposer 之外用 SimpleCore ==&lt;br /&gt;
SimpleCore 是普通 .NET 库（`D:\src\Simple\SimpleCore\`），可以独立引用。最小集成：&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;csharp&amp;quot;&amp;gt;&lt;br /&gt;
using SimpleCore;&lt;br /&gt;
&lt;br /&gt;
var world = new World(); // 加载站点 + 路径图 / load sites + path graph&lt;br /&gt;
world.LoadFromJson(File.ReadAllText(&amp;quot;map.json&amp;quot;));&lt;br /&gt;
&lt;br /&gt;
var car1 = new MyAbstractCarImpl();   // 实现 AbstractCar 接口&lt;br /&gt;
var car2 = new MyAbstractCarImpl();&lt;br /&gt;
world.AddCar(car1); world.AddCar(car2);&lt;br /&gt;
&lt;br /&gt;
var planner = new DPSPlanner(world);&lt;br /&gt;
var mission = planner.Plan(&lt;br /&gt;
    from: world.GetSite(&amp;quot;A&amp;quot;),&lt;br /&gt;
    to:   world.GetSite(&amp;quot;Z&amp;quot;));&lt;br /&gt;
&lt;br /&gt;
foreach (var step in mission.Steps)&lt;br /&gt;
{&lt;br /&gt;
    Console.WriteLine($&amp;quot;car={step.Car} site={step.Site} action={step.Action}&amp;quot;);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= 算法 / Algorithms =&lt;br /&gt;
SimpleCore 内置：&lt;br /&gt;
SimpleCore ships with:&lt;br /&gt;
&lt;br /&gt;
* DPS 调度（动态规划交管）—— `[[Special:MyLanguage/DPS调度算法详解|DPS调度算法详解]]`&lt;br /&gt;
* 寻路启发器 —— `[[Special:MyLanguage/使用手册 - 寻路启发器功能|寻路启发器功能]]`&lt;br /&gt;
* 流场规划 —— `[[Special:MyLanguage/流场规划|流场规划]]`&lt;br /&gt;
* 网络流业务规划 —— `[[Special:MyLanguage/基于网络流的业务规划器|基于网络流的业务规划器]]`&lt;br /&gt;
&lt;br /&gt;
== 调试 / Debugging ==&lt;br /&gt;
* 用 [[Special:MyLanguage/CycleGUI|CycleGUI]] 把交管锁、车辆状态、路径片段实时画出来。&lt;br /&gt;
* SimpleComposer 的 ''Trace 面板'' 显示每条任务的 Queue 行执行轨迹。&lt;br /&gt;
* 死锁怀疑时打开 ''DPS 决策可视化''（DPS 算法会输出每次决策的剪枝树）。&lt;br /&gt;
&lt;br /&gt;
* Use [[Special:MyLanguage/CycleGUI|CycleGUI]] to render locks, car state, path segments live.&lt;br /&gt;
* SimpleComposer's ''Trace panel'' shows the Queue-row execution timeline per mission.&lt;br /&gt;
* When deadlock is suspected, enable ''DPS decision visualisation''.&lt;br /&gt;
&lt;br /&gt;
== 相关页面 / See also ==&lt;br /&gt;
* [[Special:MyLanguage/AGV任务运行逻辑|AGV任务运行逻辑]]&lt;br /&gt;
* [[Special:MyLanguage/调度内核运行原理|调度内核运行原理]]&lt;br /&gt;
* [[Special:MyLanguage/DPS调度算法详解|DPS调度算法详解]]&lt;br /&gt;
* [[Special:MyLanguage/Simple-API|Simple-API]]&lt;br /&gt;
* [[Special:MyLanguage/开发手册 - SimpleComposer界面开发 - CAD工具|SimpleComposer界面开发]]&lt;br /&gt;
* [[Special:MyLanguage/使用手册 - Simple:从使用到开发|Simple:从使用到开发]]&lt;br /&gt;
&lt;br /&gt;
[[Category:二次开发相关说明]]&lt;br /&gt;
[[Category:开发手册]]&lt;/div&gt;</summary>
		<author><name>Artheru</name></author>
	</entry>
</feed>