🤖 roboto_origin_03 Wiki
首页 / IMU 子模块 / Python SDK 快速上手

roboto_imu 的 Python SDK 基于 pybind11 将 C++ 核心驱动封装为原生扩展模块 imu_py,使 Python 开发者无需编写 C++ 代码即可实时读取超核电子(HiPNUC)系列 IMU 的传感器数据。本页面向初次接触的初学者,聚焦 Python 模块的编译安装、导入配置、基础 API 调用与常见错误排查,假设你已具备 Python 基础语法知识。更底层的编译依赖与系统配置请参考前文 环境依赖与安装

Sources: src/pybind_module.cpp

环境准备

在构建 Python 模块之前,请确认系统已安装 python3-devpybind11-dev(或 ROS 2 环境下的 pybind11_vendor)。CMake 通过 find_package(Python3 COMPONENTS Interpreter Development REQUIRED)find_package(pybind11 REQUIRED) 自动探测 Python 解释器与头文件路径,若探测失败,编译将中止并提示缺失依赖。本项目要求 Python 版本不低于 3.8,且编译与运行需使用同一解释器,否则可能出现符号未定义错误。

Sources: CMakeLists.txt, package.xml

编译与安装

Python 模块并非独立构建,而是随 C++ 静态库一同编译。在 ROS 2 工作空间内执行 colcon build --packages-select roboto_imu 后,imu_py*.so 会被放置在 install/roboto_imu/lib/python3.x/site-packages/ 目录下;若采用纯 CMake 构建,则默认安装到系统前缀(如 /usr/local/lib/python3.x/site-packages/);若使用 build_deb.sh 打包部署,安装前缀固定为 /opt/roboparty。无论哪种方式,构建完成后都建议通过 find 命令定位 .so 文件,以确认 Python 模块确实已生成。

Sources: CMakeLists.txt, build_deb.sh

配置 Python 模块路径

由于安装路径并非系统默认的 dist-packages,初学者最常遇到的错误是 ModuleNotFoundError: No module named 'imu_py'。最直接的做法是将模块所在目录加入 PYTHONPATH,例如在 bash 中执行 export PYTHONPATH=/opt/roboparty/lib/python3.10/site-packages:$PYTHONPATH(请根据实际 Python 小版本号替换 3.10)。更持久的方案是在系统 site-packages 或虚拟环境的 site-packages 中创建一个 .pth 文件,如 echo "/opt/roboparty/lib/python3.10/site-packages" | sudo tee /usr/lib/python3/dist-packages/roboto-imu.pth,这样每次启动 Python 时解释器都会自动扫描该路径。完成配置后,运行 python3 -c "from imu_py import IMUDriver; print('OK')" 验证导入是否成功。

Sources: CMakeLists.txt

Python SDK 架构一览

为了帮助你理解 Python 脚本与底层硬件之间的调用关系,下图展示了 Python SDK 的分层架构。你的 Python 代码通过 import imu_py 加载由 pybind11 生成的共享对象,该对象内部持有 std::shared_ptr<IMUDriver> 并转发所有方法调用到 C++ 抽象基类,再由具体驱动完成 CAN 帧或串口字节流的收发。

graph TD
    A[Python 脚本] -->|import imu_py| B[pybind11 绑定层<br/>imu_py.so]
    B -->|调用 C++ API| C[IMUDriver 抽象基类]
    C --> D[HipnucIMUDriver 实现]
    D -->|CAN 帧| E[SocketCAN 单例]
    D -->|UART 字节流| F[SerialPort]
    E --> G[CAN 协议解析]
    F --> H[私有协议解码]

Sources: src/pybind_module.cpp

五分钟入门示例

当模块可正常导入后,即可在 Python 中创建 IMU 实例并读取数据。整个流程可分为四个步骤:导入模块、调用工厂方法 create_imu 创建实例、循环读取传感器数据、按需处理或打印结果。下图以流程图形式展现了这一最小闭环,后文将分别给出 CAN 与串口的完整可运行代码。

flowchart LR
    A[导入 imu_py] --> B[create_imu 创建实例]
    B --> C[get_quat / get_ang_vel<br/>读取数据]
    C --> D[业务处理或打印]

Sources: src/pybind_module.cpp, include/imu_driver.hpp

CAN 接口示例

以下示例展示了如何通过 CAN 接口连接 IMU。假设你的设备节点地址为 0x08,且主机 can0 接口已启用并与设备处于相同波特率。create_imubaudrate 参数在 CAN 模式下无实际作用,通常填 0 即可。实例创建后,底层会自动启动实时接收线程,将解析后的传感器数据更新到内部缓冲区,你只需调用对应的 getter 方法即可拿到最新一帧数据。

from imu_py import IMUDriver
import time

imu = IMUDriver.create_imu(
    imu_id=0x08,
    interface_type="can",
    interface="can0",
    imu_type="HIPNUC",
    baudrate=0
)

