Medulla软件架构

来自MDCS wiki2
Artheru讨论 | 贡献2026年5月16日 (六) 19:42的版本 (Initial bilingual draft (auto-published))
(差异) ←上一版本 | 最后版本 (差异) | 下一版本→ (差异)
跳到导航 跳到搜索


概述 / Overview

Medulla 是 MDCS 的硬件层:它把异构硬件(电机控制器、PLC、传感器、相机、雷达)抽象成 IOObject字段,并提供跨进程共享内存(DObject)让上层算法订阅数据,无关进程或语言。

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.

关键概念 / Key concepts

概念 / Concept 含义 / Meaning
`IOObject` 一切硬件抽象的基类 / base class for everything: lidars, cameras, carts. File: `D:\src\M2\MedullaCore\Types\IO.cs:47`
Sub-classes `Lidar2DIOObject`, `Lidar3DIOObject`, `CartDefinition`, camera `MainIOObject`
`[AsInitParam]` 启动配置字段 / start-time config field (JSON-serialised)
`[AsUpperIO]` / `[AsLowerIO]` 上 / 下位 IO 字段 / command-down / status-up field
`[UseLadderLogic]` 周期性控制循环(默认 50 ms)/ cyclic control loop (default 50 ms)
`[IOObjectMonitor]` 注册字段到监控面板 / dashboard registration
`[IOObjectUtility]` / `WebUtility` 注册方法为 UI 按钮 / web API / register as UI button / web endpoint
`DObject` 命名共享内存(跨进程)/ named shared memory (cross-process). 详见 DObject
`LadderLogic<T>` 周期性回调宿主 / cyclic-callback host

体系结构 / Architecture

 Plugin DLL (CartDef, Lidar2DIOObject, ...)
       │  reflection-loaded by name (no [Plugin] attr)
       ▼
 MedullaCore: IOObject lifecycle, threading, DObject pub/sub
       │
       ▼
 DObject (shared memory, cross-process)
       ▲       ▲
       │       │
 Detour, Clumsy, SimpleComposer — subscribers

Medulla 既是 加载器 又是 运行时:插件 DLL 通过 `io load plugins/X.dll` 启动命令载入;反射查找入口类(`MainIOObject` 或 `CartDefinition` 派生),实例化,调用 `Init()`,启动配置的 LadderLogic 周期线程。

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.

插件加载示例 / Plugin loading example

# startup.iocmd
lidar = io load plugins/MyLidar.dll
lidar Start 192.168.0.2 2110

cart  = io load plugins/MyCart.dll
cart  Init

`io load` 把 DLL 反射扫描后实例化入口类;其余命令通过赋值(左侧)保存引用,并把命令转发给该实例。

`io load` reflection-scans the DLL, instantiates the entry type, and the variable assignment keeps a reference. Subsequent commands forward to the instance.

上下位 IO 数据流 / Upper / lower IO data flow

车体抽象原理。简而言之:

  • 上位 IO(`[AsUpperIO]`)= 调度 / Clumsy 写入命令;Medulla 转发到硬件。
  • 下位 IO(`[AsLowerIO]`)= Medulla 读硬件状态;调度 / Clumsy 订阅。
  • 初始化参数 IO(`[AsInitParam]`)= 启动时一次性 JSON 注入。
  • 监控(`[IOObjectMonitor]`)= 显示在 Medulla 仪表盘 + 暴露给 Web API。

LadderLogic 周期循环 / Ladder cycles

LadderLogic 是 Medulla 提供的 周期性控制循环宿主。一个 `CartDefinition` 可以有多个 LadderLogic 嵌套类,每个 `[UseLadderLogic(IntervalMs = N)]`:

A `CartDefinition` may declare multiple nested LadderLogic classes, each at a configured tick rate:

[UseLadderLogic(IntervalMs = 50)]
public class ControlLoop : LadderLogic<MyCart>
{
    public override void Run(MyCart self)
    {
        // 写 UpperIO → 读硬件 → 更新 LowerIO
    }
}

[UseLadderLogic(IntervalMs = 200)]
public class BatteryMonitor : LadderLogic<MyCart>
{
    public override void Run(MyCart self)
    {
        // 较慢的循环,例如电池电压采样
    }
}

DObject 共享内存 / DObject IPC

DObject 是 Medulla 提供的 命名共享内存 pub/sub:发布者写一个二进制 blob,订阅者按名字订阅,等到下一帧再读。Detour 用 DObject 读雷达数据;SimpleComposer 用 DObject 读车辆状态。详见 DObject

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.

与 Medulla 1(旧版)的区别 / vs legacy Medulla

  • `D:\src\M2\` 是 Medulla2(当前在用),`D:\src\Medulla\` 是 legacy
  • Medulla2 引入了:DObject 替代旧 IPC、属性化 IO 表(`[AsUpperIO]` 等)、`LessokajiWeaver` 编译后处理生成代理类。
  • 不要使用 legacy Medulla 编写新插件。

相关页面 / See also