M5ATOMS3基础04给ROS2发一个问候(micro-ROS)

2023-11-04 01:31

本文主要是介绍M5ATOMS3基础04给ROS2发一个问候(micro-ROS),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

参考以往部分历程:

1. esp32与ros2的欢乐启程 2021

2. micro-ROS之esp32与ros2资料(freertos) 2021

3. esp32发布机器人电池电压到ros2(micro-ros+CoCube) 2022

4. CoCube和Micro-ROS简单案例演示 2022


不需要僵化的区分ROS1和ROS2,借助人工智能工具,提出需求让AI解决就好。

M5ATOMS3基础03给ROS1发一个问候(rosserial)


ROS1使用:

  • rosserial

ROS2使用:

  • micro-ROS

这两种方式并不是唯一的,但是最为方便,网络上资料多,AI也熟悉并且能写出没有错误的代码。

2023年,使用端口号2023

./MicroXRCEAgent udp4 -p 2023

连接M5AtomS3成功后会显示:


 下面资料提供给人工智能,让它完成代码就好。 

#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 <std_msgs/msg/int32.h>rcl_publisher_t publisher;
std_msgs__msg__Int32 msg;
rclc_executor_t executor;
rclc_support_t support;
rcl_allocator_t allocator;
rcl_node_t node;
rcl_timer_t timer;#define LED_PIN 13#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));msg.data++;}
}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(std_msgs, msg, Int32),"micro_ros_arduino_node_publisher"));// 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));msg.data = 0;
}void loop() {delay(100);RCSOFTCHECK(rclc_executor_spin_some(&executor, RCL_MS_TO_NS(100)));
}

这段代码是一个使用MicroROS的Arduino库来创建一个ROS节点并发布一个整数消息的示例。

首先,代码包含了一些必要的头文件,包括micro_ros_arduino.h、stdio.h、rcl.h、rclc.h、std_msgs.h等。

然后,定义了一些全局变量,包括publisher、msg、executor、support、allocator、node和timer,这些变量将在后面的函数中使用。

接下来,定义了一些宏函数,包括RCCHECK和RCsoftCHECK,用于检查ROS函数的返回值并处理错误。

然后,定义了一个error_loop函数,用于在出现错误时进入一个无限循环,通过LED的开关状态来指示错误状态。

在setup函数中,进行一些初始化设置。首先,设置MicroROS传输层。然后,设置LED引脚为输出模式,并初始化为高电平。

之后,延迟2秒钟,然后初始化ROS相关组件。首先,获取默认分配器。然后,使用rclc_support_init函数初始化support。接下来,使用rclc_node_init_default函数创建节点。然后,使用rclc_publisher_init_default函数创建发布者,并指定消息类型和话题名称。接着,使用rclc_timer_init_default函数创建计时器,并指定回调函数和超时时间。最后,使用rclc_executor_init函数初始化执行器,并使用rclc_executor_add_timer函数将计时器添加到执行器中。

在loop函数中,延迟100毫秒,然后使用rclc_executor_spin_some函数让执行器处理一些消息。

总体而言,这段代码创建了一个ROS节点,该节点每秒发布一个整数消息,并通过LED的开关状态来显示发布的状态。

然后,让人工智能完成字符串发送的代码。

#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 <std_msgs/msg/string.h>  rcl_publisher_t publisher;  
std_msgs__msg__String msg;  
rclc_executor_t executor;  
rclc_support_t support;  
rcl_allocator_t allocator;  
rcl_node_t node;  
rcl_timer_t timer;  #define LED_PIN 13  #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));  msg.data = "Hello ROS!";  }  
}  void setup() {  set_microros_transports();  pinMode(LED_PIN, Output);  digitalWrite(LED_PIN, HIGH);    delay(2000);  allocator = rcl_get_default_allocator();  //create init_options  RCCHECK(rclc_support_init(&support, 0, NULL, &allocator));  // create node  RCCHECK(rclc_node_init_default(&node, "micro_ros_arduino_node", "", &support));  // create publisher  RCCHECK(rclc_publisher_init_default(  &publisher,  &node,  ROSIDL_GET_MSG_TYPE_SUPPORT(std_msgs, msg, String),  "micro_ros_arduino_node_publisher"));  // create timer,  const unsigned int timer_timeout = 1000;  RCCHECK(rclc_timer_init_default(  &timer,  &support,  RCL_MS_TO_NS(timer_timeout),  timer_callback));  // create executor  RCCHECK(rclc_executor_init(&executor, &support.context, 1, &allocator));  RCCHECK(rclc_executor_add_timer(&executor, &timer));  msg.data = "";  
}  void loop() {  delay(100);  RCSOFTCHECK(rclc_executor_spin_some(&executor, RCL_MS_TO_NS(100)));  
}#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 <std_msgs/msg/string.h>  rcl_publisher_t publisher;  
std_msgs__msg__String msg;  
rclc_executor_t executor;  
rclc_support_t support;  
rcl_allocator_t allocator;  
rcl_node_t node;  
rcl_timer_t timer;  #define LED_PIN 13  #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));  msg.data = "Hello ROS!";  }  
}  void setup() {  set_microros_transports();  pinMode(LED_PIN, Output);  digitalWrite(LED_PIN, HIGH);    delay(2000);  allocator = rcl_get_default_allocator();  //create init_options  RCCHECK(rclc_support_init(&support, 0, NULL, &allocator));  // create node  RCCHECK(rclc_node_init_default(&node, "micro_ros_arduino_node", "", &support));  // create publisher  RCCHECK(rclc_publisher_init_default(  &publisher,  &node,  ROSIDL_GET_MSG_TYPE_SUPPORT(std_msgs, msg, String),  "micro_ros_arduino_node_publisher"));  // create timer,  const unsigned int timer_timeout = 1000;  RCCHECK(rclc_timer_init_default(  &timer,  &support,  RCL_MS_TO_NS(timer_timeout),  timer_callback));  // create executor  RCCHECK(rclc_executor_init(&executor, &support.context, 1, &allocator));  RCCHECK(rclc_executor_add_timer(&executor, &timer));  msg.data = "";  
}  void loop() {  delay(100);  RCSOFTCHECK(rclc_executor_spin_some(&executor, RCL_MS_TO_NS(100)));  
}

