AimRT 架构解析

引言

机器人与工业运动控制场景中,框架选型始终存在一对核心矛盾:既要支持算法快速迭代的开发灵活性,又要满足量产所需的硬实时、高稳定、低资源开销。

传统 ROS2 生态丰富、适合原型研发,但架构天生偏向科研场景,存在线程调度混乱、DDS 通信冗余、模块耦合重、资源开销臃肿、云边协同能力弱等量产短板,很难胜任高精度伺服控制、大规模分布式机器人的工业化落地。

AimRT 是智元机器人开源的新一代机器人运行时框架,基于 C++20 现代 C++ 特性构建,主打轻量高效、确定性实时、插件化解耦、云边端统一、可量产。它重构了机器人系统的生命周期管理、任务调度、跨进程通信与异步编程模型,精准解决 ROS2 的量产痛点,现已广泛应用于人形机器人、工业机械臂。

一、整体架构总览

AimRT 采用内核驱动 + 分层解耦 + 可插拔扩展的架构设计,严格遵循单一职责、依赖注入、配置驱动、异步优先四大原则。各组件边界清晰、互不侵入,具备极强的可维护性与扩展性。

整体架构分层与依赖关系如下:

graph TB
    %% 内核层:全局唯一管控中心
    subgraph 框架内核层
        Core["Core 全局核心管理器生命周期/配置/插件统一管控"]
    end

    %% 基础运行时组件:框架核心能力
    subgraph 运行时基础组件层
        Executor["Executor 任务执行器全局任务调度、实时性保障"]
        Channel["Channel 发布订阅组件数据流单向分发"]
        RPC["RPC 请求响应组件指令双向交互"]
    end

    %% 业务承载层:落地具体功能
    subgraph 业务应用层
        Module["Module 业务模块最小业务逻辑单元"]
        Pkg["Pkg 动态库包模块物理部署载体"]
    end

    %% 严格依赖关系
    Core --->|统一初始化/管控| Executor
    Core --->|统一初始化/管控| Channel
    Core --->|统一初始化/管控| RPC
    Core --->|生命周期管理| Module
    
    Pkg --->|动态承载、打包| Module
    Module --->|依赖注入调用| Executor
    Module --->|依赖注入调用| Channel
    Module --->|依赖注入调用| RPC

核心设计思想:

  1. 职责隔离:调度、通信、业务三层能力完全解耦,各司其职,避免逻辑混杂;

  2. 全局统一管控:单例 Core 统筹所有组件启停与资源管理,杜绝时序混乱与内存泄漏;

  3. 动态部署:业务以动态库 Pkg 形式打包,支持运行时加载、按需启停、版本迭代;

  4. 可插拔通信:底层通信后端可通过配置一键切换,业务代码无需改动,适配多场景部署。

二、Core:框架全局内核与资源总管

Core 是 AimRT 全局唯一的核心管控实例,是整个框架的启动入口与资源中枢,全权负责生命周期调度、配置解析、插件管理与资源注入,是系统实时性与稳定性的底层基石。

graph LR
    subgraph Core 内置核心子模块
        ConfigMgr["配置管理TOML解析、全局配置分发"]
        PluginMgr["插件管理通信/调度插件加载切换"]
        ExecMgr["执行器管理全局Executor实例维护"]
        LogMgr["日志管理统一日志输出与分级"]
        ChannelMgr["Channel通信管理话题发布订阅调度"]
        RPCMgr["RPC服务管理服务注册与请求分发"]
        ModuleMgr["模块管理Module生命周期管控"]
    end

    %% 框架生命周期时序
    Init["Initialize 全局初始化"] --> Start["Start 启动运行"]
    Start --> Shutdown["Shutdown 优雅销毁"]

    %% 启动阶段资源调度
    Init --> ExecMgr
    Init --> ChannelMgr
    Init --> RPCMgr
    Init --> ModuleMgr
