查看“DriveTask调度循环”的源代码
←
DriveTask调度循环
跳到导航
跳到搜索
因为以下原因,您没有权限编辑本页:
您请求的操作仅限属于该用户组的用户执行:
管理员
您可以查看和复制此页面的源代码。
<languages/> == 概述 / Overview == `DriveTask` 是 Clumsy 内部把 [[Special:MyLanguage/MovementDefinition详解|`MovementDefinition`]] 的 ''迭代器''变成 ''周期控制循环''的工具。每次调用 `DriveTask.WaitDriveTask(IEnumerable<bool>)` : 1. 起一条 ''新线程''(`ThreadPriority.AboveNormal`)。 2. 每隔 `Configuration.conf.DriveTaskInterval`(默认 20 ms)调一次 `enumerator.MoveNext()`。 3. 阻塞调用方直到迭代器结束(正常完成或异常)。 `DriveTask` is Clumsy's mechanism for turning a [[Special:MyLanguage/MovementDefinition详解|MovementDefinition]]'s iterator into a '''timed control loop'''. Each `DriveTask.WaitDriveTask(IEnumerable<bool>)` call: 1. Spawns a new thread at `ThreadPriority.AboveNormal`. 2. Calls `enumerator.MoveNext()` every `Configuration.conf.DriveTaskInterval` (default 20 ms). 3. Blocks the caller until the iterator ends (success or exception). 实现:`D:\src\Clumsy\ClumsyCore\DriveTask.cs:34-205`。 Implementation: `D:\src\Clumsy\ClumsyCore\DriveTask.cs:34-205`. == 标准用法 / Standard usage == <syntaxhighlight lang="csharp"> DriveTask.WaitDriveTask(new SteeringLineFollowing { srcX = sx, srcY = sy, dstX = dx, dstY = dy, basespeed = 600 }.Follow()); // Returns when the Movement finishes (normal or thrown) </syntaxhighlight> == 循环细节 / Loop details == WaitDriveTask(IEnumerable<bool>) 入口: │ ▼ new DriveTask: enumerator = iterable.GetEnumerator(); Thread(prio=AboveNormal) starts: │ ▼ 循环 / loop: if (stopToken) break; bool keepGoing = enumerator.MoveNext(); if (!keepGoing) { stopped_reason = 0; break; } Thread.Sleep(DriveTaskInterval); // 20 ms 默认 │ ▼ 退出 / exit (any cause): Monitor.PulseAll(wait) │ ▼ WaitDriveTask blocks on Monitor.Wait(wait) └─→ 醒来后检查 exception,重新抛 / wakes, rethrows captured exception if any == `DoUntil` 并行检查 / Parallel termination check == `DoUntil(IEnumerable<bool> condition)` 起一条 ''并行''任务,独立轮询 `condition`;若 `condition.MoveNext()` 返回 true,停止主 Movement 并设置 `stopped_reason = stop_condition_id`: <syntaxhighlight lang="csharp"> var driveTask = DriveTask.WaitDriveTaskBegin(new SteeringLineFollowing { ... }.Follow()); driveTask.DoUntil(new ObstacleCloseCheck { distThres = 200 }.Get()); driveTask.Wait(); // blocks; returns when either main Movement done OR DoUntil fires </syntaxhighlight> `stopped_reason` 区分了正常完成 (0)、`DoUntil` 触发(其条件 id)、异常 (-1)。 `stopped_reason` differentiates normal (0), `DoUntil` triggered (the cond ID), and exception (-1). == 与 SecurityCheck 的关系 / Relation to SecurityCheck == `PilotBase.SecurityCheck()`(`D:\src\Clumsy\ClumsyCore\Pilot\PilotDefinition.cs:64-75`)是 ''独立''的看门狗,每个 Movement 都不感知它。SecurityCheck 监测 : * 当前 DriveTask 是否在 `Configuration.conf.DriveTaskTimeout`(默认 300 ms)内有控制信号产生。 * 若没有 → 调 `DriveStop()` 强制车停 → 主 DriveTask 的 `stopToken = true` → 下一 tick 退出循环。 【发现】 SecurityCheck 不杀 Movement 的 enumerator;它只是让 DriveTask 在下一 tick 退出循环。所以 ''Movement 作者需自己确保 `Get()` 在迭代器内可被中断''(不要 sleep 长时间)。<br> SecurityCheck doesn't kill the enumerator; it just lets the loop bail next tick. Movement authors must keep `Get()` interruptible (no long sleeps). == 异常传播 / Exception propagation == * `MoveNext()` 抛异常 → 捕获到 `_exception` 字段 → `stopped_reason = -1` → 触发 `Monitor.PulseAll`。 * `WaitDriveTask` 调用方 ''醒来后''重新抛该异常。 * 上游 `SimpleAgvInterface.Queue` 的 action 内异常 → 记到 `queueInfo[i].exception`,跳过本行剩余 action。 【注意】 不要把异常 ''吞''在 Movement 内。让它传出,让上层决定恢复策略。<br> Don't swallow exceptions inside Movements; let them propagate so the upper layer decides. == Thread Priority 与延迟 / Thread priority & latency == * DriveTask 线程是 `AboveNormal`,比 LadderLogic 略高。 * tick 抖动主要来自 `Thread.Sleep` 精度(Windows ~1–15 ms 量级)。 * 高速 / 高精度场景(如 [[Special:MyLanguage/汽车面差检测|汽车面差检测]])可能需要在 PLC 层做关键回路,DriveTask 仅做高层规划。 == 在 SimpleAgvInterface 中的使用 / Usage in SimpleAgvInterface == `SimpleAgvInterface.Queue` 的每个 action 内通常一次 `DriveTask.WaitDriveTask(...)`。详见 [[Special:MyLanguage/SimpleAgvInterface Queue机制|SimpleAgvInterface Queue机制]]。 Each action inside `SimpleAgvInterface.Queue` typically calls `DriveTask.WaitDriveTask` once. == 配置 / Configuration == {| class="wikitable" ! 字段 / Field !! 默认 / Default !! 文件 / File |- | `DriveTaskInterval` || 20 ms || `D:\src\Clumsy\ClumsyCore\Configuration.cs` |- | `DriveTaskTimeout` || 300 ms || same |- | `basicSpeed` || 项目相关 || same |} 从嵌入资源 `ClumsyCore.res.defaultconf.json` 加载,或用 `Configuration.FromFile(fn)` 覆盖。 Loaded from embedded `ClumsyCore.res.defaultconf.json` or overridden via `Configuration.FromFile`. == 常见错误 / Common mistakes == * '''忘了 `WaitDriveTask` 是阻塞的''' → 在 UI 线程调会冻 UI。包到 `SimpleAgvInterface.Queue` 的 async action 里。 * '''Movement Get() 不 yield''' → 立即耗尽,DriveTask 立即返回,看起来"完成了 0 ms"。Always `yield return` at least once per control cycle. * '''DriveStop 中无 vCmd = 0''' → 即使 enumerator 停了,最后一帧的 vCmd 还在 DObject 里,车继续动。在 `DriveStop()` 里显式清零所有 IDriveWriter 状态。 * `WaitDriveTask` is blocking; calling it on the UI thread freezes UI. Wrap in `SimpleAgvInterface.Queue`'s async action. * If `Get()` never yields, DriveTask exits immediately. * `DriveStop()` must explicitly zero all IDriveWriter outputs; otherwise the last frame's `vCmd` stays in DObject. == 相关页面 / See also == * [[Special:MyLanguage/MovementDefinition详解|MovementDefinition详解]] * [[Special:MyLanguage/SimpleAgvInterface Queue机制|SimpleAgvInterface Queue机制]] * [[Special:MyLanguage/巡线行走|巡线行走]] * [[Special:MyLanguage/绕障行走|绕障行走]] * [[Special:MyLanguage/车体抽象原理|车体抽象原理]] * [[Special:MyLanguage/Clumsy-API|Clumsy-API]] [[Category:二次开发相关说明]] [[Category:运动控制使用手册]]
返回
DriveTask调度循环
。
导航菜单
个人工具
中文(中国大陆)
创建账号
登录
命名空间
页面
讨论
大陆简体
查看
阅读
查看源代码
查看历史
更多
导航
首页
最近更改
随机页面
MediaWiki帮助
工具
链入页面
相关更改
特殊页面
页面信息