查看“MovementDefinition详解”的源代码
←
MovementDefinition详解
跳到导航
跳到搜索
因为以下原因,您没有权限编辑本页:
您请求的操作仅限属于该用户组的用户执行:
管理员
您可以查看和复制此页面的源代码。
<languages/> == 概述 / Overview == `MovementDefinition` 是 Clumsy 中描述 ''一个运动行为''的抽象基类。每个 Movement 是一段 ''可迭代''的控制循环,由 `DriveTask` 宿主按 ''DriveTaskInterval''(默认 20 ms)周期推进。它是 Clumsy 自动驾驶的 ''基本运动语汇''。 `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'''. 定义:`D:\src\Clumsy\ClumsyCore\Pilot\MovementDefinition.cs:41-48`。 Definition: `D:\src\Clumsy\ClumsyCore\Pilot\MovementDefinition.cs:41-48`. == 契约 / Contract == <syntaxhighlight lang="csharp"> public abstract class MovementDefinition { public abstract IEnumerable<bool> Get(); } public abstract class MovementDefinition<T> : MovementDefinition { public new abstract IEnumerable<T> Get(); } </syntaxhighlight> `Get()` 返回一个 ''可迭代'';框架每次调 `MoveNext()` 推一格。 `Get()` returns an enumerable; the framework calls `MoveNext()` once per tick. * '''每次 `yield return true`''' = "继续 tick" / "keep ticking" * '''迭代器耗尽(不再 `yield`)''' = "Movement 完成" / "Movement done" == 生命周期 / Lifecycle == 你的代码 / Your code: DriveTask.WaitDriveTask(new MyMovement{...}.Get()); │ ▼ DriveTask 内部 / Inside DriveTask (D:\src\Clumsy\ClumsyCore\DriveTask.cs:104-144): new Thread + AboveNormal priority │ ▼ 循环 / loop: enumerator.MoveNext() Thread.Sleep(Configuration.conf.DriveTaskInterval) // 20 ms ... │ ▼ 完成 / done (MoveNext returns false): stopped_reason = 0 Monitor.PulseAll(wait) │ ▼ 异常 / on exception: stopped_reason = -1 capture & rethrow on Wait() 调用方 `WaitDriveTask` 在 `Monitor.Wait(wait)` 上阻塞直到完成。 Caller `WaitDriveTask` blocks on `Monitor.Wait(wait)` until completion. == 最小 Movement / Minimal Movement == <syntaxhighlight lang="csharp"> using ClumsyCore.Pilot; using ClumsyCore.DrivePlans; using System.Collections.Generic; public class MyStraight : MovementDefinition { public float dx, dy; // displacement public float basespeed = 600; // mm/s public override IEnumerable<bool> Get() { var sx = currentX; // pose at start var sy = currentY; var driver = new SteeringLineFollowing { srcX = sx, srcY = sy, dstX = sx + dx, dstY = sy + dy, basespeed = basespeed }; foreach (var t in driver.Follow()) yield return t; } } </syntaxhighlight> == [MovementTest] 属性 / Attribute == '''目标''' / Target: 类 / class '''效果''' / Effect: 在 Clumsy 测试 UI 注册一个 ''测试按钮'';按下立即在车上跑这个 Movement(车应静止 / 在仿真)。 Registers a test button in the Clumsy UI; pressing it runs the Movement on a stationary (or simulated) vehicle. <syntaxhighlight lang="csharp"> [MovementTest(name = "测试我的直线 / Test my line")] public class MyStraight : MovementDefinition { ... } </syntaxhighlight> == 可用原语 / Primitive library == Movement 通常 ''组合''下层原语而不是从零写控制律。下面是仓库里现成的: Movements usually compose lower-level primitives rather than implement control law from scratch. === ClumsyCore/Legacy/(几何跟踪基础) === {| class="wikitable" ! Primitive !! 用途 / Use |- | `SteeringLineFollowing` || 阿克曼正向纯跟踪 |- | `SteeringLineFollowingReverse` || 阿克曼反向跟踪 |- | `OmniWheelTracking` || 全向轮速跟踪 |- | `LeftRightWheelTracking` || 差速轮速跟踪 |- | `OmniBezierTracking` / `LeftRightBezierTracking` || Bezier 曲线跟踪 |- | `TrajectoryReplanningObstacleAvoidance` || 动态避障 |} === ClumsyDance/Movements/(行为聚合) === {| class="wikitable" ! Movement !! 用途 / Use |- | `SlotFollowing` || 槽位跟踪(叉车叉孔 / KIVA 腿对) |- | `ReflexDock` || 反射式对接 |- | `KivaFollowShelfOfManyLegs` || 多腿料架导航 |- | `TopHatFollowing` || 礼帽形特征跟踪 |- | `BezierMPC` || Bezier 参考的 MPC |- | `LRWheelOdometryCalculator` || 编码器积分助手 |} === ClumsyDance/Detectors/(感知) === {| class="wikitable" ! Detector !! 用途 |- | `LidarDetectTray` || 通用托盘检测(2 腿 / 3 腿可调) |- | `Lidar2dDetect2LegTray`, `Lidar2dDetect3LegTray`, `Lidar3dDetectTray` || 特化变体 |- | `Cam3dDetectTray` || 3D 相机检测 |} == MovementDefinition<T> 泛型变体 / Generic variant == 当 Movement 需要 ''返回''一个对象(如已配置好的子 Movement): When a Movement needs to ''return'' a typed handle (e.g. a pre-configured sub-Movement): <syntaxhighlight lang="csharp"> public class BuildFollower : MovementDefinition<SteeringLineFollowing> { public float srcX, srcY, dstX, dstY; public override IEnumerable<SteeringLineFollowing> Get() { yield return new SteeringLineFollowing { srcX = srcX, srcY = srcY, dstX = dstX, dstY = dstY, basespeed = 800 }; } } </syntaxhighlight> == 异常 + 中止 / Exceptions & abort == * `Get()` 内抛异常 → `DriveTask.Wait()` 返回时 ''重新抛出''。 * `PilotBase.SecurityCheck()` 在没收到控制信号超时(默认 300 ms)时调 `DriveStop()`;当前 Movement 的 enumerator 不会再被推进,但 ''资源清理责任在 Movement 作者''(在 yield 前后包 try/finally)。 * 调用者按 `WaitDriveTask(...)` 同步等;要异步用 `DriveTask.WaitDriveTask` 包在另一线程或 `SimpleAgvInterface.Queue`。 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). == 与 Pilot 的关系 / Relation to Pilot == * `PilotBase` 是 Movement 的 ''宿主进程上下文''(提供 pose、IDriveWriter 等)。 * `PilotDefinition<T>` 加 typed config。 * 95% 的车型定制不用碰 PilotBase —— 写 Movement 就够。 `PilotBase` is Movement's ''host context'' (pose, drive writers); `PilotDefinition<T>` adds typed config. 95% of customisation only needs Movements. == 常见错误 / Gotchas == * '''在 `Get()` 用 `Thread.Sleep`''' → 阻塞 DriveTask 线程,定时器漂移。正确方式:`yield return` 多次。<br> Don't `Thread.Sleep` inside `Get()`; just `yield return` multiple times. * '''Movement 跨实例共享状态''' → Movement 应是 ''可重入''的;不要用 static 字段保存进度。<br> Movements should be reentrant; don't use static fields for progress. * '''忘了在不需要继续时 `yield break`''' → 看起来在原地踏步。 * '''构造时读 pose''' → 应在 `Get()` 第一帧读,避免构造与执行间车移动了。<br> Read pose inside `Get()`, not in the ctor — otherwise the car may have moved. == 相关页面 / See also == * [[Special:MyLanguage/巡线行走|巡线行走]] * [[Special:MyLanguage/绕障行走|绕障行走]] * [[Special:MyLanguage/DriveTask调度循环|DriveTask调度循环]] * [[Special:MyLanguage/SimpleAgvInterface Queue机制|SimpleAgvInterface Queue机制]] * [[Special:MyLanguage/车体抽象原理|车体抽象原理]] * [[Special:MyLanguage/Clumsy-API|Clumsy-API]] [[Category:二次开发相关说明]] [[Category:运动控制使用手册]]
返回
MovementDefinition详解
。
导航菜单
个人工具
中文(中国大陆)
创建账号
登录
命名空间
页面
讨论
大陆简体
查看
阅读
查看源代码
查看历史
更多
导航
首页
最近更改
随机页面
MediaWiki帮助
工具
链入页面
相关更改
特殊页面
页面信息