核心职责 详细说明
全生命周期管控 统一调度所有组件与业务模块的初始化、启动、运行、优雅退出,规避启停混乱、任务残留、资源泄漏等问题
配置驱动管理 全局解析 TOML 配置,自动分发调度策略、通信后端、模块参数,实现配置与代码解耦
统一资源注入 通过 CoreRef 对外提供标准化资源句柄,业务无需手动创建线程、通信实例
插件热管理 支持动态加载、切换通信与调度插件,无缝适配单机实时、分布式组网、云边协同场景

AimRT 采用依赖注入模式,禁止业务直接依赖全局 Core 对象。框架通过 CoreRef 只读引用 将调度、通信、日志等资源统一注入模块,彻底隔离业务层与底层框架实现,极大提升代码可移植性与可维护性。

1
2
3
4
5
6
7
8
9
10
11
bool MyModule::Initialize(aimrt::CoreRef core) {
core_ = core;
// 获取全局执行器
auto exe = core.GetExecutorManager().GetExecutor("work_executor");
// 获取话题发布句柄
auto pub = core.GetChannelHandle().GetPublisher<MsgType>("sensor_topic");
// 获取RPC客户端句柄
auto client = core.GetRpcHandle().GetClient<Req, Resp>("control_service");
return true;
}

该机制下,底层框架升级、插件替换、策略调整均不会侵入业务代码,非常适合长期迭代与量产维护。

三、Module \& Pkg:业务最小单元与部署载体

3.1 Module:标准化业务逻辑原子

Module 是 AimRT 唯一的业务最小承载单元,所有传感器解析、运动控制、算法推理、设备驱动等业务,均需封装为独立 Module。框架为 Module 提供统一生命周期,由 Core 严格调度管控。

stateDiagram-v2
    direction LR
    [*] --> Initialize: 初始化资源、解析配置
    Initialize --> Start: 启动任务、执行业务
    Start --> Running: 正常调度运行
    Running --> Shutdown: 停止任务、释放资源
    Shutdown --> [*]: 模块销毁
1
2
3
4
5
6
7
8
9
10
class MyModule : public aimrt::ModuleBase {
public:
bool Initialize(aimrt::CoreRef core) override;
bool Start() override;
void Shutdown() override;

private:
aimrt::CoreRef core_;
};

3.2 Pkg:工程化动态部署单元

Pkg 是 Module 的物理部署载体,编译后生成跨平台动态库(.so/.dll),支持模块化打包、动态加载、版本管理,适配工业化部署规范。一个 Pkg 可聚合多个关联 Module,通过标准接口暴露模块实例,框架可按配置顺序自动初始化与启动,精准管控多模块时序依赖。

四、Executor:任务调度核心(实时性基石)

Executor 是 AimRT 调度确定性、线程安全性、系统实时性的核心保障,彻底解决 ROS2 线程泛滥、调度无序、抖动不可控、上下文频繁切换等量产痛点。AimRT 所有执行器均基于原生线程/线程池实现,协程仅为上层异步编码语法,最终所有任务均由 Executor 真实调度执行。

4.1 七大官方执行器全维度详解

AimRT 内置七类场景化执行器,全覆盖 IO 并发、CPU 计算、硬实时定时、串行控制、后台运维、系统启动等机器人业务场景,实现精细化、确定性调度。

1. asio_thread 执行器

基于 Boost.Asio 线程池实现,是 AimRT 最通用的基础并发执行器。内部维护可配置数量的常驻线程,支持任务均衡分发、高精度定时器、IO 事件监听,IO 密集型任务吞吐性能优异。主打多线程并发提速,不保证任务顺序,多线程场景需业务自行保证数据互斥。同时作为 asio_strand 的底层线程底座,是整个调度体系的基础。适用于日志上报、大数据传输、IO 轮询、通用异步任务。

2. asio_strand 执行器

挂靠 asio_thread 线程池的轻量化串行调度器,无独立线程、零额外开销。依托 Asio 串行队列机制,强制任务严格 FIFO 执行,底层多线程环境下同一时刻仅运行单个任务,天然线程安全、无需手动加锁。非常适合跨模块业务流水线、高精度运动控制、状态机流转等对时序与顺序一致性要求极高的核心业务,是工业控制确定性调度的关键能力。

