<?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=Medulla%E8%BD%AF%E4%BB%B6%E6%9E%B6%E6%9E%84</id>
	<title>Medulla软件架构 - 版本历史</title>
	<link rel="self" type="application/atom+xml" href="https://wiki2.lessokaji.com/index.php?action=history&amp;feed=atom&amp;title=Medulla%E8%BD%AF%E4%BB%B6%E6%9E%B6%E6%9E%84"/>
	<link rel="alternate" type="text/html" href="https://wiki2.lessokaji.com/index.php?title=Medulla%E8%BD%AF%E4%BB%B6%E6%9E%B6%E6%9E%84&amp;action=history"/>
	<updated>2026-05-16T16:54:04Z</updated>
	<subtitle>本wiki上该页面的版本历史</subtitle>
	<generator>MediaWiki 1.40.0</generator>
	<entry>
		<id>https://wiki2.lessokaji.com/index.php?title=Medulla%E8%BD%AF%E4%BB%B6%E6%9E%B6%E6%9E%84&amp;diff=1019&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=Medulla%E8%BD%AF%E4%BB%B6%E6%9E%B6%E6%9E%84&amp;diff=1019&amp;oldid=prev"/>
		<updated>2026-05-16T11:42:53Z</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;
Medulla 是 MDCS 的硬件层：它把异构硬件（电机控制器、PLC、传感器、相机、雷达）抽象成 ''IOObject'' 与 ''字段''，并提供跨进程共享内存（DObject）让上层算法订阅数据，无关进程或语言。&lt;br /&gt;
&lt;br /&gt;
Medulla is the hardware-abstraction layer of MDCS: it wraps heterogeneous hardware (motor controllers, PLCs, sensors, cameras, lidars) into '''IOObject''' instances exposing typed fields, and exposes them across processes via the '''DObject''' shared-memory bus.&lt;br /&gt;
&lt;br /&gt;
== 关键概念 / Key concepts ==&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! 概念 / Concept !! 含义 / Meaning&lt;br /&gt;
|-&lt;br /&gt;
| `IOObject` || 一切硬件抽象的基类 / base class for everything: lidars, cameras, carts. File: `D:\src\M2\MedullaCore\Types\IO.cs:47`&lt;br /&gt;
|-&lt;br /&gt;
| Sub-classes || `Lidar2DIOObject`, `Lidar3DIOObject`, `CartDefinition`, camera `MainIOObject`&lt;br /&gt;
|-&lt;br /&gt;
| `[AsInitParam]` || 启动配置字段 / start-time config field (JSON-serialised)&lt;br /&gt;
|-&lt;br /&gt;
| `[AsUpperIO]` / `[AsLowerIO]` || 上 / 下位 IO 字段 / command-down / status-up field&lt;br /&gt;
|-&lt;br /&gt;
| `[UseLadderLogic]` || 周期性控制循环（默认 50 ms）/ cyclic control loop (default 50 ms)&lt;br /&gt;
|-&lt;br /&gt;
| `[IOObjectMonitor]` || 注册字段到监控面板 / dashboard registration&lt;br /&gt;
|-&lt;br /&gt;
| `[IOObjectUtility]` / `WebUtility` || 注册方法为 UI 按钮 / web API / register as UI button / web endpoint&lt;br /&gt;
|-&lt;br /&gt;
| `DObject` || 命名共享内存（跨进程）/ named shared memory (cross-process). 详见 [[Special:MyLanguage/DObject|DObject]]&lt;br /&gt;
|-&lt;br /&gt;
| `LadderLogic&amp;lt;T&amp;gt;` || 周期性回调宿主 / cyclic-callback host&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== 体系结构 / Architecture ==&lt;br /&gt;
&lt;br /&gt;
  Plugin DLL (CartDef, Lidar2DIOObject, ...)&lt;br /&gt;
        │  reflection-loaded by name (no [Plugin] attr)&lt;br /&gt;
        ▼&lt;br /&gt;
  MedullaCore: IOObject lifecycle, threading, DObject pub/sub&lt;br /&gt;
        │&lt;br /&gt;
        ▼&lt;br /&gt;
  DObject (shared memory, cross-process)&lt;br /&gt;
        ▲       ▲&lt;br /&gt;
        │       │&lt;br /&gt;
  Detour, Clumsy, SimpleComposer — subscribers&lt;br /&gt;
