🤖 roboto_origin_03 Wiki
首页 / 电机子模块 / 架构总览与模块划分

本文从物理目录结构、逻辑分层设计和模块依赖关系三个维度,系统性地介绍 roboto_motors SDK 的整体架构。理解这些顶层设计决策,是后续深入各子系统实现细节、甚至扩展新电机品牌或通信后端的前提。本代码库面向多品牌伺服电机(达妙 DM、EVO、LeadRobot)提供统一的 C++/Python 控制接口,并在通信层抽象了 CAN 2.0、CAN-FD 与 EtherCAT 三种总线形态。

Sources: CMakeLists.txt

逻辑分层架构

SDK 采用经典的分层架构,自上而下可分为语言绑定层核心抽象层电机驱动实现层通信协议层基础设施层。各层之间通过显式接口契约交互,下层对上层透明,而上层不感知下层具体实现。这种结构使得新增一个电机品牌或更换总线后端时,无需改动上层业务代码。

flowchart TB
    subgraph L1["语言绑定层"]
        PY["pybind_module.cpp<br/>Python SDK 导出"]
    end

    subgraph L2["核心抽象层"]
        MD["MotorDriver 抽象基类<br/>工厂方法 create_motor()"]
    end

    subgraph L3["电机驱动实现层"]
        DM["DmMotorDriver"]
        EVO["EvoMotorDriver"]
        LRO["LroMotorDriver"]
    end

    subgraph L4["通信协议层"]
        subgraph CAN["CAN 2.0"]
            CAN_ISO["MotorsCAN 接口"]
            SOC["MotorsSocketCAN<br/>单例 + 无锁队列"]
        end
        subgraph CANFD["CAN-FD"]
            CANFD_ISO["MotorsCANFD 接口"]
            SOCFD["MotorsSocketCANFD<br/>单例 + 无锁队列"]
        end
        subgraph ECAT["EtherCAT (预留)"]
            ECAT_ISO["MotorsEtherCAT 接口"]
        end
    end

    subgraph L5["基础设施层"]
        UTIL["utils.hpp<br/>日志 / 限幅 / 计时器"]
    end

    L1 --> L2
    L2 --> DM
    L2 --> EVO
    L2 --> LRO
    DM --> CAN_ISO
    DM --> CANFD_ISO
    EVO --> CAN_ISO
    EVO --> CANFD_ISO
    LRO --> CANFD_ISO
    CAN_ISO --> SOC
    CANFD_ISO --> SOCFD
    DM --> UTIL
    EVO --> UTIL
    LRO --> UTIL
    SOC --> UTIL
    SOCFD --> UTIL

核心设计意图:MotorDriver 基类定义了所有电机公共行为的契约(初始化、锁止、MIT/位置/速度控制、状态刷新、错误清除等),而通信协议层进一步将帧发送与回调注册抽象为 MotorsCAN / MotorsCANFD / MotorsEtherCAT 三个独立接口。电机驱动实现层位于两者之间,负责将高层控制指令翻译成特定品牌的总线帧格式,并通过协议层接口完成物理收发。这种双层抽象(设备抽象 + 总线抽象)是系统能够横向扩展的根本。

Sources: motor_driver.hpp, can_iso.hpp, canfd_iso.hpp

物理目录与构建单元

代码的物理组织严格映射到逻辑分层。src/ 下的每个一级子目录在 CMake 中对应一个独立静态库,最终由顶层 CMakeLists.txt 汇总链接为 motors 主库,并生成 motors_py Python 扩展模块。

src/
├── motor_driver.cpp          # 工厂方法与基类日志初始化
├── pybind_module.cpp         # Python 绑定入口
├── utils.hpp                 # 跨模块工具集
├── CMakeLists.txt            # 聚合 drivers / protocol
├── drivers/
│   ├── CMakeLists.txt
│   ├── dm/                   # dm_motors 静态库
│   ├── evo/                  # evo_motors 静态库
│   └── lro/                  # lro_motors 静态库
└── protocol/
    ├── CMakeLists.txt
    ├── can/                  # motors_can 静态库
    ├── canfd/                # motors_canfd 静态库
    ├── can_iso.hpp           # CAN 2.0 抽象接口
    ├── canfd_iso.hpp         # CAN-FD 抽象接口
    └── ethercat_iso.hpp      # EtherCAT 抽象接口 (预留)

顶层构建脚本显式声明了所有子库的最终链接关系:motors 依赖 dm_motors evo_motors lro_motors motors_can motors_canfd。这意味着如果未来加入第四个品牌(如注释中预留的 XYN),只需新增一个静态库并追加到链接列表即可,不会破坏现有模块的编译边界。

Sources: src/CMakeLists.txt, CMakeLists.txt

模块职责对照表

下表按从顶至底的顺序列出各模块的职责边界、关键类/文件以及它们对外提供的核心价值。