3. tbb_thread 执行器

基于 Intel TBB 工作窃取线程池实现,区别于传统固定线程池,空闲线程会主动窃取繁忙线程任务,实现全自动 CPU 负载均衡。针对图像预处理、矩阵运算、批量推理、分片计算等 CPU 密集型场景深度优化,长短任务均可自适应调度,最大化挖掘多核算力,是感知与 AI 算法模块的最优执行器。

4. simple_thread 执行器

极简独立单线程执行器,所有任务串行运行,架构简单、资源占用极低、无线程竞争。但能力单一,不支持高精度定时与复杂队列调度,无并发能力。仅适用于逻辑简单、低频执行的后台轻量常驻任务,严禁用于控制、感知、算法核心链路。

5. time_wheel 执行器

基于高精度时间轮算法的硬实时定时组件,核心特性为只计时、不执行。计时周期到达后,将任务投递至业务执行器完成调度执行,有效规避传统定时器抖动大、精度差的问题,可稳定支撑 1ms/10ms 级周期任务,广泛用于伺服控制、状态轮询、超时监控等硬实时场景。

6. main_thread 执行器

绑定进程主线程的任务队列,所有任务串行执行,无并发冲突与上下文切换。仅用于框架全局初始化、资源注册、系统启停等底层系统任务,禁止执行业务逻辑与耗时阻塞任务,保障框架基础服务稳定。

7. guard_thread 执行器

独立后台守护线程,完全隔离于核心业务线程。专门承载心跳检测、状态巡检、异常上报、后台统计、进程保活等运维任务,运维任务阻塞与卡顿不会影响控制、感知等核心业务的实时性,大幅提升系统容错与稳定性。

五、通信体系:Channel 数据流与 RPC 指令交互

AimRT 构建了统一可插拔通信体系,彻底解决 ROS2 单一 DDS 协议延迟高、拷贝多、组网僵硬、实时性差的问题。整套通信能力分为 Channel 数据流广播与 RPC 请求应答两类模式,分工互补,覆盖机器人全部数据交互场景,且底层协议可配置切换、业务代码零改动。

5.1 Channel 与 RPC 差异化定位

两种通信模式面向完全不同的业务模型,适配数据流与指令流两类核心场景:

对比维度 Channel(发布订阅) RPC(请求响应)
通信模式 单向广播、多对多数据流解耦 双向应答、一对一指令交互
执行特性 发布即返回、无阻塞、无需等待对端 支持协程挂起等待、可获取执行结果与状态
典型场景 雷达、相机、IMU 传感器数据流、设备状态周期上报 伺服控制、参数配置、设备启停、指令查询交互

5.2 统一通信核心特性

AimRT 通信体系具备架构级统一优势:业务完全解耦、底层可插拔替换、能力可扩展、生命周期统一管控。Channel 支持消息 Filter 链式预处理,RPC 支持超时、重试、异步/协程等待等丰富策略,所有通信句柄由 Core 统一管理,杜绝资源泄漏。

5.3 三大可插拔通信后端

AimRT 原生支持三套通信插件,按需适配单机实时、分布式组网、生态调试三类场景:

通信后端 适用场景 核心优势
Iceoryx 单机多进程硬实时通信 共享内存真零拷贝、微秒级延迟、无运行期动态内存分配,无随机卡顿,适配高频伺服控制场景
Zenoh 多机组网、跨网段、云边协同 协议轻量化、带宽开销低、组网灵活,全方位替代传统笨重 DDS,适配分布式机器人集群
DDS(FastDDS) ROS2 生态兼容与调试 原生对接 Rviz、rosbag、ROS 功能包,仅用于开发调试与生态兼容,不做主流量实时通信

六、C++20 协程:告别回调地狱的异步范式

6.1 协程核心定位

AimRT 基于 C++20 无栈协程 构建异步业务体系,区别于 ROS2 传统回调嵌套模式与 Go 有栈协程。依托编译器状态机+堆协程帧实现,复用线程栈、挂起清空栈帧,无栈溢出风险,支持数万级轻量并发,是现代机器人异步业务的最优编码范式。