这个示例与之前的示例类似,不同之处在于发布者发布的是字符串消息而不是整数消息。在timer回调函数中,我们将字符串消息的数据设置为"Hello ROS!",然后进行发布。其他部分与之前的示例相同。 


并不准确的AI总结

在MicroROS与ROS2之间进行通信时,需要注意以下事项:

  1. 兼容性:MicroROS和ROS2在消息传递和通信方面有所不同,因此需要确保两者之间的兼容性。在编写节点时,需要使用兼容的通信库和API。
  2. 通信协议:MicroROS和ROS2使用不同的通信协议。因此,在通信过程中,需要确保使用正确的通信协议进行消息传递。
  3. 消息格式:MicroROS和ROS2使用的消息格式可能不同。在通信过程中,需要确保消息格式的正确性,以便正确解析和传递消息。
  4. 节点间互操作性:MicroROS和ROS2之间的节点可能具有不同的功能和能力。在通信过程中,需要确保节点之间的互操作性,以便正确地交换数据和服务。
  5. 数据同步:如果MicroROS和ROS2之间存在数据同步的需求,需要确保数据在正确的时间和顺序进行传递和更新。
  6. 错误处理:在通信过程中,可能会出现各种错误和异常情况。因此,需要适当的处理和记录这些错误,以确保系统的正常运行。
  7. 跨平台支持:MicroROS和ROS2都可以在不同的操作系统和平台上运行。在通信过程中,需要考虑跨平台支持,以确保通信的稳定性和可靠性。

综上所述,在进行MicroROS与ROS2之间的通信时,需要注意这些事项,以确保通信的正确性和可靠性。

ESP32是一种嵌入式系统开发板,具有强大的处理能力和丰富的的学习资源。在ROS(机器人操作系统)通信方面,它可以同时支持ROS1和MicroROS与ROS2之间的通信。下面将比较这三种通信方式之间的差异:

1 ROS1与MicroROS

ROS1是早期的ROS版本,使用master仲裁机制进行通信。它不支持跨网络通信,因此需要使用ROS自带的ROS Master来实现节点之间的通信。而MicroROS是ROS的精简版本,专门为嵌入式系统设计,具有更小的内存占用和更快的运行速度。它支持跨网络通信,可以使用多种通信协议进行节点之间的通信。

2 MicroROS与ROS2

ROS2是ROS的最新版本,引入了新的通信机制,包括数据分发和服务质量(QoS)。它支持跨网络通信,具有更好的可靠性和实时性。MicroROS与ROS2之间的主要区别在于通信协议和QoS的支持。MicroROS使用基于UDP的通信协议,而ROS2支持多种通信协议,包括TCP和UDP。此外,MicroROS不支持QoS,而ROS2可以根据需要选择不同的QoS等级。

3 ESP32与ROSSerial

rosserial是ROS的一个串口库,可以在ESP32等嵌入式系统中使用。它支持通过串口与ROS节点进行通信,并可以进行消息的发布和订阅。在ESP32上使用rosserial进行通信时,需要配置串口参数和波特率,以确保与ROS Master的正常通信。

综上所述,ESP32可以使用rosserial与ROS1通信,使用MicroROS与ROS2通信。虽然这三种通信方式之间存在一些差异,但都可以实现ESP32与ROS节点之间的通信。选择哪种通信方式取决于具体应用场景和需求,例如对通信实时性、可靠性和网络的要求等。


Micro-ROS其实是支持QoS的。

The DDS-XRCE wire protocol is specified to be in at least TCP and UDP transport protocol, but there is room to expand to other protocols. Currently, implementations are supporting Serial links and possible to be extended to any other such Zigbee, 6LoWPAN, and more. DDS-XRCE allows setting two different delivery QoS:

  • Reliable.
  • Best-effort.

这篇关于M5ATOMS3基础04给ROS2发一个问候(micro-ROS)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/342287

相关文章

零基础学习Redis(10) -- zset类型命令使用

zset是有序集合,内部除了存储元素外,还会存储一个score,存储在zset中的元素会按照score的大小升序排列,不同元素的score可以重复,score相同的元素会按照元素的字典序排列。 1. zset常用命令 1.1 zadd  zadd key [NX | XX] [GT | LT]   [CH] [INCR] score member [score member ...]

【Linux 从基础到进阶】Ansible自动化运维工具使用

Ansible自动化运维工具使用 Ansible 是一款开源的自动化运维工具,采用无代理架构(agentless),基于 SSH 连接进行管理,具有简单易用、灵活强大、可扩展性高等特点。它广泛用于服务器管理、应用部署、配置管理等任务。本文将介绍 Ansible 的安装、基本使用方法及一些实际运维场景中的应用,旨在帮助运维人员快速上手并熟练运用 Ansible。 1. Ansible的核心概念

基于UE5和ROS2的激光雷达+深度RGBD相机小车的仿真指南(五):Blender锥桶建模

前言 本系列教程旨在使用UE5配置一个具备激光雷达+深度摄像机的仿真小车,并使用通过跨平台的方式进行ROS2和UE5仿真的通讯,达到小车自主导航的目的。本教程默认有ROS2导航及其gazebo仿真相关方面基础,Nav2相关的学习教程可以参考本人的其他博客Nav2代价地图实现和原理–Nav2源码解读之CostMap2D(上)-CSDN博客往期教程: 第一期:基于UE5和ROS2的激光雷达+深度RG

AI基础 L9 Local Search II 局部搜索

Local Beam search 对于当前的所有k个状态,生成它们的所有可能后继状态。 检查生成的后继状态中是否有任何状态是解决方案。 如果所有后继状态都不是解决方案,则从所有后继状态中选择k个最佳状态。 当达到预设的迭代次数或满足某个终止条件时,算法停止。 — Choose k successors randomly, biased towards good ones — Close

取得 Git 仓库 —— Git 学习笔记 04

取得 Git 仓库 —— Git 学习笔记 04 我认为, Git 的学习分为两大块:一是工作区、索引、本地版本库之间的交互;二是本地版本库和远程版本库之间的交互。第一块是基础,第二块是难点。 下面,我们就围绕着第一部分内容来学习,先不考虑远程仓库,只考虑本地仓库。 怎样取得项目的 Git 仓库? 有两种取得 Git 项目仓库的方法。第一种是在本地创建一个新的仓库,第二种是把其他地方的某个

音视频入门基础:WAV专题(10)——FFmpeg源码中计算WAV音频文件每个packet的pts、dts的实现

一、引言 从文章《音视频入门基础:WAV专题(6)——通过FFprobe显示WAV音频文件每个数据包的信息》中我们可以知道,通过FFprobe命令可以打印WAV音频文件每个packet(也称为数据包或多媒体包)的信息,这些信息包含该packet的pts、dts: 打印出来的“pts”实际是AVPacket结构体中的成员变量pts,是以AVStream->time_base为单位的显

C 语言基础之数组

文章目录 什么是数组数组变量的声明多维数组 什么是数组 数组,顾名思义,就是一组数。 假如班上有 30 个同学,让你编程统计每个人的分数,求最高分、最低分、平均分等。如果不知道数组,你只能这样写代码: int ZhangSan_score = 95;int LiSi_score = 90;......int LiuDong_score = 100;int Zhou

c++基础版

c++基础版 Windows环境搭建第一个C++程序c++程序运行原理注释常亮字面常亮符号常亮 变量数据类型整型实型常量类型确定char类型字符串布尔类型 控制台输入随机数产生枚举定义数组数组便利 指针基础野指针空指针指针运算动态内存分配 结构体结构体默认值结构体数组结构体指针结构体指针数组函数无返回值函数和void类型地址传递函数传递数组 引用函数引用传参返回指针的正确写法函数返回数组

【QT】基础入门学习

文章目录 浅析Qt应用程序的主函数使用qDebug()函数常用快捷键Qt 编码风格信号槽连接模型实现方案 信号和槽的工作机制Qt对象树机制 浅析Qt应用程序的主函数 #include "mywindow.h"#include <QApplication>// 程序的入口int main(int argc, char *argv[]){// argc是命令行参数个数,argv是

【MRI基础】TR 和 TE 时间概念

重复时间 (TR) 磁共振成像 (MRI) 中的 TR(重复时间,repetition time)是施加于同一切片的连续脉冲序列之间的时间间隔。具体而言,TR 是施加一个 RF(射频)脉冲与施加下一个 RF 脉冲之间的持续时间。TR 以毫秒 (ms) 为单位,主要控制后续脉冲之前的纵向弛豫程度(T1 弛豫),使其成为显著影响 MRI 中的图像对比度和信号特性的重要参数。 回声时间 (TE)