掌上单片机实验室 — RT - Thread+ROS2 浅尝(26)

        前面化解了Micro_ROS通讯问题,并在 RT-Thread Studio 环境下,使用Micro_ROS软件包中的例程,实现了STM32F411CE核心板和ROS2主机的通讯。之后还尝试修改例程 micro_ros_sub_twist.c ,实现了接收 turtle_teleop_key 所发出的 turtle1/cmd_vel 信息,很是兴奋,认为只需将由 msh 命令启动的例程纳入到我的程序中(msh本身是个独立线程,和我的程序运行无关),即可实现用 turtle_teleop_key操控小车了。

        计划第一步先将 micro_ros_sub_twist.c 示例程序略加修改后加入到我的程序中,作为一个线程(示例本身也是创建了一个线程),由我的程序启动,在收到ROS2主机信息的基础上,下一步实现在此线程中解析数据,并通过 RT-Thread的消息机制和其它线程交互,操控小车。

        本以为这是块“豆腐”,不用一天即可完成,没想到却“硌了牙”!整整花了一周时间才搞定。欲知详情,容我慢慢道来。

一、构思

        之前完成了前文所述的 ROS2 及 Micro_ROS 基本环境;这一步计划在原有的程序框架下,增加一个线程,专门负责和 ROS2 主机通讯,类似于原来程序中的命令接收线程。将收到的 ROS2 信息解析后,转发给相应线程,实现小车的操控。

        第一步想要实现的是订阅(subscribe)turtle_teleop_key 所发出的 turtle1/cmd_vel 主题,其数据格式为 twist,而 RT-Thread 软件包 Micro_ROS 中就有相应例程:micro_ros_sub_twist.c,略加修改后作为我的线程即可(从表面上看十分简单)。

        为减小不确定性,这一步都没有考虑使用收到的信息控制小车,只是将收到的内容输出即可,重点是能在我的程序框架下运行此例程,实现和 ROS2 主机交互。

二、实施

        新线程命名为:microRosThread。

        总不能直接拷贝例程吧,所以第一步先将变量名个性化:

        再按我原来的方式创建线程:

        将原来示例中的初始化部分放在线程的开始部分,和原程序中其它线程一样,先完成各自的初始化,之后进入while(1)循环:

        之后就是原来的初始化同步机制,用事件组实现所有线程均初始化完成后,再各自进入死循环执行线程任务,避免出现初始化不同步导致的错误:

        至于输出信息,因为只是作为验证,故直接拷贝原来的例程:

        将例程的原来的打印输出改为 RT-Thread 的日志输出。

        再在主程序中,按原来线程的创建逻辑添加此线程。

        至此,程序修改完毕,并不复杂;逻辑也算是清晰、简单。

三、遇阻

        本以为会很顺利,没想到编译出错。关键是出错位置均在 Micro_ROS 软件包中,自己代码中的错误很容易就消除了。

        首先是RMW目录下的 types.h 文件中的 425行出错:

        提示在 __attribute__((deprecated(msg))) 之前少东西,后请教高手后,说可以删除这部分,删除后,此错误消除(后来找到问题并解决后,此处不用删除),但新的错误出现。

        这次是编译完成,在链接过程中提示出错:

        在microRosThread 程序中,调用 set_microros_transports() 函数时,提示micro_ros_rtt.h中所声明的函数指针未定义

        此函数是将四个串口操作的函数指针传给 Micro_ROS ,实现对硬件的操作。总是提示这四个函数指针未定义。

        软件包在示例程序编译时是没有问题的,且可以正确执行。按此推论,应该不是软件包代码问题。

        首先怀疑是编译环境所致,缺少相应的路径。可 RT-Thread 编译使用了 Kconfig及Scon生成make 文件,我对此不熟,临时抱佛脚也未吃透,网上搜未果。找身边 C 语言高手请教,可人家也不了解 Kconfig及 Scon,无法轻易解决。

        不过在此过程中,发现只是这个函数有问题,将 set_microros_transports() 封掉,编译即可通过。看来问题就出在那几个函数指针上!

        至此,已反反复复折腾了近一周时间了。

        期间,我尝试直接将示例程序拷贝到我的程序文件夹中,用我的程序调用示例程序中的函数,未果。

        总觉得是 msh 执行的环境和我自己的程序不同,所以想尝试改变示例程序的激活方式,按照程序的方式启动,而非msh命令。

        既然在我的程序中通过调用方式编译不通,那就重新建一个工程,再将示例程序直接放在主函数中,通过main启动。

        按此实施,居然编译通过了;仔细观察发现,原来新建的工程主函数为 C 文件,尝试将其扩展名改为 cpp,前面的问题重现了。

        看来问题找到了:是 C++ 和 C 编译的差别所致!

        再次请教C语言高手,他说是的:C++程序编译时有name mangling 处理,会将所有程序中的函数重新命名;而C程序编译没有。

      看来问题就在此:因为 set_microros_transports() 函数中所用的几个函数定义在文件rtt_serial_transports.c 中,而我的程序当初为了学习类定义,使用了 C++,所有文件均为 cpp,新创建的 microRosThread 也是。应该就是在C++文件中调用C函数所产生的问题

四、化解

        既然明确了问题,就有办法解决。

        继续请教,他们似乎也未遇到过这类问题,但居然帮我从chatgpt 那里找到了答案:

        按此实施,针对我目前的程序,简化一下,将 microRosThread 线程改为C文件,这样和调用的 Micro_ROS 软件包的 C 文件相同,不会发生编译重命名。因为软件包内容太多,不方便修改,只能用我的程序迎合软件包。

        问题转化为我的主函数 C++ 程序如何调用 microRosThread.c 中的 C 函数,只有一个创建线程函数和主程序相关,其余均通过RT-Thread消息机制交互,不存在问题;参考chatgpt 的答案处理:

  1. 声明函数和函数指针

        2)用函数指针调用C文件中的创建函数:

        microRosThread程序不变,只是修改扩展名为C:

        编译通过:

        执行正确:

第一次实现ROS2话题订阅

        这是我第一次切身感受到 AI 的作用。

        总算从这个坑里爬出来了,不过还是有收获的!知道了C++还有个 name Mangling 机制。

五、回顾

        跌跌爬爬,总算是可以步入正轨,去实现基于 ROS2 控制小车。

        说实话,这个准备过程有点长,也有点劳神费心。回顾一下,应该是踩了三个大坑

        第一个:安装Micro_ROS;因为对linux不熟悉,加之网络问题,折腾了一下,这个没啥收获,只是觉得玩这种开源项目有点累,缺少系统、完善的支持,需要靠从网上支离破碎的信息中自己摸索、整合,得到自己的领悟,有时甚至是误打误撞。

        第二个:安装完成 Micro_ROS 后无法通过串口和硬件通讯,这个坑有点大,最后是将 ROS2及 Micro_ROS 安装在物理机器上才解决,都没有弄清楚原因,只能推测是 Linux 虚拟机操作硬件有点问题。可在linux中安装的串口助手Comcute是能正常运行啊,无语,只能推测是micro_ros_agent 有 bug,不能在虚拟机中运行。

        关于这个过程的详细描述见鱼香ROS社区帖子:

        学习第一个 MicroROS 节点时接收 ESP32 数据报 [ros2run]: Segmentation fault 错

        第三个:就是上文所描述的这个,这应该是由于我 C 语言功底不扎实所致,半路出家,没有系统学习过 C 语言,在稍微复杂一些的环境下,就有些力不从心了。

        在 RT-Thread studio 中引入软件包 micro_ros,还有一个小插曲,因为解决的比较顺利,所以没有费笔墨描述。但为避免同道的朋友们踩坑,还是在此顺带说明一下:

        在RT-Thread Studio 环境下,加入micro_ros软件包和例程后,直接编译会出错,提示很多软件包中的文件找不到,打开 packages 目录发现 src 目录内容似乎自动加载有误,按我的理解将 src 下的所有目录重新整理后,编译正常,测试通过。

        这部分内容应该在上一篇中交代,可我给那个物理机的事情搞得有点头大,忘了,在此补上。详细的说明发在 RT-Thread 社区中:

        RT-Thread-RTThread studio 中添加 Micro_ROS 软件包有 BugRT-Thread问答社区 - RT-Thread

        还好,这次总算坚持走过来了,没有半途而废。

        但愿后面不要再遇到太大的障碍,能顺利的实现我的愿望,否则将Micro_ROS作为学习素材我都觉得是不是选错了?

        因为学习过程不应该耗费在这些说不出道理的事情上,而是将精力集中在创造性劳动上,通过素材引导学习者掌握解决问题的方式、方法,尤其是在AI已如此聪明的大趋势下!

        待续……

——————————

加入microRos线程的小车程序

通过网盘分享的文件:RTT_ROS2_1.rar
链接: https://pan.baidu.com/s/1Q3nzzTkLRxURYTQF_MUu9A

提取码: t1vr

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

展现运动类型

同样&#xff0c;我们通过函数的方式将运动类型插入我们的HTML代码中 _renderWorkout(workout) {let html <li class"workout workout-${workout.type}" data-id"${workout.id}"><h2 class"workout__title">${workout.description}…

vscode 怎么下载 vsix 文件?

参考&#xff1a;https://marketplace.visualstudio.com/items?itemNameMarsCode.marscode-extension 更好的办法&#xff1a;直接去相关插件的 github repo 下载老版本 https://github.com/VSCodeVim/Vim/releases?page5 或者&#xff0c;去 open-vsx.org 下载老版本 点击这…

python 练习题

目录 1&#xff0c;输入三个整数&#xff0c;按升序输出 2&#xff0c;输入年份及1-12月份&#xff0c;判断月份属于大月&#xff0c;小月&#xff0c;闰月&#xff0c;平月&#xff0c;并输出本月天数 3&#xff0c;输入一个整数&#xff0c;显示其所有是素数因子 4&#…

我的第一个创作纪念日 —— 梦开始的地方

前言 时光荏苒&#xff0c;转眼间&#xff0c;我已经在CSDN这片技术沃土上耕耘了365天 今天&#xff0c;我迎来了自己在CSDN的第1个创作纪念日&#xff0c;这个特殊的日子不仅是对我过去努力的肯定&#xff0c;更是对未来持续创作的激励 机缘 回想起初次接触CSDN&#xff0c;那…

Rook入门:打造云原生Ceph存储的全面学习路径(上)

文章目录 一.Rook简介二.Rook与Ceph架构2.1 Rook结构体系2.2 Rook包含组件2.3 Rook与kubernetes结合的架构图如下2.4 ceph特点2.5 ceph架构2.6 ceph组件 三.Rook部署Ceph集群3.1 部署条件3.2 获取rook最新版本3.3 rook资源文件目录结构3.4 部署Rook/CRD/Ceph集群3.5 查看rook部…

【Gitlab】CICD使用minio作为分布式缓存

1、安装minio 下载适合自己系统版本的安装文件https://dl.min.io/server/minio/release/windows-amd64/ yum install xxx.rpm 2、配置/etc/profile export MINIO_ACCESS_KEYroot [ui登录账号] export MINIO_SECRET_KEYminioDev001 [ui登录密码] export MINIO_OPTS"…

奇数求和ᅟᅠ

奇数求和 C语言代码C 代码Java代码Python代码 &#x1f490;The Begin&#x1f490;点点关注&#xff0c;收藏不迷路&#x1f490; 计算非负整数 m 到 n&#xff08;包括m 和 n &#xff09;之间的所有奇数的和&#xff0c;其中&#xff0c;m 不大于 n&#xff0c;且n 不大于30…

Django 视图层

from django.shortcuts import render, HttpResponse, redirectfrom django.http import JsonResponse1. render: 渲染模板 def index(request):print(reverse(index))return render(request, "index.html")return render(request, index.html, context{name: lisi})…

手机实时提取SIM卡打电话的信令声音-蓝牙电话如何适配eSIM卡的手机

手机实时提取SIM卡打电话的信令声音 --蓝牙电话如何适配eSIM卡的手机 一、前言 蓝牙电话的海外战略中&#xff0c;由于海外智能手机市场中政策的差异性&#xff0c;对内置eSIM卡的手机进行支持是非常合理的需求。Android系列手机中&#xff0c;无论是更换通信运营商&#xf…

python3 + selenium 中用PIL获取全屏幕截图

获取当前屏幕截图非常简单&#xff0c;需要import PIL.ImageGrab。调用grab函数即可得到Image对象&#xff0c;显示图片如图所示。 高版本的PIL中的grab函数还提供有一些参数。要查看当前PIL包的版本&#xff0c;可以import然后查看其__version__属性。 如果是较高版本的PIL…

SpringBoot3 + Vue3 由浅入深的交互 基础交互教学2

目录 一、这篇文章是基础交互教学系列的续作 二、发送请求时&#xff0c;携带发送的数据json格式的参数&#xff1a;data 三、携带token请求头&#xff0c;进行JWT校验 四、实现throw抛出异常&#xff0c;并交互显示在前端的界面 一、这篇文章是基础交互教学系列的续作 大…

UIE与ERNIE-Layout:智能视频问答任务初探

内容来自百度飞桨ai社区UIE与ERNIE-Layout&#xff1a;智能视频问答任务初探&#xff1a; 如有侵权&#xff0c;请联系删除 1 环境准备 In [2] # 安装依赖库 !pip install paddlenlp --upgrade !pip install paddleocr --upgrade !pip install paddlespeech --upgrade In …

Tomcat新手成长之路:安装部署优化全解析(下)

接上篇《Tomcat新手成长之路&#xff1a;安装部署优化全解析&#xff08;上&#xff09;》: link 文章目录 7.应用部署7.1.上下文7.2.启动时进行部署7.3.动态应用部署 8.Tomcat 类加载机制8.1.简介8.2.类加载器定义8.3.XML解析器和 Java 9.JMS监控9.1.简介9.2.启用 JMX 远程监…

vue项目部署到github pages后页面显示不出来??

问题&#xff1a; 当我们在命令行执行 npm run build 后&#xff0c;项目的目录下会生成一个 dist 文件夹&#xff0c;它里面又包含一个 static 文件夹和一个 index.html 文件&#xff0c;这是 webpack 最终打包好的文件 项目上传到仓库后发现页面为空&#xff0c;找不到文件路…

用 React 编写一个笔记应用程序

这篇文章会教大家用 React 编写一个笔记应用程序。用户可以创建、编辑、和切换 Markdown 笔记。 1. nanoid nanoid 是一个轻量级和安全的唯一字符串ID生成器&#xff0c;常用于JavaScript环境中生成随机、唯一的字符串ID&#xff0c;如数据库主键、会话ID、文件名等场景。 …

“指标管理系统”是什么?企业如何搭建指标管理系统?

在当今数字化时代&#xff0c;数据已成为企业决策的重要依据。然而&#xff0c;海量数据中如何筛选出关键指标&#xff0c;并对其进行有效管理&#xff0c;成为了众多企业面临的难题。为此&#xff0c;指标管理系统应运而生&#xff0c;它旨在帮助企业规范化定义、统一管理和高…

数学建模——Topsis法

数模评价类&#xff08;2&#xff09;——Topsis法 概述 Topsis:Technique for Order Preference by Similarity to Ideal Solution 也称优劣解距离法&#xff0c;该方法的基本思想是&#xff0c;通过计算每个备选方案与理想解和负理想解之间的距离&#xff0c;从而评估每个…

LuaForWindows_v5.1.5-52.exe

Releases rjpcomputing/luaforwindows GitHub #lua C:\Users\Administrator\Desktop\test.lua print("Hello lua&#xff01;") print("ZengWenFeng 13805029595")

HTTP协议详解:从HTTP/1.0到HTTP/3的演变与优化

深入浅出&#xff1a;从头到尾全面解析HTTP协议 一、HTTP协议概述 1.1 HTTP协议简介 HTTP&#xff08;HyperText Transfer Protocol&#xff0c;超文本传输协议&#xff09;是互联网上应用最广泛的通信协议之一。它用于客户端与服务器之间的数据传输&#xff0c;尤其是在Web…

AI高中数学教学视频生成技术:利用通义千问、MathGPT、视频多模态大模型,语音大模型,将4个模型融合 ,生成高中数学教学视频,并给出实施方案。

大家好&#xff0c;我是微学AI&#xff0c;今天给大家介绍一下AI高中数学教学视频生成技术&#xff1a;利用通义千问、MathGPT、视频多模态大模型&#xff0c;语音大模型&#xff0c;将4个模型融合 &#xff0c;生成高中数学教学视频&#xff0c;并给出实施方案。本文利用专家模…