while True:
    print("Quaternion:", imu.get_quat())        # [w, x, y, z]
    print("Angular Velocity:", imu.get_ang_vel()) # [x, y, z] rad/s
    print("Linear Accel:", imu.get_lin_acc())     # [x, y, z] m/s²
    print("Temperature:", imu.get_temperature())  # °C
    time.sleep(0.1)

Sources: README_CN.md, src/pybind_module.cpp

串口接口示例

若使用串口通信,仅需将 interface_type 改为 "serial"interface 改为设备节点路径(如 "/dev/ttyUSB0"),并根据设备实际配置设置 baudrate。常见波特率包括 9600115200921600 等。串口模式下底层同样会启动独立的 SCHED_FIFO 实时接收线程,通过 select 阻塞读取并在收到完整数据包后触发解码回调,因此你的 Python 主循环无需关心字节流拼接细节。

from imu_py import IMUDriver
import time

imu = IMUDriver.create_imu(
    imu_id=0x01,
    interface_type="serial",
    interface="/dev/ttyUSB0",
    imu_type="HIPNUC",
    baudrate=115200
)

while True:
    print("Quaternion:", imu.get_quat())
    print("Angular Velocity:", imu.get_ang_vel())
    print("Linear Accel:", imu.get_lin_acc())
    print("Temperature:", imu.get_temperature())
    time.sleep(0.1)

Sources: README_CN.md, src/protocol/serial/serial_port.cpp

API 参数与方法速查

为了便于快速查阅,下表汇总了 create_imu 工厂方法的参数定义与实例可调用方法。所有 getter 方法均为线程安全的读操作,可直接在主循环中调用,但返回的是最近一次成功解码的数据快照;若设备尚未上电或通信异常,返回值可能保持初始零值。

create_imu 参数说明

参数 Python 类型 必填 说明
imu_id int 设备节点地址,CAN 时用于过滤总线上的目标设备
interface_type str 通信方式,取值为 "can""serial"
interface str CAN 接口名(如 "can0")或串口路径(如 "/dev/ttyUSB0"
imu_type str 驱动类型,当前仅支持 "HIPNUC"
baudrate int 串口波特率,CAN 场景下可忽略或填 0,默认值为 0

实例方法速查

方法 返回值 单位 / 说明
get_quat() list[float] 四元数 [w, x, y, z],无单位
get_ang_vel() list[float] 角速度 [x, y, z],单位 rad/s
get_lin_acc() list[float] 线加速度 [x, y, z],单位 m/s²
get_temperature() float 温度,单位 °C
get_imu_id() int 返回实例化时传入的设备地址

Sources: src/pybind_module.cpp, include/imu_driver.hpp

虚拟环境注意事项

许多初学者习惯在虚拟环境(venv)中开发,但需要注意 imu_py 是编译型扩展,其构建过程会绑定到具体的 Python 解释器与头文件版本。如果你使用系统 Python 编译,却在另一个虚拟环境中运行,且该虚拟环境的 Python 小版本号不同(例如系统为 3.10,venv 为 3.11),则会出现 ImportError: undefined symbollibpython 相关错误。建议始终在计划运行扩展的同一个 Python 环境中执行编译,或确保虚拟环境使用与系统一致的解释器。对于 ROS 2 用户,colcon 通常使用系统 Python,source 工作空间的 setup.bash 后即可直接导入。

Sources: CMakeLists.txt

常见问题排查

下表整理了 Python 初学者在首次使用本 SDK 时最可能遇到的五种现象及其根因与修复方法。若按照前文步骤仍无法读取数据,建议先对照此表逐项排查,再深入到硬件接口专题页面定位问题。

现象 可能原因 解决方案
ModuleNotFoundError: No module named 'imu_py' 模块路径未加入 sys.path 配置 PYTHONPATH.pth 文件
ImportError: undefined symbol: ... Python 编译与运行版本不一致 在同一 Python 环境下重新编译
Permission denied: /dev/ttyUSB0 当前用户无串口设备权限 sudo usermod -aG dialout $USER 后重新登录
can0: No such device CAN 接口未创建或未启用 执行 sudo ip link set can0 up type can bitrate 1000000
所有 getter 返回 [0.0, ...] 设备未响应或 imu_id / 波特率错误 检查物理接线、设备地址与波特率配置

Sources: README_CN.md, init_imu.sh

下一步阅读

完成本页的快速上手后,你已经能够通过 Python 读取 IMU 的实时姿态与运动数据。接下来建议根据你的硬件接口类型,深入阅读对应的配置指南以掌握排错与调优技巧;若对 Python 绑定背后的 C++ 实现感兴趣,也可翻阅 pybind11 机制专题。推荐的阅读顺序如下:首先根据接口选择 CAN 接口配置指南串口接口配置指南;随后可阅读 传感器数据访问与线程安全 以理解数据在并发场景下的更新语义;最后,若希望为其他型号 IMU 扩展 Python 支持,可研读 pybind11 Python 绑定机制 了解绑定代码的编写规范。