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

news2024/11/24 17:05:58

参考以往部分历程:

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_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, 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 executor
  RCCHECK(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.

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/820079.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

面试总结(三)

1.进程和线程的区别 根本区别&#xff1a;进程是操作系统分配资源的最小单位&#xff1b;线程是CPU调度的最小单位所属关系&#xff1a;一个进程包含了多个线程&#xff0c;至少拥有一个主线程&#xff1b;线程所属于进程开销不同&#xff1a;进程的创建&#xff0c;销毁&…

交流电气装置防雷接地电阻测量的方案

一、目的 为了保证交流电气装置的安全运行和防止雷电对其造成损坏&#xff0c;需要定期检测其接地装置的接地电阻&#xff0c;评估其接地效果和防雷性能。 二、原理 地凯科技认为&#xff1a;接地电阻是指接地装置与大地之间的电阻&#xff0c;它反映了接地装置与大地的接触…

【104协议】【光伏电站】电站系统中的104协议学习

文章目录 104协议学习I帧S帧U帧ASDU总结&#xff1a;关于各类帧的通俗描述建立流程详细分析 104协议学习 起始一个apdu的总长度不会超过255个字节&#xff1b; 在协议中的第二个字节会记录本apdu的长度&#xff0c;但是这个记录的长度数是除开前面两个字节之外的长读数&#xf…

【C++】开源:Linux端V4L2视频设备库

&#x1f60f;★,:.☆(&#xffe3;▽&#xffe3;)/$:.★ &#x1f60f; 这篇文章主要介绍Linux端V4L2视频设备库。 无专精则不能成&#xff0c;无涉猎则不能通。——梁启超 欢迎来到我的博客&#xff0c;一起学习&#xff0c;共同进步。 喜欢的朋友可以关注一下&#xff0c;下…

笨办法学python3进阶篇pdf,笨办法学python3pdf完整版

大家好&#xff0c;小编来为大家解答以下问题&#xff0c;笨办法学python 3电子书下载&#xff0c;笨办法学python3pdf完整版&#xff0c;今天让我们一起来看看吧&#xff01; 1、笨方法学python习题43 按照你说的 Map是一个类&#xff0c;scene_map是一老胡镇个类实例 scene_…

Scratch 详解 流畅光线追踪(盲区)引擎:角度 + 一次函数 + 区域判断

【提示1】本文将全程使用原版积木实现这一功能&#xff0c;请不要在评论区发送扩展中有相应积木。若喜欢使用扩展&#xff0c;可以自行将本文介绍的方法用扩展积木替代。 【提示2】本文中代码里出现的所有最后带*号的变量&#xff0c;均为私有变量&#xff01; 正文 近日&…

C数据结构——无向图(邻接矩阵方式) 创建与基本使用

源码注释 // // Created by Lenovo on 2022-05-13-上午 9:06. // 作者&#xff1a;小象 // 版本&#xff1a;1.0 //#include <stdio.h> #include <malloc.h>#define MAXSIZE 1000 // BFS队列可能达到的最大长度 #define MAX_AMVNUMS 100 // 最大顶点数typedef enu…

用SpringBoot实现post和get请求(多图)

用SpringBoot实现post和get请求&#xff08;多图&#xff09; 用SpringBoot实现post和get请求创建SpringBoot工程创建controller验证FAQ创建项目后依赖报错Project org.springframework.boot:spring-boot-starter-parent:3.1.2.RELEASE not found more 用SpringBoot实现post和g…

AQS构建锁和同步器的框架

1.概述 AQS全称AbstractQueuedSynchronizer&#xff0c;此类在java.util.concurrent.locks包下面&#xff0c;是一个构建锁和同步器的框架&#xff0c;比如ReentrantLock就是基于AQS来实现的。 2.AQS实现原理 AQS内部有一个由volatile修饰(保证其可见性)的变量state&#xf…

PDF文件忘记密码,怎么办?

PDF文件设置密码分为打开密码和限制密码&#xff0c;忘记了密码分别如何解密PDF密码&#xff1f; 如果是限制编辑密码忘记了&#xff0c;我们可以试着将PDF文件转换成其他格式来避开限制编辑&#xff0c;然后重新将文件转换回PDF格式就可以了。 如果因为转换之后导致文件格式…

Tuxera NTFS2023Mac强大的Mac读写工具

Mac用户在使用NTFS格式移动硬盘时&#xff0c;会遇到无法写入硬盘的情况。要想解决无法写入的问题&#xff0c;很多人选择使用Mac读写软件。面对市面上“众多”的读写硬盘软件&#xff0c;用户应该怎么选择呢&#xff1f;初次接触移动硬盘的伙伴可能不知道移动硬盘怎么和电脑连…

RabbitMQ 教程 | 第6章 RabbitMQ 配置

&#x1f468;&#x1f3fb;‍&#x1f4bb; 热爱摄影的程序员 &#x1f468;&#x1f3fb;‍&#x1f3a8; 喜欢编码的设计师 &#x1f9d5;&#x1f3fb; 擅长设计的剪辑师 &#x1f9d1;&#x1f3fb;‍&#x1f3eb; 一位高冷无情的编码爱好者 大家好&#xff0c;我是 DevO…

科大讯飞 - 基于论文摘要的文本分类与关键词抽取挑战赛(DataWhale-Camp)

文章目录 1、赛题信息2、解决方案2.1 飞桨Baseline&#xff08;提供代码&#xff09;2.2 Bert和调参2.3 chatGLMlora大模型 3、关于DataWhale-NLP 1、赛题信息 提交地址&#xff1a;https://challenge.xfyun.cn/topic/info?typeabstract-of-the-paper&chymfk4uU 项目题目…

我的会议(会议通知)

前言: 我们在实现了发布会议功能&#xff0c;我的会议功能的基础上&#xff0c;继续来实现会议通知的功能。 4.1实现的特色功能&#xff1a; 当有会议要参加时&#xff0c;通过查询会议通知可以知道会议的内容&#xff0c;以及当前会议状态&#xff08;未读&#xff09; 4.2思路…

在Linux中怎么查找文件

2023年8月1日&#xff0c;周二上午 目录 Linux的四种搜索命令find简要说明举例说明拓展阅读locate 简要说明举例说明whereis简要说明举例说明which简要说明举例说明 Linux的四种搜索命令 findlocate&#xff08;不一定内置有&#xff0c;可能要下载mlocate包&#xff09;wher…

【概念理解】HAL库的滴答定时器HAL_Delay()函数的实现原理

来源&#xff1a;bilibili视频 这里写目录标题 概述一、寄存器部分1. 控制和状态寄存器(STK_CTRL)2. 加载值寄存器&#xff08;STK_LOAD&#xff09;3.当前值寄存器&#xff08;STK_VAL&#xff09; 二、代码部分hal_delay()1. hal_initTick()滴答定时器的初始化2. 将七万二传…

Redis 客户端有哪些?

文章目录 JedisLettuceRedisson最佳实践 - 到底用哪个&#xff1f; Redis 最常见的 Java 客户端有两个&#xff0c;Jedis 和 Lettuce&#xff0c;高级客户端有 Redisson&#xff0c;见下图&#xff08;图源 Clients | Redis&#xff09; Jedis Github地址&#xff1a;redis/j…

Windows下安装Hive(包安装成功)

Windows下安装Hive Hive与Hadoop的版本选择很关键&#xff0c;千万不能选错&#xff0c;否则各种报错。一、Hive下载1.1、官网下载Hive1.2、网盘下载Hive 二、解压安装包&#xff0c;配置Hive环境变量2.1、环境变量新增&#xff1a;HIVE_HOME2.2、修改Path环境变量&#xff0c;…

Oracle免费在线编程:Oracle APEX

前提&#xff1a; 注意&#xff1a;你要有个梯子才能更稳定的访问。 不需要安装Oracle&#xff0c;但是需要注册。&#xff08;还算方便的&#xff09; 注册&登录过程 进入Oracle APEX官网&#xff0c;我们选择免费的APEX工作区即可&#xff0c;点击“免费注册”。在注册…

基于H5或者微信小程序开发GIS地图实战全套代码

1 下面有一定基础的可以不看 (1)第一篇请看 微信小程序开发天地图 (2)第二篇请看 http://GeoServer+PostgreSQL+PostGIS+Tomcat+QGIS一整套相关 (3)第三篇请看 有国产化需求的 (4)第四篇请看 支持国家EPSG:4490 2 vue+openlayers实例代码