🤖 roboto_origin_03 Wiki
首页 / IMU 子模块 / CAN 接口配置指南

本指南面向需要在 Linux 环境下通过 SocketCAN 使用 HiPNUC 系列 IMU 的中级开发者,涵盖主机 CAN 接口的系统级启停、SDK 初始化参数含义、节点 ID 过滤规则以及常见故障排查。完成本节配置后,你将能够通过 can0can4 等标准网络接口名访问 IMU 数据。若你的应用场景涉及串口,可参考 串口接口配置指南

前置条件与依赖

在编写应用代码之前,需确保操作系统层面已具备 SocketCAN 支持。Linux 内核需编译有 cancan_raw 及对应 CAN 控制器驱动(如 mcp251xgs_usb 等)。用户空间工具依赖 can-utils 包提供的 ipcansendcandump 等命令。若使用 Python SDK,还需确保已正确安装本库的 imu_py 模块。

下表汇总了不同层级的依赖要求:

层级 依赖项 验证命令
内核 CAN 子系统与控制器驱动 ip link type can
系统工具 can-utils which candump
C++ SDK spdlog, fmt, pthread 已链接至 libimu.so
Python SDK pybind11 生成的 imu_py python -c "import imu_py"

Sources: README_CN.md

主机 CAN 接口启停流程

IMUSocketCAN 在构造时直接调用底层 socket(PF_CAN, SOCK_RAW, CAN_RAW) 并绑定到指定的网络接口,因此接口必须预先处于 UP 状态。整个配置流程遵循 Linux 网络接口标准语义。

flowchart TD
    A[确认 CAN 控制器识别] --> B[设置波特率并启用接口]
    B --> C[验证物理层状态]
    C --> D[运行 candump 确认有数据]
    D --> E[启动 SDK 应用]

can4 接口、1 Mbps 波特率为例,终端执行如下命令:

sudo ip link set can4 down
sudo ip link set can4 up type can bitrate 1000000
ip -details link show can4

ip -details 输出应包含 <UP, RUNNING, NOARP> 标志。随后可通过 candump can4 观察原始报文,确认物理层与数据链路层正常。此步骤独立于 SDK 代码,却是后续所有回调触发的先决条件。

Sources: socket_can.cpp

SDK 初始化与参数配置

在 C++ 或 Python 中创建 IMU 实例时,将 interface_type 固定为 "can",并将 interface 设为已启用的 SocketCAN 接口名称(如 can0can4)。baudrate 参数仅对串口有效,在 CAN 模式下传 0 即可。

auto imu = IMUDriver::create_imu(
    0x08,        // imu_id: 必须与设备源地址一致
    "can",       // interface_type
    "can0",      // interface
    "HIPNUC"     // imu_type
);
from imu_py import IMUDriver
imu = IMUDriver.create_imu(
    imu_id=0x08,
    interface_type="can",
    interface="can0",
    imu_type="HIPNUC",
    baudrate=0
)

参数含义如下:

参数 类型 说明
imu_id uint16_t 设备节点 ID,用于 CAN 回调过滤,必须匹配报文低 7 位源地址
interface_type string 固定为 "can",触发 HipnucIMUDriver 进入 CAN 分支
interface string SocketCAN 网络接口名,如 can0can4
imu_type string 固定为 "HIPNUC",工厂方法据此分配具体驱动
baudrate int CAN 模式下忽略,保持默认 0 即可

Sources: imu_driver.hpp, hipnuc_imu_driver.cpp, pybind_module.cpp

节点 ID 与回调过滤机制

IMUSocketCAN 采用单例模式管理每个 CAN 接口,同一接口可被多个逻辑 IMU 实例共享。HipnucIMUDriver 在构造时为当前 imu_id 注册一个回调,并将 key extractor 设为 frame.can_id & 0x7F,这意味着驱动仅响应当前节点 ID 对应的报文。

因此,imu_id 必须与实际设备的源地址(SA)一致。在 J1939 报文中,设备发送的标准帧 ID 低 7 位即为其节点地址;若配置错误,数据将到达 SocketCAN 内核缓冲区,但应用层回调不会触发,表现为数据始终为初始零值。

sequenceDiagram
    participant CAN as CAN Bus
    participant Kernel as Linux SocketCAN
    participant Rx as IMUSocketCAN<br>接收线程
    participant Filter as Key Extractor<br>(can_id & 0x7F)
    participant CB as HipnucIMUDriver<br>回调

    CAN->>Kernel: 0x0CEFxx08 (SA=0x08)
    Kernel->>Rx: can_frame
    Rx->>Filter: 提取 key = 0x08
    Filter->>CB: 命中已注册 imu_id=0x08
    CB->>CB: hipnuc_j1939_parse_frame()

Sources: hipnuc_imu_driver.cpp, hipnuc_can_common.c

设备级参数修改(波特率与输出内容)

SDK 不负责修改 IMU 设备的内部寄存器,但仓库提供了 init_imu.sh 脚本作为参考,演示如何通过 J1939 配置报文修改设备波特率及输出数据类型。该脚本通过 cansend 向目标地址发送写寄存器指令,完成后需手动将主机接口切换到新波特率。

脚本默认向 can4 接口上的节点 0x08 执行以下操作:

  1. 关闭欧拉角输出、开启四元数输出
  2. 将设备波特率修改为 1 Mbps
  3. 发送保存指令与复位指令
# 使用前需修改脚本顶部的 CAN_IF 变量
CAN_IF="can4"
bash init_imu.sh
# 脚本结束后,按提示切换主机波特率
sudo ip link set can4 up type can bitrate 1000000

该过程属于设备固件配置,与 SDK 初始化相互独立。若仅读取默认状态的 IMU,可跳过此步骤。

Sources: init_imu.sh, README_CN.md

故障排查指南

配置过程中常见问题及排查方法如下:

现象 可能原因 排查方法
Failed to create CAN socket 内核缺少 CAN 支持 检查 modprobe can_raw 是否成功
Unable to detect CAN interface canX 接口名错误或未 UP 执行 ip link show 确认接口存在且状态为 UP
cansend 成功但 get_quat() 始终返回零 imu_id 与设备 SA 不匹配 使用 candump 观察报文 ID 低 7 位,核对 imu_id
数据偶发丢失或时延大 未设置实时调度或缓冲区溢出 确认 IMUSocketCAN 线程已设为 SCHED_FIFO 优先级 80
修改波特率后无法通信 主机与设备波特率不一致 先以旧波特率验证,再同步更新两端

当遇到数据为零的情况时,建议先用 candump can0 确认总线上存在目标 ID 的报文,再逐步检查 SDK 中的 imu_idinterface 是否匹配。若需深入了解 SocketCAN 单例的实时接收线程实现,可继续阅读 SocketCAN 单例与实时接收线程;若需解析具体的 J1939 PGN 数据格式,请参阅 J1939 协议解析与 PGN 映射