模块 核心文件 主要职责 对外暴露的关键接口
Python 绑定 src/pybind_module.cpp 通过 pybind11 将 C++ 类和方法导出为 Python 模块 motors_py MotorDriver.create_motor(), motor_mit_cmd(), get_motor_pos()
核心抽象 include/motor_driver.hpp<br>src/motor_driver.cpp 定义电机统一接口契约与工厂方法;管理跨模块 spdlog 日志器 MotorDriver 基类、create_motor() 静态工厂
DM 驱动 src/drivers/dm/dm_motor_driver.hpp/cpp 达妙 DM 电机协议转换:MIT/位置/速度指令编码、状态解码、寄存器读写 DmMotorDriver 继承 MotorDriver
EVO 驱动 src/drivers/evo/evo_motor_driver.hpp/cpp EVO 电机协议转换:含 Flash 烧录、多反馈类型解析、CAN-FD 扩展帧支持 EvoMotorDriver 继承 MotorDriver
LRO 驱动 src/drivers/lro/lro_motor_driver.hpp/cpp LeadRobot 电机协议转换:配置模式、查询模式、零位设置、错误清除 LroMotorDriver 继承 MotorDriver
CAN 协议 src/protocol/can_iso.hpp<br>src/protocol/can/socket_can.hpp/cpp 定义 CAN 2.0 抽象接口;提供基于 Linux SocketCAN 的单例实现,含收发线程与无锁发送队列 MotorsCAN 接口、MotorsSocketCAN::get()
CAN-FD 协议 src/protocol/canfd_iso.hpp<br>src/protocol/canfd/socket_canfd.hpp/cpp 定义 CAN-FD 抽象接口;提供 SocketCAN-FD 单例实现,结构与 CAN 模块对称 MotorsCANFD 接口、MotorsSocketCANFD::get()
EtherCAT 协议 src/protocol/ethercat_iso.hpp 定义 EtherCAT 抽象接口(帧结构、回调类型),预留 SOEM/IgH 后端接入点 MotorsEtherCAT 接口
基础设施 src/utils.hpp 提供限幅、数值映射、L1/L2 范数、高精度计时器、日志器初始化等跨模块工具 limit(), range_map(), Timer, setup_logger()

各电机驱动模块仅依赖其所需的协议子集:DM 同时支持 CAN 与 CAN-FD,EVO 同样兼容两者,而 LRO 当前仅依赖 CAN-FD(代码中 EtherCAT 部分已被注释预留)。这种按需依赖避免了不必要的编译耦合。

Sources: dm_motor_driver.hpp, evo_motor_driver.hpp, lro_motor_driver.hpp

模块间依赖关系

从链接依赖角度,整个系统呈现为“倒置树”形状:顶层 motors 静态库聚合所有子库,而 Python 扩展 motors_py 唯一依赖 motors。子库之间不存在横向依赖——例如 dm_motors 不引用 evo_motors,它们只共享公共的 motor_driver.hpp 头文件和 utils.hpp 工具集。

flowchart LR
    PY["motors_py<br/>(Python扩展)"]
    MOT["motors<br/>(主静态库)"]
    DM["dm_motors"]
    EVO["evo_motors"]
    LRO["lro_motors"]
    CAN["motors_can"]
    CANFD["motors_canfd"]

    PY --> MOT
    MOT --> DM
    MOT --> EVO
    MOT --> LRO
    MOT --> CAN
    MOT --> CANFD
    DM --> CAN
    DM --> CANFD
    EVO --> CAN
    EVO --> CANFD
    LRO --> CANFD

这种依赖结构带来两个工程优势:一是增量编译友好,修改单个品牌驱动不会触发全量重编译;二是安装接口清晰,motors 库作为唯一对外暴露的 C++ 链接目标,配合 include/motor_driver.hpp 公共头文件,即可满足绝大多数集成场景。

Sources: CMakeLists.txt

横向扩展机制

架构在两个维度上为扩展预留了明确的接入点,这也是理解“模块划分”深层意图的关键。

新增电机品牌:开发者需要创建新的子目录(如 src/drivers/xyn/),继承 MotorDriver 并实现全部纯虚方法,然后在 src/motor_driver.cpp 的工厂方法中追加分支判断。协议层已有的 MotorsCAN / MotorsCANFD 接口可直接复用,无需重写 SocketCAN 逻辑。

新增通信后端:以 CAN-FD 为例,当前仅有 MotorsSocketCANFD 一个实现,但 MotorsCANFD 接口的 get() 工厂方法在设计上已预留 backend 参数(如 "socketcan""ethercat""shm")。未来若需加入基于共享内存或 EtherCAT 桥接的 CAN-FD 后端,只需新增一个实现类并注册到工厂即可,所有电机驱动代码零改动。

Sources: motor_driver.cpp, canfd_iso.hpp

建议阅读路径

架构总览的意义在于建立全局认知,下一步可根据实际关注点深入特定模块: