我覺得如果使用這個人的micro_ros通信協議,就不用再去Ubuntu或者Windows上面自己寫驅動程序了,
利用micro_ros實現esp32與ros2的通訊
Tianci
?
天津大學 工學博士
參考:https://github.com/micro-ROS/micro_ros_arduino
https://blog.csdn.net/ZhangRelay/article/details/101394537
- micro_ros可以理解為一個運行在嵌入式平臺的輕量級ros,其好處是建立了一套上位機平臺(主要運行ubuntu+ros)與下位機平臺(MCU)的通訊機制,包括串口、UDP、wifi等,省去了我們編寫通訊協議的煩惱。
- 這套通訊機制最大的好處是可以將下位機平臺(MCU)當作ros中的一個Node,實現topic的發布、訂閱,以及service、action等等。可以說是無縫兼容ros。
- 個人粗淺的理解,ros最大的方便就是提供了一個基于Node的分布式通訊機制。
本文所用安裝環境:
- 上位機:旭日x3派 (ros2 foxy+ubuntu 20.04)
- 下位機:M5stack Atom Lite(esp32 core)
0. micro_ros與micro_ros_arduino的安裝
參考我之前寫的一篇記錄micro_ros配置記錄 - 知乎
特別注意:
- 2GB內存的旭日x3派開啟swap,否則micro_ros_agent的build過程容易內存不足;
- 網絡環境務必能夠通暢無阻的訪問github,否則大概率失敗!
1. 下位機配置
1.1 arduino支持包安裝
我這里使用的下位機是M5stack Atom Lite,其核心是esp32,但我用arduino框架進行開發。
理論上,所有支持arduino開發的嵌入式平臺應該都可以。
注意:務必安裝自己嵌入式平臺對應的arduino支持包。
正確安裝M5stack支持包后,在開發板管理中應該出現M5 stack相關的信息。
image-20220716210240849
1.2 下位機代碼
#include <micro_ros_arduino.h>#include <stdio.h>
#include <rcl/rcl.h>
#include <rcl/error_handling.h>
#include <rclc/rclc.h>
#include <rclc/executor.h>#include <geometry_msgs/msg/twist.h> //changed!rcl_publisher_t publisher;
geometry_msgs__msg__Twist msg; //changed!-->modify msg type <twist__struct.h>
rclc_executor_t executor;
rclc_support_t support;
rcl_allocator_t allocator;
rcl_node_t node;
rcl_timer_t timer;#define LED_PIN 27 //changed!-->Modify M5 stack Atom Lite LED pin#define RCCHECK(fn) { rcl_ret_t temp_rc = fn; if((temp_rc != RCL_RET_OK)){error_loop();}}
#define RCSOFTCHECK(fn) { rcl_ret_t temp_rc = fn; if((temp_rc != RCL_RET_OK)){}}void error_loop(){while(1){digitalWrite(LED_PIN, !digitalRead(LED_PIN));delay(100);}
}void timer_callback(rcl_timer_t * timer, int64_t last_call_time)
{ RCLC_UNUSED(last_call_time);if (timer != NULL) {RCSOFTCHECK(rcl_publish(&publisher, &msg, NULL));static int cnt = 0;msg.linear.x = 0.2; //const linear.xmsg.angular.z = 1.0 - 0.001*cnt; //variable angular.zcnt++;}
}void setup() {set_microros_transports();pinMode(LED_PIN, OUTPUT);digitalWrite(LED_PIN, HIGH); delay(2000);allocator = rcl_get_default_allocator();//create init_optionsRCCHECK(rclc_support_init(&support, 0, NULL, &allocator));// create nodeRCCHECK(rclc_node_init_default(&node, "micro_ros_arduino_node", "", &support));// create publisherRCCHECK(rclc_publisher_init_default(&publisher,&node,ROSIDL_GET_MSG_TYPE_SUPPORT(geometry_msgs, msg, Twist),"turtle1/cmd_vel")); //changed!-->modify topic name// create timer,const unsigned int timer_timeout = 1000;RCCHECK(rclc_timer_init_default(&timer,&support,RCL_MS_TO_NS(timer_timeout),timer_callback));// create executorRCCHECK(rclc_executor_init(&executor, &support.context, 1, &allocator));RCCHECK(rclc_executor_add_timer(&executor, &timer));// changed!-->msg initializationmsg.linear.x=0;msg.linear.y=0;msg.linear.z=0;msg.angular.x=0;msg.angular.y=0;msg.angular.z=0;
}void loop() {delay(100);RCSOFTCHECK(rclc_executor_spin_some(&executor, RCL_MS_TO_NS(100)));
}
1.3 代碼解析
- 代碼基于micro_ros_arduino的示例代碼micro-ros_publisher,對其進行簡單修改。
- ros2中turtle接收的msg類型為twist,所以首先添加twist頭文件,并定義msg類型為twist
#include <geometry_msgs/msg/twist.h> //changed! geometry_msgs__msg__Twist msg; //changed!-->modify msg type <twist__struct.h>
- 將msg中的變量初始化為0
// changed!-->msg initialization msg.linear.x=0; msg.linear.y=0; msg.linear.z=0; msg.angular.x=0; msg.angular.y=0; msg.angular.z=0;
- 修改發布的topic的名字,修改為turtle1/cmd_vel。
- 這一topic name要與ros2中turtlesim接收的topic name一致
// create publisher RCCHECK(rclc_publisher_init_default( &publisher, &node, ROSIDL_GET_MSG_TYPE_SUPPORT(geometry_msgs, msg, Twist), "turtle1/cmd_vel")); //changed!-->modify topic name
- 在定時器回調函數中對線速度和角速度進行處理
- 線速度恒定,角速度變化
void timer_callback(rcl_timer_t * timer, int64_t last_call_time) { RCLC_UNUSED(last_call_time); if (timer != NULL) { RCSOFTCHECK(rcl_publish(&publisher, &msg, NULL)); static int cnt = 0; msg.linear.x = 0.2; //const linear.x msg.angular.z = 1.0 - 0.001*cnt; //variable angular.z cnt++; } }
- 修改LED燈的管腳號(非必須)
2. 上位機配置
將下位機代碼燒錄后,將下位機通過串口連接上位機,這里我使用usb串口的方式連接。
微信圖片_20220717085646
為了顯示turtle的運動,旭日x3派需要連接hdmi或者遠程VNC,我使用的后者。
新建終端,source一下ros2,再source一下micro_ros。
source /opt/tros/setup.bash #或者 source /opt/ros/foxy/setup.bash
cd /microros_ws/ #進入micro_ros的工作空間
source install/setup.bash #source一下,也可以將這些命令添加到 /.bashrc
- 首先提升串口讀寫權限(確保自己的串口是ttyUSB0,因硬件而異)
sudo chmod -R 777 /dev/ttyUSB0
- 開啟micro_agent
ros2 run micro_ros_agent micro_ros_agent serial --dev /dev/ttyUSB0
- 按下下位機的復位鍵(特別注意,需要按下復位鍵)
image-20220717084958430
- 重新開啟一個終端,打開turtlesim_node
ros2 run turtlesim turtlesim_node
- 此時可以看到turtle在運動了
image-20220717085058875
3. 其他
- publisher示例代碼的話題發布頻率默認為1Hz,可以進行調整,10Hz沒問題。但是想要100Hz往上就不行了
- 需要更高的話題發布頻率需要使用rclc_publisher_init_best_effort代替rclc_publisher_init_default
- 但是best_effort的pub也需要best_effort的sub,所以當使用best_effort發布twist時,turtle不會運動,因為沒有使用best_effort的sub來接收。關于這個可以參考:https://docs.ros.org/en/rolling/Concepts/About-Quality-of-Service-Settings.html#qos-compatibilities