&lt;br /&gt;
Medulla 既是 ''加载器'' 又是 ''运行时''：插件 DLL 通过 `io load plugins/X.dll` 启动命令载入；反射查找入口类（`MainIOObject` 或 `CartDefinition` 派生），实例化，调用 `Init()`，启动配置的 LadderLogic 周期线程。&lt;br /&gt;
&lt;br /&gt;
Medulla is both loader and runtime: plugin DLLs are loaded via the `io load plugins/X.dll` startup command; reflection finds the entry type (named `MainIOObject` or derived from `CartDefinition`), instantiates it, calls `Init()`, and spawns the configured LadderLogic threads.&lt;br /&gt;
&lt;br /&gt;
== 插件加载示例 / Plugin loading example ==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
# startup.iocmd&lt;br /&gt;
lidar = io load plugins/MyLidar.dll&lt;br /&gt;
lidar Start 192.168.0.2 2110&lt;br /&gt;
&lt;br /&gt;
cart  = io load plugins/MyCart.dll&lt;br /&gt;
cart  Init&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
`io load` 把 DLL 反射扫描后实例化入口类；其余命令通过赋值（左侧）保存引用，并把命令转发给该实例。&lt;br /&gt;
&lt;br /&gt;
`io load` reflection-scans the DLL, instantiates the entry type, and the variable assignment keeps a reference. Subsequent commands forward to the instance.&lt;br /&gt;
&lt;br /&gt;
== 上下位 IO 数据流 / Upper / lower IO data flow ==&lt;br /&gt;
见 [[Special:MyLanguage/车体抽象原理|车体抽象原理]]。简而言之：&lt;br /&gt;
* '''上位''' IO（`[AsUpperIO]`）= 调度 / Clumsy 写入命令；Medulla 转发到硬件。&lt;br /&gt;
* '''下位''' IO（`[AsLowerIO]`）= Medulla 读硬件状态；调度 / Clumsy 订阅。&lt;br /&gt;
* '''初始化参数''' IO（`[AsInitParam]`）= 启动时一次性 JSON 注入。&lt;br /&gt;
* '''监控'''（`[IOObjectMonitor]`）= 显示在 Medulla 仪表盘 + 暴露给 Web API。&lt;br /&gt;
&lt;br /&gt;
== LadderLogic 周期循环 / Ladder cycles ==&lt;br /&gt;
LadderLogic 是 Medulla 提供的 ''周期性控制循环''宿主。一个 `CartDefinition` 可以有多个 LadderLogic 嵌套类，每个 `[UseLadderLogic(IntervalMs = N)]`：&lt;br /&gt;
&lt;br /&gt;
A `CartDefinition` may declare multiple nested LadderLogic classes, each at a configured tick rate:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;csharp&amp;quot;&amp;gt;&lt;br /&gt;
[UseLadderLogic(IntervalMs = 50)]&lt;br /&gt;
public class ControlLoop : LadderLogic&amp;lt;MyCart&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
    public override void Run(MyCart self)&lt;br /&gt;
    {&lt;br /&gt;
        // 写 UpperIO → 读硬件 → 更新 LowerIO&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
[UseLadderLogic(IntervalMs = 200)]&lt;br /&gt;
public class BatteryMonitor : LadderLogic&amp;lt;MyCart&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
    public override void Run(MyCart self)&lt;br /&gt;
    {&lt;br /&gt;
        // 较慢的循环，例如电池电压采样&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== DObject 共享内存 / DObject IPC ==&lt;br /&gt;
DObject 是 Medulla 提供的 ''命名共享内存 pub/sub''：发布者写一个二进制 blob，订阅者按名字订阅，等到下一帧再读。Detour 用 DObject 读雷达数据；SimpleComposer 用 DObject 读车辆状态。详见 [[Special:MyLanguage/DObject|DObject]]。&lt;br /&gt;
&lt;br /&gt;
DObject is the named binary pub/sub channel. The publisher writes a blob, subscribers wait on the name and consume. Used by Detour for lidar, SimpleComposer for vehicle state. See the dedicated page.&lt;br /&gt;
&lt;br /&gt;
== 与 Medulla 1（旧版）的区别 / vs legacy Medulla ==&lt;br /&gt;
* `D:\src\M2\` 是 Medulla2（当前在用），`D:\src\Medulla\` 是 ''legacy''。&lt;br /&gt;
* Medulla2 引入了：DObject 替代旧 IPC、属性化 IO 表（`[AsUpperIO]` 等）、`LessokajiWeaver` 编译后处理生成代理类。&lt;br /&gt;
* 已 ''不要''使用 legacy Medulla 编写新插件。&lt;br /&gt;
&lt;br /&gt;
== 相关页面 / See also ==&lt;br /&gt;
* [[Special:MyLanguage/Medulla|Medulla]] — 主页 / canonical entry&lt;br /&gt;
* [[Special:MyLanguage/Medulla-API|Medulla-API]]&lt;br /&gt;
* [[Special:MyLanguage/DObject|DObject]]&lt;br /&gt;
* [[Special:MyLanguage/车体抽象原理|车体抽象原理]]&lt;br /&gt;
* [[Special:MyLanguage/如何适配新的雷达|如何适配新的雷达]]&lt;br /&gt;
* [[Special:MyLanguage/LessokajiWeaver编译后处理工具|LessokajiWeaver编译后处理工具]]&lt;br /&gt;
&lt;br /&gt;
[[Category:开发手册]]&lt;/div&gt;</summary>
		<author><name>Artheru</name></author>
	</entry>
</feed>