6.2 协程与 Executor 协作原理

协程是上层异步语法糖,Executor 是底层真实调度载体,二者通过 AimRTScheduler 绑定联动:

sequenceDiagram
    participant Coro as C++20 协程(业务语法层)
    participant Scheduler as AimRTScheduler(桥梁层)
    participant Exec as Executor(调度执行层)

    Coro->>Scheduler: co_await 挂起异步逻辑
    Scheduler->>Exec: 封装恢复任务,提交调度
    Scheduler-->>Coro: 协程挂起,释放线程
    Exec->>Exec: 执行任务、等待异步事件
    Exec-->>Scheduler: 事件就绪,触发恢复
    Scheduler-->>Coro: 协程恢复,继续执行后续逻辑

Executor 负责线程调度与任务执行,协程负责将碎片化回调逻辑改写为线性同步代码,兼顾开发效率与运行性能。

6.3 协程工程价值与代码示例

协程彻底解决 ROS2 多层回调嵌套、代码割裂、难以维护的问题,让异步流水线顺序编写、线性阅读:

1
2
3
4
5
6
7
8
9
co::Task<void> RobotControlPipeline() {
// 线性顺序执行,无嵌套、不阻塞线程
auto joint_state = co_await GetJointState(); // 等待关节状态
co_await MoveJoint(joint_state.target_pose); // 执行运动指令
co_await WaitArrive(); // 等待到位
co_await GraspOperation(); // 执行抓取动作
co_return;
}

七、DynamicLatch:高性能异步同步工具

DynamicLatch 是 AimRT 自研的无锁异步同步工具,用于解决「动态批量提交异步任务并等待全部完成」的场景,能力优于 C++20 标准 std::latch,支持动态增减计数、关闭锁止、高并发无锁调度。

1
2
3
4
5
6
7
8
9
10
11
// 批量异步任务等待标准用法
aimrt::util::DynamicLatch latch;

for (int i = 0; i < 1000; i++) {
executor.TryExecute(latch, [](){
// 批量异步业务任务
});
}

latch.CloseAndWait(); // 禁止新增任务并阻塞等待全部完成

八、全链路启动与运行时序

AimRT 拥有严格可控的全局启停时序,彻底规避 ROS2 启动混乱、任务乱序问题:

sequenceDiagram
    autonumber
    participant Main as 主程序
    participant Core as AimRT Core内核
    participant Pkg as 动态库Pkg
    participant Module as 业务Module
    participant Exec as 执行器

    Main->>Core: 执行全局Initialize()
    Core->>Pkg: 动态加载所有业务Pkg
    Pkg-->>Core: 导出并创建Module实例
    Core->>Module: 执行模块Initialize()初始化
    Core->>Exec: 启动所有Executor线程池
    Core->>Module: 执行模块Start()启动业务
    Note over Main,Exec: 系统实时运行、调度通信、执行业务逻辑
    Main->>Core: 触发全局Shutdown()
    Core->>Module: 执行模块Shutdown()停止业务
    Core->>Exec: 停止任务调度、回收线程资源

结语

AimRT 并非简单的 ROS2 替代品,而是一套面向工业量产、从底层重构的现代化机器人运行时架构,从设计根源解决了 ROS2 偏向科研原型、不适配工业落地的核心短板。

相较于 ROS2,AimRT 优势全方位覆盖量产核心需求:

调度层面,ROS2 依赖用户手动管理线程,极易出现线程泛滥、调度无序、抖动不可控的问题,无法支撑毫秒级硬实时控制;而 AimRT 通过七类精细化执行器实现场景化、确定性调度,严格区分并发、串行、定时、运维任务,从底层保障运动控制的时序稳定性。

通信层面,ROS2 单一依赖 DDS,拷贝冗余、延迟偏高、组网笨重;AimRT 采用可插拔通信架构,结合 Iceoryx 零拷贝实时通信与 Zenoh 轻量化分布式组网,同时兼容 DDS 生态调试,兼顾极致性能与生态兼容。