查看“LadderLogic框架”的源代码
←
LadderLogic框架
跳到导航
跳到搜索
因为以下原因,您没有权限编辑本页:
您请求的操作仅限属于该用户组的用户执行:
管理员
您可以查看和复制此页面的源代码。
<languages/> == 概述 / Overview == '''LadderLogic''' 是 Medulla 提供的 ''周期循环宿主''。CartDefinition 插件用嵌套类 `: LadderLogic<MyCart>` + `[UseLadderLogic(IntervalMs = N)]` 声明一个定时执行的控制循环;框架按 N 毫秒间隔调用 `Operation(int iteration)`。多个循环可在同一 Cart 上共存,各自在独立线程。 '''LadderLogic''' is Medulla's ''cyclic-loop host''. A CartDefinition plugin declares a timed loop via a nested class `: LadderLogic<MyCart>` plus `[UseLadderLogic(IntervalMs = N)]`; the framework calls `Operation(int iteration)` every N ms. Multiple loops can coexist on one cart, each on its own thread. 实现:`D:\src\M2\OfficialPlugins\CartActivator\LadderLogic.cs:7-272`,属性定义 `D:\src\M2\OfficialPlugins\CartActivator\Attrs.cs:26-36`。 Implementation: `D:\src\M2\OfficialPlugins\CartActivator\LadderLogic.cs:7-272`; attribute at `Attrs.cs:26-36`. == 最小骨架 / Minimal skeleton == <syntaxhighlight lang="csharp"> public class MyCart : CartDefinition { [AsUpperIO] public float vCmd; [AsLowerIO] public float vEst; public override void Init() { // connect to hardware here } [UseLadderLogic(IntervalMs = 50)] public class Loop : LadderLogic<MyCart> { public override void Operation(int iteration) { // iteration == 0 on first tick after Init/restart self.WriteToHw(self.vCmd); self.vEst = self.ReadFromHw(); } } } </syntaxhighlight> == 属性参数 / Attribute parameters == {| class="wikitable" ! 字段 / Field !! 默认 / Default !! 含义 / Meaning |- | `logic: Type` || (自动)|| LadderLogic 子类(嵌套类自动绑定) |- | `scanInterval: int` (or `IntervalMs`)|| 50 || tick 周期(ms) |- | `realTime: bool` || false || 保留,暂未使用 / reserved |- | `resume: bool` || true || 异常后自动重启循环 / auto-restart on exception |- | `resumeRetryDelay: int` || 1000 || 重启前等多久(ms) |- | `timeoutInterval: double` || 10000 || 保留 / reserved |} == 生命周期 / Lifecycle == CartDefinition.Init() ← 你的初始化 │ ▼ CartDefinition.createLadders() ← 反射扫 [UseLadderLogic] │ ▼ 对每个属性 / for each attribute 实例化 LadderLogic<T>, 注入 self = this │ ▼ 创建 MultimediaTimer + 工作线程 │ ▼ 周期触发 / every scanInterval ms Operation(iteration: 0) ← 第一次 / first tick Operation(iteration: 1) Operation(iteration: 2) ... │ ▼ 异常时 / on exception Hedingben.ToastText(...) 如果 resume=true 等 resumeRetryDelay 后重启 / resume after delay == Tick 精度 / Tick precision == 基于 MultimediaTimer(OS 决定,Windows 约 1–15 ms 分辨率)。 Based on MultimediaTimer; OS-dependent (~1–15 ms on Windows). '''超时行为''' / Overrun: 若 `Operation()` 耗时 > scanInterval,下一 tick 排队执行(不丢 tick)。长期超时会累积延迟。 If `Operation()` exceeds scanInterval, the next tick queues behind (no tick skipping). Sustained overrun accrues latency. 【注意】 不要在 `Operation()` 里阻塞 / sleep / 等 IO 超过 scanInterval。<br> Don't block / sleep / wait IO longer than scanInterval inside `Operation()`. == 多 LadderLogic 共存 / Multiple loops == 一个 CartDefinition 可以有多个 `[UseLadderLogic]` 属性,每个一对独立的线程 + Timer: A CartDefinition can declare multiple loops, each on its own thread: <syntaxhighlight lang="csharp"> [UseLadderLogic(IntervalMs = 50)] public class CtrlLoop : LadderLogic<MyCart> { ... } // motion control 50 Hz [UseLadderLogic(IntervalMs = 200)] public class BatteryLoop : LadderLogic<MyCart> { ... } // battery / telemetry 5 Hz [UseLadderLogic(IntervalMs = 1000)] public class DiagLoop : LadderLogic<MyCart> { ... } // health 1 Hz </syntaxhighlight> 线程之间共享 cart 字段;如果同一字段同时被多个 loop 读写,自己处理同步(lock / Interlocked)。 Threads share cart fields; if multiple loops touch the same field, synchronise (lock / Interlocked). == 内置工具方法 / Built-in helpers == `LadderLogic<T>` 基类提供以下状态机助手(`LadderLogic.cs:50-272`): The `LadderLogic<T>` base class offers these state-machine helpers (`LadderLogic.cs:50-272`): {| class="wikitable" ! 方法 / Method !! 用途 / Use |- | `TriggerOnce(bool active, int millis, Action a)` || 信号持续 `millis` ms 后触发 `a()` 一次 / fire once after signal held `millis` ms |- | `WaitSignal(bool sig, int timeout)` || 等信号上升或超时 / wait for signal rising or timeout |- | `TriggerIfChanged<T>(Func<T> g, Action<T> h)` || 值变化触发 / fire when value changes |- | `FlipFlop<T>(ref T field, int millis, T[] vals)` || 周期切换值 / cycle values periodically (e.g. blinking LED) |- | `SwitcherTrigger(bool, Action, bool)` || 边沿触发一次 / edge-trigger one-shot |- | `ModSignal(Func<bool>, int delay, int span)` || 时间窗内信号检测 / time-window detection |- | `IsochronousFork(Action)` || "同步分叉",一次只跑一个 / one-at-a-time async fork |- | `PriorityActions` || 高优先级动作执行器 / priority action runner |- | `DaemonVal(float send, float read, float r, int t, Action<bool>)` || 多变量一致性看门狗 / multi-var consistency watcher |} 用这些替代裸 `if (Math.Abs(now - lastEvent) > T) ...` 的散乱时间状态机。 Use these helpers to replace ad-hoc `if (Math.Abs(now - lastEvent) > T) ...` time state-machines scattered through the loop. == 错误传播 / Error propagation == * `Operation()` 抛异常 → 框架捕获 → log 到 DLog + Hedingben toast `"Ladder broken: <msg>"` 在 UI 显示。 * 若 `resume = true`:等 `resumeRetryDelay` 后重新调用 `Operation(iteration: 0)`(iteration 重置)。 * 若 `resume = false`:循环退出,cart 进入"半工作"状态 —— 其它 loop 还在跑。 【发现】 `resume = true` 是默认值。一个 buggy 插件不会让整个进程崩,但会 ''无限重试'' —— 务必在开发期密切看 Hedingben。<br> `resume = true` is the default. A buggy plugin won't crash the process but will silently retry forever — watch Hedingben during development. == iteration 参数 / iteration parameter == * `iteration == 0`:首次 tick 或异常重启后的首次 tick;框架自动清空内部跟踪状态(如 `TriggerOnce` 的计时器)。 * `iteration > 0`:递增;可用来做 "每 N tick 做一次"。 == 调试 / Debugging == * `Hedingben` toast 是最直接的报错通道 —— 总打开。 * DLog 有详细 stack trace 用 `$ladder` 主题。 * 用 `[IOObjectMonitor]` 暴露 `iteration` 或自定义计数器到 Medulla dashboard 看跳速。 == 相关页面 / See also == * [[Special:MyLanguage/CartDefinition属性参考|CartDefinition属性参考]] * [[Special:MyLanguage/MDCS引擎适配机器人入门教学|MDCS引擎适配机器人入门教学]] * [[Special:MyLanguage/Medulla软件架构|Medulla软件架构]] * [[Special:MyLanguage/看门狗Wawa使用说明|看门狗Wawa使用说明]] [[Category:开发手册]] [[Category:二次开发相关说明]]
返回
LadderLogic框架
。
导航菜单
个人工具
中文(中国大陆)
创建账号
登录
命名空间
页面
讨论
大陆简体
查看
阅读
查看源代码
查看历史
更多
导航
首页
最近更改
随机页面
MediaWiki帮助
工具
链入页面
相关更改
特殊页面
页面信息