STM32与ROS的无缝对接——rosserial实战开发与调试技巧
1. 为什么需要STM32与ROS对接很多做机器人开发的朋友都遇到过这样的问题上层算法跑在ROS里底层控制需要STM32实现两者怎么高效通信传统做法可能要用USB转串口或者自己定义一套通信协议不仅麻烦还容易出问题。这里就要搬出我们的救星——rosserial了。我第一次用rosserial是在做一个四足机器人项目当时需要实时传输12个舵机的角度数据到ROS做逆运动学解算。如果自己写通信协议光是调试数据格式就得花上一周。用了rosserial之后STM32直接变身ROS节点发布和订阅消息就像在PC端写ROS节点一样简单。rosserial本质上是一个串口通信协议转换工具。它把ROS的消息序列化成二进制流通过串口传输到STM32再在STM32端反序列化成ROS消息。整个过程对开发者完全透明你只需要关心业务逻辑。实测下来在115200波特率下传输IMU数据100Hz完全无压力延迟可以控制在10ms以内。2. 环境搭建全攻略2.1 PC端安装建议使用Ubuntu 18.04ROS Melodic组合这是最稳定的搭配。安装只需要两条命令sudo apt-get install ros-melodic-rosserial sudo apt-get install ros-melodic-rosserial-arduino这里有个坑要注意如果你之前装过Arduino版的rosserial可能会遇到库冲突。我建议先删除~/.arduino15目录下的ros_lib文件夹。安装完成后到catkin_ws/src目录克隆stm32专用库git clone https://github.com/yoneken/rosserial_stm322.2 STM32工程配置推荐使用STM32CubeIDE 1.8.0以上版本。新建工程时关键要配置好USART2在Connectivity选项卡启用USART2模式选择Asynchronous波特率设为115200这是rosserial默认值记得开启全局中断和DMA有个容易忽略的地方NVIC设置里要把USART2中断优先级设得比SysTick高否则在高频通信时可能丢数据。我一般设为3SysTick默认是15。配置完成后把rosserial_stm32库里的STM32Hardware.h和ros.h复制到工程Core/Inc目录。这两个文件需要根据你的硬件稍作修改// STM32Hardware.h修改示例 #define USARTx USART2 #define HANDLE_UART_IRQ HANDLE_USART2_IRQ3. 消息通信实战技巧3.1 基本消息收发在mainpp.cpp里实现setup()和loop()函数这和Arduino编程很像。举个发布IMU数据的例子#include sensor_msgs/Imu.h ros::NodeHandle nh; sensor_msgs::Imu imu_msg; ros::Publisher imu_pub(imu_data, imu_msg); void setup() { nh.initNode(); nh.advertise(imu_pub); // IMU初始化代码... } void loop() { if(nh.connected()){ // 读取IMU数据 imu_msg.linear_acceleration.x readAccelX(); // 其他字段赋值... imu_pub.publish(imu_msg); } nh.spinOnce(); }3.2 自定义消息处理当需要自定义消息时先在ROS工作空间创建msg文件比如# MyCustom.msg float32[3] position uint8 status然后在PC端重新生成库文件rosrun rosserial_stm32 make_libraries.py .把生成的Inc/文件夹拷贝到STM32工程。这里有个技巧可以用符号链接代替复制这样PC端更新消息定义时STM32工程自动同步。4. 调试中的那些坑4.1 常见错误排查问题1节点连不上ROS master检查USB转串口驱动是否安装执行ls -l /dev/tty*查看设备名给权限sudo chmod 777 /dev/ttyUSB0问题2数据接收不完整增大缓冲区大小修改ros.h中的#define SERIAL_BUFFER_SIZE 1024问题3浮点数打印异常 STM32默认不支持printf浮点数需要重定向// 在main.c添加 #ifdef __GNUC__ #define PUTCHAR_PROTOTYPE int __io_putchar(int ch) #else #define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f) #endif PUTCHAR_PROTOTYPE { HAL_UART_Transmit(huart2, (uint8_t *)ch, 1, HAL_MAX_DELAY); return ch; }4.2 性能优化技巧降低通信频率非关键数据可以降到20-30Hz使用紧凑数据类型比如用int16代替float启用压缩修改STM32Hardware.h中的#define USE_BASE64DMA传输确保串口配置了DMA模式5. 进阶应用案例5.1 多传感器融合我在无人机项目里用rosserial同时传输IMU、GPS和超声波数据。关键是要合理安排消息发布时间void loop() { static uint32_t imu_tick 0, gps_tick 0; uint32_t now HAL_GetTick(); if(now - imu_tick 10) { // 100Hz publishIMU(); imu_tick now; } if(now - gps_tick 100) { // 10Hz publishGPS(); gps_tick now; } }5.2 实时控制实现做机械臂控制时需要在STM32端实现PID闭环。我的做法是ROS下发目标位置订阅topicSTM32运行PID计算1000Hz只把关键状态数据如实际位置回传ROS50Hzvoid commandCallback(const std_msgs::Float32 cmd) { target_position cmd.data; } ros::Subscriberstd_msgs::Float32 sub(arm_command, commandCallback);6. 工程管理建议目录结构规范/RosLibs存放生成的ROS头文件/User业务代码/Drivers硬件驱动版本控制忽略编译生成文件使用.gitmodules管理rosserial_stm32子模块自动化构建 写个脚本自动生成头文件并拷贝#!/bin/bash rosrun rosserial_stm32 make_libraries.py . cp -r Inc/* ../STM32_Project/RosLibs/最后提醒大家每次修改消息定义后记得clean再rebuild工程否则可能会遇到奇怪的链接错误。我在这个坑里栽过三次跟头希望你们能避开。
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2441689.html
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!