<?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=MovementDefinition%E8%AF%A6%E8%A7%A3</id>
	<title>MovementDefinition详解 - 版本历史</title>
	<link rel="self" type="application/atom+xml" href="https://wiki2.lessokaji.com/index.php?action=history&amp;feed=atom&amp;title=MovementDefinition%E8%AF%A6%E8%A7%A3"/>
	<link rel="alternate" type="text/html" href="https://wiki2.lessokaji.com/index.php?title=MovementDefinition%E8%AF%A6%E8%A7%A3&amp;action=history"/>
	<updated>2026-05-16T17:53:20Z</updated>
	<subtitle>本wiki上该页面的版本历史</subtitle>
	<generator>MediaWiki 1.40.0</generator>
	<entry>
		<id>https://wiki2.lessokaji.com/index.php?title=MovementDefinition%E8%AF%A6%E8%A7%A3&amp;diff=1042&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=MovementDefinition%E8%AF%A6%E8%A7%A3&amp;diff=1042&amp;oldid=prev"/>
		<updated>2026-05-16T14:00:21Z</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;
`MovementDefinition` 是 Clumsy 中描述 ''一个运动行为''的抽象基类。每个 Movement 是一段 ''可迭代''的控制循环，由 `DriveTask` 宿主按 ''DriveTaskInterval''（默认 20 ms）周期推进。它是 Clumsy 自动驾驶的 ''基本运动语汇''。&lt;br /&gt;
&lt;br /&gt;
`MovementDefinition` is the Clumsy abstract base that describes a single motion behaviour. Each Movement is an iterable control loop, ticked by `DriveTask` at `DriveTaskInterval` (default 20 ms). It's Clumsy's '''basic motion vocabulary'''.&lt;br /&gt;
&lt;br /&gt;
定义：`D:\src\Clumsy\ClumsyCore\Pilot\MovementDefinition.cs:41-48`。&lt;br /&gt;
Definition: `D:\src\Clumsy\ClumsyCore\Pilot\MovementDefinition.cs:41-48`.&lt;br /&gt;
&lt;br /&gt;
== 契约 / Contract ==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;csharp&amp;quot;&amp;gt;&lt;br /&gt;
public abstract class MovementDefinition&lt;br /&gt;
{&lt;br /&gt;
    public abstract IEnumerable&amp;lt;bool&amp;gt; Get();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
public abstract class MovementDefinition&amp;lt;T&amp;gt; : MovementDefinition&lt;br /&gt;
{&lt;br /&gt;
    public new abstract IEnumerable&amp;lt;T&amp;gt; Get();&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
`Get()` 返回一个 ''可迭代''；框架每次调 `MoveNext()` 推一格。&lt;br /&gt;
&lt;br /&gt;
`Get()` returns an enumerable; the framework calls `MoveNext()` once per tick.&lt;br /&gt;
&lt;br /&gt;
* '''每次 `yield return true`''' = &amp;quot;继续 tick&amp;quot; / &amp;quot;keep ticking&amp;quot;&lt;br /&gt;
* '''迭代器耗尽（不再 `yield`）''' = &amp;quot;Movement 完成&amp;quot; / &amp;quot;Movement done&amp;quot;&lt;br /&gt;
&lt;br /&gt;
== 生命周期 / Lifecycle ==&lt;br /&gt;
&lt;br /&gt;
  你的代码 / Your code:&lt;br /&gt;
    DriveTask.WaitDriveTask(new MyMovement{...}.Get());&lt;br /&gt;
       │&lt;br /&gt;
       ▼&lt;br /&gt;
  DriveTask 内部 / Inside DriveTask (D:\src\Clumsy\ClumsyCore\DriveTask.cs:104-144):&lt;br /&gt;
    new Thread + AboveNormal priority&lt;br /&gt;
       │&lt;br /&gt;
       ▼ 循环 / loop:&lt;br /&gt;
    enumerator.MoveNext()&lt;br /&gt;
    Thread.Sleep(Configuration.conf.DriveTaskInterval) // 20 ms&lt;br /&gt;
    ...&lt;br /&gt;
       │&lt;br /&gt;
       ▼ 完成 / done (MoveNext returns false):&lt;br /&gt;
    stopped_reason = 0&lt;br /&gt;
    Monitor.PulseAll(wait)&lt;br /&gt;
       │&lt;br /&gt;
       ▼ 异常 / on exception:&lt;br /&gt;
    stopped_reason = -1&lt;br /&gt;
    capture &amp;amp; rethrow on Wait()&lt;br /&gt;
&lt;br /&gt;
调用方 `WaitDriveTask` 在 `Monitor.Wait(wait)` 上阻塞直到完成。&lt;br /&gt;
Caller `WaitDriveTask` blocks on `Monitor.Wait(wait)` until completion.&lt;br /&gt;
&lt;br /&gt;
== 最小 Movement / Minimal Movement ==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;csharp&amp;quot;&amp;gt;&lt;br /&gt;
using ClumsyCore.Pilot;&lt;br /&gt;
using ClumsyCore.DrivePlans;&lt;br /&gt;
using System.Collections.Generic;&lt;br /&gt;
&lt;br /&gt;
public class MyStraight : MovementDefinition&lt;br /&gt;
{&lt;br /&gt;
    public float dx, dy;          // displacement&lt;br /&gt;
    public float basespeed = 600; // mm/s&lt;br /&gt;
&lt;br /&gt;
    public override IEnumerable&amp;lt;bool&amp;gt; Get()&lt;br /&gt;
    {&lt;br /&gt;
        var sx = currentX;        // pose at start&lt;br /&gt;
        var sy = currentY;&lt;br /&gt;
        var driver = new SteeringLineFollowing&lt;br /&gt;
        {&lt;br /&gt;
            srcX = sx, srcY = sy,&lt;br /&gt;
            dstX = sx + dx, dstY = sy + dy,&lt;br /&gt;
            basespeed = basespeed&lt;br /&gt;
        };&lt;br /&gt;
        foreach (var t in driver.Follow()) yield return t;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== [MovementTest] 属性 / Attribute ==&lt;br /&gt;
'''目标''' / Target: 类 / class&lt;br /&gt;
&lt;br /&gt;
'''效果''' / Effect: 在 Clumsy 测试 UI 注册一个 ''测试按钮''；按下立即在车上跑这个 Movement（车应静止 / 在仿真）。&lt;br /&gt;
Registers a test button in the Clumsy UI; pressing it runs the Movement on a stationary (or simulated) vehicle.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;csharp&amp;quot;&amp;gt;&lt;br /&gt;
[MovementTest(name = &amp;quot;测试我的直线 / Test my line&amp;quot;)]&lt;br /&gt;
public class MyStraight : MovementDefinition { ... }&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 可用原语 / Primitive library ==&lt;br /&gt;
Movement 通常 ''组合''下层原语而不是从零写控制律。下面是仓库里现成的：&lt;br /&gt;
Movements usually compose lower-level primitives rather than implement control law from scratch.&lt;br /&gt;
&lt;br /&gt;
=== ClumsyCore/Legacy/（几何跟踪基础） ===&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Primitive !! 用途 / Use&lt;br /&gt;
|-&lt;br /&gt;
| `SteeringLineFollowing` || 阿克曼正向纯跟踪&lt;br /&gt;
|-&lt;br /&gt;
| `SteeringLineFollowingReverse` || 阿克曼反向跟踪&lt;br /&gt;
|-&lt;br /&gt;
| `OmniWheelTracking` || 全向轮速跟踪&lt;br /&gt;
|-&lt;br /&gt;
| `LeftRightWheelTracking` || 差速轮速跟踪&lt;br /&gt;
|-&lt;br /&gt;
| `OmniBezierTracking` / `LeftRightBezierTracking` || Bezier 曲线跟踪&lt;br /&gt;
|-&lt;br /&gt;
| `TrajectoryReplanningObstacleAvoidance` || 动态避障&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== ClumsyDance/Movements/（行为聚合） ===&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Movement !! 用途 / Use&lt;br /&gt;
|-&lt;br /&gt;
| `SlotFollowing` || 槽位跟踪（叉车叉孔 / KIVA 腿对）&lt;br /&gt;
|-&lt;br /&gt;
| `ReflexDock` || 反射式对接&lt;br /&gt;
|-&lt;br /&gt;
| `KivaFollowShelfOfManyLegs` || 多腿料架导航&lt;br /&gt;
|-&lt;br /&gt;
| `TopHatFollowing` || 礼帽形特征跟踪&lt;br /&gt;
|-&lt;br /&gt;
| `BezierMPC` || Bezier 参考的 MPC&lt;br /&gt;
|-&lt;br /&gt;
| `LRWheelOdometryCalculator` || 编码器积分助手&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== ClumsyDance/Detectors/（感知） ===&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Detector !! 用途&lt;br /&gt;
|-&lt;br /&gt;
| `LidarDetectTray` || 通用托盘检测（2 腿 / 3 腿可调）&lt;br /&gt;
|-&lt;br /&gt;
| `Lidar2dDetect2LegTray`, `Lidar2dDetect3LegTray`, `Lidar3dDetectTray` || 特化变体&lt;br /&gt;
|-&lt;br /&gt;
| `Cam3dDetectTray` || 3D 相机检测&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== MovementDefinition&amp;lt;T&amp;gt; 泛型变体 / Generic variant ==&lt;br /&gt;
当 Movement 需要 ''返回''一个对象（如已配置好的子 Movement）：&lt;br /&gt;
When a Movement needs to ''return'' a typed handle (e.g. a pre-configured sub-Movement):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;csharp&amp;quot;&amp;gt;&lt;br /&gt;
public class BuildFollower : MovementDefinition&amp;lt;SteeringLineFollowing&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
    public float srcX, srcY, dstX, dstY;&lt;br /&gt;
    public override IEnumerable&amp;lt;SteeringLineFollowing&amp;gt; Get()&lt;br /&gt;
    {&lt;br /&gt;
        yield return new SteeringLineFollowing&lt;br /&gt;
        {&lt;br /&gt;
            srcX = srcX, srcY = srcY,&lt;br /&gt;
            dstX = dstX, dstY = dstY,&lt;br /&gt;
            basespeed = 800&lt;br /&gt;
        };&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 异常 + 中止 / Exceptions &amp;amp; abort ==&lt;br /&gt;
* `Get()` 内抛异常 → `DriveTask.Wait()` 返回时 ''重新抛出''。&lt;br /&gt;
* `PilotBase.SecurityCheck()` 在没收到控制信号超时（默认 300 ms）时调 `DriveStop()`；当前 Movement 的 enumerator 不会再被推进，但 ''资源清理责任在 Movement 作者''（在 yield 前后包 try/finally）。&lt;br /&gt;
* 调用者按 `WaitDriveTask(...)` 同步等；要异步用 `DriveTask.WaitDriveTask` 包在另一线程或 `SimpleAgvInterface.Queue`。&lt;br /&gt;
&lt;br /&gt;
Exceptions from `Get()` re-throw when `WaitDriveTask` returns. The watchdog (`SecurityCheck`, default 300 ms timeout) calls `DriveStop()`; the enumerator stops being advanced but Movement-owned cleanup is on the author (wrap in try/finally).&lt;br /&gt;
&lt;br /&gt;
== 与 Pilot 的关系 / Relation to Pilot ==&lt;br /&gt;
* `PilotBase` 是 Movement 的 ''宿主进程上下文''（提供 pose、IDriveWriter 等）。&lt;br /&gt;
* `PilotDefinition&amp;lt;T&amp;gt;` 加 typed config。&lt;br /&gt;
* 95% 的车型定制不用碰 PilotBase —— 写 Movement 就够。&lt;br /&gt;
&lt;br /&gt;
`PilotBase` is Movement's ''host context'' (pose, drive writers); `PilotDefinition&amp;lt;T&amp;gt;` adds typed config. 95% of customisation only needs Movements.&lt;br /&gt;
&lt;br /&gt;
== 常见错误 / Gotchas ==&lt;br /&gt;
* '''在 `Get()` 用 `Thread.Sleep`''' → 阻塞 DriveTask 线程，定时器漂移。正确方式：`yield return` 多次。&amp;lt;br&amp;gt;&lt;br /&gt;
  Don't `Thread.Sleep` inside `Get()`; just `yield return` multiple times.&lt;br /&gt;
* '''Movement 跨实例共享状态''' → Movement 应是 ''可重入''的；不要用 static 字段保存进度。&amp;lt;br&amp;gt;&lt;br /&gt;
  Movements should be reentrant; don't use static fields for progress.&lt;br /&gt;
* '''忘了在不需要继续时 `yield break`''' → 看起来在原地踏步。&lt;br /&gt;
* '''构造时读 pose''' → 应在 `Get()` 第一帧读，避免构造与执行间车移动了。&amp;lt;br&amp;gt;&lt;br /&gt;
  Read pose inside `Get()`, not in the ctor — otherwise the car may have moved.&lt;br /&gt;
&lt;br /&gt;
== 相关页面 / See also ==&lt;br /&gt;
* [[Special:MyLanguage/巡线行走|巡线行走]]&lt;br /&gt;
* [[Special:MyLanguage/绕障行走|绕障行走]]&lt;br /&gt;
* [[Special:MyLanguage/DriveTask调度循环|DriveTask调度循环]]&lt;br /&gt;
* [[Special:MyLanguage/SimpleAgvInterface Queue机制|SimpleAgvInterface Queue机制]]&lt;br /&gt;
* [[Special:MyLanguage/车体抽象原理|车体抽象原理]]&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>