<?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=SimpleAgvInterface_Queue%E6%9C%BA%E5%88%B6</id>
	<title>SimpleAgvInterface Queue机制 - 版本历史</title>
	<link rel="self" type="application/atom+xml" href="https://wiki2.lessokaji.com/index.php?action=history&amp;feed=atom&amp;title=SimpleAgvInterface_Queue%E6%9C%BA%E5%88%B6"/>
	<link rel="alternate" type="text/html" href="https://wiki2.lessokaji.com/index.php?title=SimpleAgvInterface_Queue%E6%9C%BA%E5%88%B6&amp;action=history"/>
	<updated>2026-05-16T17:52:46Z</updated>
	<subtitle>本wiki上该页面的版本历史</subtitle>
	<generator>MediaWiki 1.40.0</generator>
	<entry>
		<id>https://wiki2.lessokaji.com/index.php?title=SimpleAgvInterface_Queue%E6%9C%BA%E5%88%B6&amp;diff=1043&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=SimpleAgvInterface_Queue%E6%9C%BA%E5%88%B6&amp;diff=1043&amp;oldid=prev"/>
		<updated>2026-05-16T14:00:23Z</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;
`SimpleAgvInterface.Queue(params Func&amp;lt;Task&amp;gt;[] actions)` 是 Clumsy 车载侧的 ''任务流水线''机制。它把多个 ''异步 action''组织成可串可并的执行图，使任务作者能以声明式风格写出 &amp;quot;巡线 → 取货 → 升叉 → 倒车&amp;quot;这样的业务序列。&lt;br /&gt;
&lt;br /&gt;
`SimpleAgvInterface.Queue(params Func&amp;lt;Task&amp;gt;[] actions)` is the '''task pipeline''' on the Clumsy on-vehicle side. It organises multiple async actions into a serial/parallel execution graph so mission authors can write business sequences declaratively.&lt;br /&gt;
&lt;br /&gt;
实现：`D:\src\Clumsy\ClumsyCore\Interfaces\SimpleAgvInterface.cs:410`。&lt;br /&gt;
Implementation: `D:\src\Clumsy\ClumsyCore\Interfaces\SimpleAgvInterface.cs:410`.&lt;br /&gt;
&lt;br /&gt;
== 基本用法 / Basic usage ==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;csharp&amp;quot;&amp;gt;&lt;br /&gt;
public void Fetch(double sx, double sy, double dx, double dy)&lt;br /&gt;
{&lt;br /&gt;
    Queue(&lt;br /&gt;
      async () =&amp;gt;&lt;br /&gt;
      {&lt;br /&gt;
          DriveTask.WaitDriveTask(new SteeringLineFollowing&lt;br /&gt;
          { srcX = currentX, srcY = currentY, dstX = sx, dstY = sy, basespeed = 600 }.Follow());&lt;br /&gt;
      },&lt;br /&gt;
      async () =&amp;gt;&lt;br /&gt;
      {&lt;br /&gt;
          DriveTask.WaitDriveTask(new AutoFetchGood&lt;br /&gt;
          { aX = sx, aY = sy, bX = dx, bY = dy, initSpeed = 500, stopDist = 80 }.Get());&lt;br /&gt;
      },&lt;br /&gt;
      async () =&amp;gt;&lt;br /&gt;
      {&lt;br /&gt;
          SetUpperIO(&amp;quot;forkHeightTgt&amp;quot;, 50);&lt;br /&gt;
          await WaitForLowerIO(&amp;quot;forkAtTarget&amp;quot;, 4000);&lt;br /&gt;
      },&lt;br /&gt;
      async () =&amp;gt;&lt;br /&gt;
      {&lt;br /&gt;
          DriveTask.WaitDriveTask(new SteeringLineFollowingReverse&lt;br /&gt;
          { srcX = dx, srcY = dy, dstX = sx, dstY = sy, basespeed = 200 }.ReverseFollow());&lt;br /&gt;
      });&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
按提交顺序，4 个 action 形成 4 ''行''（rows），框架依次执行。&lt;br /&gt;
The 4 actions form 4 ''rows''; the framework executes them.&lt;br /&gt;
&lt;br /&gt;
== 数据结构 / Data structure ==&lt;br /&gt;
内部维护两个队列（`SimpleAgvInterface.cs:308-352`）：&lt;br /&gt;
Internally there are two queues:&lt;br /&gt;
&lt;br /&gt;
* '''`staticTaskLs : List&amp;lt;List&amp;lt;Task&amp;gt;&amp;gt;`''' — 静态共享队列；每行是 `List&amp;lt;Task&amp;gt;`。&lt;br /&gt;
* '''`taskLs : List&amp;lt;List&amp;lt;Task&amp;gt;&amp;gt;`''' — 当前实例的队列；可与 static 共享或独立。&lt;br /&gt;
* '''`queueInfo : List&amp;lt;SaiInfo&amp;gt;`''' — 每行的状态字符串、提交线程 ID、异常上下文。&lt;br /&gt;
&lt;br /&gt;
每次 `Queue(actions)` 调用 ：&lt;br /&gt;
Each `Queue(actions)` call:&lt;br /&gt;
&lt;br /&gt;
# 把 `actions[i]` ContinueWith 到 `taskLs[i]` 的最后一个 Task 后面。&lt;br /&gt;
# `actions[i]` 内部 `await taskLs[i-1].Last()` —— 即等上一 ''行''最新提交的 action 完成。&lt;br /&gt;
# 注册到 `queueInfo[i]`。&lt;br /&gt;
&lt;br /&gt;
# Chain `actions[i]` after `taskLs[i].Last()` (the previous action in the same row).&lt;br /&gt;
# Inside `actions[i]`, `await taskLs[i-1].Last()` (the previous row's latest action).&lt;br /&gt;
# Register in `queueInfo[i]`.&lt;br /&gt;
&lt;br /&gt;
== &amp;quot;超标量&amp;quot;实际行为 / The &amp;quot;super-scalar&amp;quot; reality ==&lt;br /&gt;
【发现】 当前实现 ''没有''真正的跨行并发。第 i 行的 action ''必须''等第 i-1 行的 ''最新提交''完成，所以多行 Queue 调用实际上是 ''串行执行''。&amp;quot;超标量流水线&amp;quot;是设计目标，不是当前实现。&lt;br /&gt;
【发现】 The current implementation does NOT actually run rows in parallel. Row i awaits row i-1's most recent Task, so multi-row Queue calls execute '''sequentially'''. The &amp;quot;super-scalar pipeline&amp;quot; is design aspiration, not current behaviour.&lt;br /&gt;
&lt;br /&gt;
也就是说 ：&lt;br /&gt;
In practice:&lt;br /&gt;
&lt;br /&gt;
* '''单次 `Queue(a, b, c)`''' → a, b, c 串行（b 等 a 完成，c 等 b 完成）。&lt;br /&gt;
* '''连续 `Queue(a, b)`; `Queue(c, d)`''' → a → b → c → d 串行；c 等 b 完成（同行）；d 等 c 完成（同行）。&lt;br /&gt;
* '''并发要靠 action 内 `Task.WhenAll`''' —— 若你想 a + b 同时开始，自己在 a 内 `Task.WhenAll(taskA, taskB)`。&lt;br /&gt;
&lt;br /&gt;
* `Queue(a, b, c)` runs a → b → c sequentially.&lt;br /&gt;
* Repeated `Queue` calls also serialise via row chaining.&lt;br /&gt;
* For concurrency '''within''' an action, use `Task.WhenAll` explicitly.&lt;br /&gt;
&lt;br /&gt;
== `WaitAsync` / `Wait` ==&lt;br /&gt;
等待指定行完成：&lt;br /&gt;
Wait for a specific row to finish:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;csharp&amp;quot;&amp;gt;&lt;br /&gt;
await agv.WaitAsync(pipe: 2);  // wait for row 2's latest task&lt;br /&gt;
// or sync&lt;br /&gt;
agv.Wait(pipe: 0);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== `TryLock` / `Leave` ==&lt;br /&gt;
交管 ''锁''的两种执行路径，由 `useSimpleCallTraffic` 开关决定（`SimpleAgvInterface.cs:40`）：&lt;br /&gt;
&lt;br /&gt;
Traffic locks have two paths controlled by `useSimpleCallTraffic`:&lt;br /&gt;
&lt;br /&gt;
=== 同步内置 / In-process synchronous ===&lt;br /&gt;
当 `useSimpleCallTraffic = true`（同一进程跑调度内核 + 车载）：&lt;br /&gt;
* `TryLock(siteID, route_id)` 轮询 `PilotBase.latestLock == siteID`（`SimpleAgvInterface.cs:124`）&lt;br /&gt;
* `Leave(siteID)` 直接更新本地 `PilotBase.leaves`&lt;br /&gt;
&lt;br /&gt;
=== HTTP RPC ===&lt;br /&gt;
跨进程时（车载与调度内核不在同一进程）：&lt;br /&gt;
* `TryLock` → POST `http://{host}:{port}/trylock` body `{carid, siteid}`（line 170）&lt;br /&gt;
* `Leave` → GET `/leave?carid={id}&amp;amp;siteid={siteID}`（line 260）&lt;br /&gt;
&lt;br /&gt;
== 异常处理 / Error handling ==&lt;br /&gt;
* Action 内异常 → 写到 `queueInfo[i].exception`；该行后续 action 跳过；其它行继续。&lt;br /&gt;
* 调度可通过 `Flush()` 显式终结队列；之后 `Queue(...)` 抛 `_pipelineError`（line 112）。&lt;br /&gt;
* 任务级失败上报靠 ''任务脚本编译时插入的 try/catch'' + Hedingben toast。&lt;br /&gt;
&lt;br /&gt;
* Exceptions in actions → recorded in `queueInfo[i].exception`; subsequent actions in that row skipped; other rows continue.&lt;br /&gt;
* `Flush()` ends the queue; later `Queue(...)` throws `_pipelineError`.&lt;br /&gt;
&lt;br /&gt;
== 实战模式 / Patterns ==&lt;br /&gt;
=== 顺序业务动作 / Sequential business action ===&lt;br /&gt;
最常见。每个 action 是一段独立的 ''检查 → 行驶 → 等硬件''微操。&lt;br /&gt;
Most common. Each action is a self-contained &amp;quot;check → drive → wait hw&amp;quot; micro-op.&lt;br /&gt;
&lt;br /&gt;
=== 锁先于动作 / Lock-then-act ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;csharp&amp;quot;&amp;gt;&lt;br /&gt;
Queue(&lt;br /&gt;
  async () =&amp;gt; { if (!TryLock(targetSite, routeId)) return; /* signal failure */ },&lt;br /&gt;
  async () =&amp;gt; { /* the actual drive */ },&lt;br /&gt;
  async () =&amp;gt; Leave(prevSite)&lt;br /&gt;
);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== 设备 IO 等待 / Wait-for-IO ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;csharp&amp;quot;&amp;gt;&lt;br /&gt;
Queue(&lt;br /&gt;
  async () =&amp;gt; { SetUpperIO(&amp;quot;jackTarget&amp;quot;, 80); },&lt;br /&gt;
  async () =&amp;gt; { await WaitForLowerIO(&amp;quot;jackAtTarget&amp;quot;, timeoutMs: 4000); }&lt;br /&gt;
);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== 错误恢复 / Error recovery ===&lt;br /&gt;
Action 内部 try/catch；失败时把 cart 切到 &amp;quot;故障&amp;quot;状态并 toast：&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;csharp&amp;quot;&amp;gt;&lt;br /&gt;
Queue(&lt;br /&gt;
  async () =&amp;gt;&lt;br /&gt;
  {&lt;br /&gt;
      try { await DoFragileThing(); }&lt;br /&gt;
      catch (Exception e)&lt;br /&gt;
      {&lt;br /&gt;
          Hedingben.ToastText($&amp;quot;Action failed: {e.Message}&amp;quot;, &amp;quot;AGV&amp;quot;);&lt;br /&gt;
          DriveStop();&lt;br /&gt;
          throw;&lt;br /&gt;
      }&lt;br /&gt;
  }&lt;br /&gt;
);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 调度侧 AGVInterface / Fleet-side AGVInterface ==&lt;br /&gt;
SimpleCore 端的 `AGVInterface` (`D:\src\Simple\SimpleCore\BasicProps\AGVInterface.cs`) 提供 ''同款 Queue 机制''，用于自评估车 ：调度直接在自己进程里跑 Queue 来翻译 TopazScript。详见 [[Special:MyLanguage/如何基于SimpleCore核心库进行调度系统开发|如何基于SimpleCore核心库进行调度系统开发]]。&lt;br /&gt;
&lt;br /&gt;
The fleet-side `AGVInterface` provides the same Queue mechanism for self-evaluating cars (scheduler runs Queue locally to translate TopazScript).&lt;br /&gt;
&lt;br /&gt;
== 相关页面 / See also ==&lt;br /&gt;
* [[Special:MyLanguage/MovementDefinition详解|MovementDefinition详解]]&lt;br /&gt;
* [[Special:MyLanguage/DriveTask调度循环|DriveTask调度循环]]&lt;br /&gt;
* [[Special:MyLanguage/车体抽象原理|车体抽象原理]]&lt;br /&gt;
* [[Special:MyLanguage/如何基于SimpleCore核心库进行调度系统开发|如何基于SimpleCore核心库进行调度系统开发]]&lt;br /&gt;
* [[Special:MyLanguage/Clumsy-API|Clumsy-API]]&lt;br /&gt;
&lt;br /&gt;
[[Category:二次开发相关说明]]&lt;br /&gt;
[[Category:开发手册]]&lt;/div&gt;</summary>
		<author><name>Artheru</name></author>
	</entry>
</feed>