基于诺亚无人船ROS与Dronekit之间的通信浅析

news2024/10/7 10:21:48

阿木实验室的诺亚无人船上市已经有一段时间,经过对开发者们的多次调研,我们发现不少开发者都对诺亚无人船的通信实现方式感兴趣,为了帮助大家更好地理解并使用该产品,本期我们将针对诺亚无人船中所使用的linux编程技术以及ROS系统,为大家分享一些经验。

基于Ardupilot的开源自主无人船icon-default.png?t=N4P3https://www.bilibili.com/video/BV1AR4y167ne/?vd_source=83d699d29d0a56e0274cd41e59a6c3a9

基于Ardupilot平台开发的无人船——“ 诺亚(2022款) ”,不仅行驶速度快,续航时间长,还具备4G异地控制、航点规划、视频回传等功能,可应用于多种开发场景。阿木实验室,公众号:阿木实验室新品上架 | 2022款“诺亚”无人船正式开售!

提到无人船,就不得不先聊一聊ROS,什么是ROS?

ROS是机器人操作系统(Robot Operating System)的缩写,实际上它并不是我们传统的操作系统,它之所以称之为操作系统,是因为它提供的分布式软件框架以及消息通信机制让我们能够协调并控制机器人的各个组件,就像操作系统管理计算机的各个部分,让机器人开发既简单又高效。

下面我们以运行小乌龟的仿真来为大家举个例子,帮助大家更好的理解ROS之间的通信:

首先我们打开三个终端,分别输入roscore打开rosmaster节点,输入rosrun turtlesim turtlesim_nod运行小乌龟仿真节点,输入 px -ef查看系统全部进程:

这里注意看上图中圈起来的进程,前面两个进程是输入roscore命令生成的进程,因为可以看到两者父进程是4069,且4069进程挂载到pts/0当中,并且执行了命令/usr/bin/python3/opt/ros/noetic/bin/roscore。这条命令就是经过输入roscore后经过ROS的命令行脚本解释之后真正运行到Linux当中的命令,试一下就会发现直接在终端输入上面的命令也能运行roscore。那么我们就可以猜测一下,当我们启动roscore的时候发生了什么?

启动roscore时,ROS生成了两个进程,第一个是master进程,后面跟有参数--core -p 11311这里的11311是ROS系统中默认的TCP端口号(既然用的TCP网络通信来作为进程间通信禁止,那么这就意味着ROSMaster只需要和节点在同一局域网就行了,而不需要在同一主机,这也是ROS多机通信的关键),它用于ROS节点之间进行通信和信息交换。当一个ROS节点想要与另一个节点通信时,它需要首先连接到主节点(ROS Master),并向其注册自己的名称、类型、URI等信息。而这些信息的传输就是通过TCP/IP协议在11311端口上完成。

第二个进程是rosout,用来接收和发布ROS日志消息。在ROS中,日志消息被用来记录程序的运行状态信息、警告和错误等信息。上述步骤完成之后,启动的小乌龟仿真就生成了一个进程。

总的来说,ROS的节点就是一个又一个的进程,它们之间通过linux当中的进程间通信方式来交换数据,促使进程间通信更加简单。

在诺亚无人船中,我们之所以选择通过dronekit来与ROS进行通信,是因为dronekit基于Python语言开发,语法相对简单,并且对于APM飞控支持更友好,易于开发者上手。

那么问题来了,怎么让dronekit得到ROS节点的数据呢?换言之,进程间通信的方式是什么?

进程间通信的方式有很多种,比如共享内存、有名管道等,这次我们使用的是套接字通信方式。

首先,我们在无人船的机载电脑(树莓派)里实现了一个ROS节点,通过订阅话题的方式来从无人机得到想要的数据,再通过套接字通信的方式发送给用dronekit来写的控制代码。在整个流程中,无人船上的ROS节点作为一个中转站,收到无人机的话题后,就用套接字转发给无人船,接收到无人船的套接字信息就用话题转发给无人机。

在这个通信过程中,ROS节点可能遇到的问题是:ROS话题的回调函数(也就是Subscribe的最后一个参数)是一个线程,这个线程触发由ROS来决定,也就是ros::spinOnce()和ros::spin()决定,当程序运行到ros::spinOnce()的时候,才会执行一下回调函数(如果有消息),而ros::spin()则是会一直执行回调函数(如果有消息),为了解决这一问题,就需要使用到进程间通信中的套接字方式的非阻塞模式,来保持回调函数一直被监听。

ROS节点接收船信息的伪代码如下所示。主循环之前主要是套接字编程必要的初始化过程,然后等待其接收信息,若没有接收到信息就要让ROS检查一次回调函数。

int sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); //创建套接字sockfd,指定协议为UDP
struct sockaddr_in server_addr;//创建用来绑定自身信息的结构体server_addr
memset(&server_addr, 0, sizeof(server_addr));//将server_addr数据全部置0
server_addr.sin_family = AF_INET;//设置协议族
server_addr.sin_addr.s_addr = inet_addr("127.0.0.1");//设置本地IP
server_addr.sin_port = htons(8080);//设置本地端口
bind(sockfd, (const struct sockaddr *)&server_addr, sizeof(server_addr))//将IP和端口绑定
char buffer[BUFFER_SIZE];
struct sockaddr_in client_addr;//得到的有关于发送端的数据都会保存在clint_addr里面
socklen_t addr_len = sizeof(client_addr);
while(ros::ok){
    int recv_bytes = recvfrom(sock, buffer, sizeof(buffer),
                    MSG_DONTWAIT, 
                    (struct sockaddr*)&addr, &client_address_len);
                    //第四个参数为设置成非阻塞,recv_bytes为接收到的数据大小
    if(recv_bytes > 0){
        //说明接收到船的数据,就可以进行处理后,用ROS的topic发送出去
    }
    ros::spinOnce();
    rate.sleep();
}

Dronekit部分实现套接字进程间通信就更加简单方便了,代码注释非常清楚,示例如下:

localaddr = ("127.0.0.1",12345)
server_address = "127.0.0.1"
udp_socket = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)#套接字初始化
udp_socket.setblocking(False)#设置为非阻塞
udp_socket.bind(localaddr)
sendbuf = '(' + str(vehicle.location.local_frame.east) + ','
            + str(vehicle.location.local_frame.east)+')'
while True:
    #recvfrom如果没有接收到信息会抛出异常,
    try:
        data, address = udp_socket.recvfrom(1024)
        print("got server data: ", data, "IP address", address)
    except socket.error as e: #捕获这个异常,就可以知道没收到信息
        udp_socket.sendto(sendbuf, server_address)#将信息发给ROS节点

由此可见,套接字通信方式操作简单且上手难度低,可以轻松实现ROS+dronekit之间的通信。除此之外,套接字通信方式还可以实现网络通信,支持不同的主机之间进行通信,应用场景丰富。后续开发者也可以通过该通信方式在QT写一个上位机界面,通过套接字来发布指令给dronekit控制部分,甚至可以用matlab发布指令用来控制船的行进方向,可操作性强。

由于篇幅内容有限,今天的分享就先到这里了,在学习ROS+dronekit之间的通信之前,建议大家提前了解线程、进程、网络编程及Linux等方面的基础知识,避免后续的学习中略感吃力。此外,如果大家对于我们的诺亚无人船感兴趣或者在使用期间有其他方面的问题,欢迎给我们留言,共同探讨相关技术~

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

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

相关文章

2023最新互联网工程师 Java 面试题及答案整理(7 天就能吃透)

现在 Java 面试都只是背答案吗? 不背就通过不了面试,但是现在面试都问原理、问场景!Java 面试题就像我们高考时的文言文,包括古诗词,不背是不可能答出来的!当然了,除了背,还得理解&…

某球中如何驾驶西锐SR-22小飞机在美国大峡谷中穿行

某球中如何驾驶西锐SR-22小飞机在美国大峡谷中穿行 我已经厌烦了无聊的围绕机场的五边飞行了,想飞一趟跨越乡野的转场飞行了。在我常用的飞软SimplePlanes里面,我已经完成取胜了所有的竞速赛道,我想自己创建一个航路想定,最终选择…

帆软Finereport数据分页,分页查询

目标: 在数据集中一次性获取所有数据后,分页查看,导出时导出的所有数据 如图: 实现步骤: 一、在表格中点击第一列数据集的单元格,添加条件属性, 条件属性内容:&A3 % 5 0 公式解…

【Spring框架学习】了解什么是Spring框架?Spring框架有什么用?创建第一个SpringBoot项目

前言: 💞💞今天我们开始学习Spring,这里我们会了解什么是Spring,知道什么是框架,为什么要学Spring框架,框架有什么作用等等。 💟💟前路漫漫,希望大家坚持下去…

pikachu靶场-../../(目录遍历)

目录遍历, 也叫路径遍历, 由于web服务器或者web应用程序对用户输入的文件名称的安全性验证不足而导致的一种安全漏洞,使得攻击者通过利用一些特殊字符就可以绕过服务器的安全限制,访问任意的文件 (可以是web根目录以外的文件),甚至…

客户案例:CACTER邮件安全网关解决餐饮企业邮件安全痛点,有效提升防护!

客户背景 某大型餐饮企业是一家在全国范围内拥有多家连锁店的知名品牌,以优秀的产品和服务质量,严格的质量控制和管理体系,以及开创性的营销策略,赢得了广泛的客户认可和信任。 然而,正因为该企业具有良好的口碑和声誉…

sonar scanner配置

sonar scanner配置 这里记录如何配置sonar scanner扫描C/C项目代码。话不多说,先上官网链接。 文章目录 sonar scanner配置1. 环境1.1 SonarSource Build Wrapper1.2 sonar-scanner 2. 使用2.1 Compilation Database2.2 执行sonar-scanner 3. 注意 1. 环境 对于C…

记录一下CSDN的markdown新功能

新功能目录 CSDN Markdown更新了欢迎使用Markdown编辑器新的改变功能快捷键合理的创建标题,有助于目录的生成如何改变文本的样式插入链接与图片如何插入一段漂亮的代码片生成一个适合你的列表创建一个表格设定内容居中、居左、居右SmartyPants 创建一个自定义列表如…

什么是原型设计?入门最全讲解指南

原型设计在产品开发和用户体验领域扮演着至关重要的角色,产品经理通过画产品原型图,可以让需求可视化,进而快速测试和验证产品可行性,为后续推动产品研发提供坚实可靠的依据。 本文将深入探讨什么是原型设计,原型设计…

【深度学习】0-1 深度学习相关数学概念的简单总结-线性代数

线性代数 标量(scalar) 标量就是一个单独的数,只具有数值大小,而没有方向,部分有正负之分。一般用小写的变量名称表示,如a、x等。 向量(vector) 一个向量就是一列数,这…

Kubernetes集群添加新集群节点

Kubernetes集群添加新集群节点 添加worker节点 参考文档https://gitee.com/open-hand/kubeadm-ha/blob/release-1.21/docs/02/%E6%B7%BB%E5%8A%A0%20worker%20%E8%8A%82%E7%82%B9.md 添加工作节点与集群安装时初始化工作节点一样,可以在主节点上执行,也可以在要加…

【ArcGIS Pro二次开发】(39):选择面要素并统计面积(含椭球面积)

写在最前面的话: 这个工具的原型是博主学学GIS做的一个工具 ,用于统计当前所选择的面要素的面积,主要是为了解决“亩”的转换,确实是一个很方便好用的工具。大家可移步原贴参观: ArcGIS Pro 加载项(5&…

上线新装ap

1.查找ap型号 1.1视频完整版 1.得到这个ap是在5教汇聚的2/0/8口连着的,且这个口是一个互连口 <NYIST-5#J-QY-HuiJu>dis mac-address 9820-449B-10A0<NYIST-5#J-QY-HuiJu>dis lldp neighbor-information list3.得到5教汇聚的2/0/8口所连接的交换机的ip地址为192.…

直播网站如何实现?

现在的年轻人基本都爱刷 B 站和抖音&#xff0c;空闲时间还喜欢去拉勾教育看看大厂面试、热门技术分享直播&#xff0c;以及各类游戏直播。不知道你有没有思考过&#xff0c;我们每天看到的这么多音视频内容&#xff0c;是如何从采集端&#xff0c;最终呈现到我们的手机 App 上…

华为OD机试真题 JavaScript 实现【Linux 发行版的数量】【2023Q1 100分】

一、题目描述 Linux 操作系统有多个发行版&#xff0c;distrowatch.com 提供了各个发行版的资料。这些发行版互相存在关联&#xff0c;例如 Ubuntu 基于 Debian 只开发而 Mint 又基于 Ubuntu 开发&#xff0c;那么我们认为 Mint 同 Debian 也存在关联。 发行版集是一个或多个…

openEuler 开源汇智赢未来|2023开放原子全球开源峰会 openEuler 论坛成功召开

2023年6月12日&#xff0c;开放原子全球开源峰会OpenAtom openEuler论坛成功召开。论坛以“openEuler汇众智&#xff0c;奔涌向前赢未来”为主题&#xff0c;众多openEuler社区成员、重磅开发者用户以及技术专家参与本次论坛。论坛充分展示了openEuler 社区的最新成果&#xff…

LabVIEW开发呼吸分析系统

LabVIEW开发呼吸分析系统 在日常生活中&#xff0c;许多人都在练习调息法&#xff0c;但大多数人都不知道如何以完美的方式做。不当的做法不会带来适当的结果。一种使用LabVIEW分析呼吸信号的方法&#xff0c;以使人们以完美的方式练习调息。这有助于从业者按照系统指定的说明…

Linux 用yum安装软件提示 cannot find a valid baseurl for repo:base/7/x86_64 的解决方法

文章目录 一、问题原因二、处理方案&#xff1a;1. 编辑修改网卡配置文件2. 在文件末尾&#xff08;或中间&#xff09;追加DNS3. 重启网络4. 验证&#xff0c;安装想要安装的软件 一、问题原因 如下&#xff1a; 出现这个问题是因为yum在安装包的过程中&#xff0c;虽然已经联…

【NOR闪存】MT25TL256BBA8ESF-0AAT 256Mbit、MT25TL01GBBB8ESF-0AAT 1Gbit 16-SOP

器件说明&#xff1a; Micron串行NOR闪存可满足消费电子、工业、有线通信以及计算应用的需求。这些器件采用行业标准封装、引脚分配、命令集和芯片组兼容性&#xff0c;易于为各类设计所采用。这样可节省宝贵的开发时间&#xff0c;同时确保与现有和未来设计的兼容性。 这些串…

超越科幻:揭秘马斯克公司在AI、机器人、脑机接口和太空探索领域的重大突破

原创 | 文 BFT机器人 得益于特斯拉股价暴涨&#xff0c;马斯克今年财富增长超过553亿美元。 根据彭博亿万富翁指数&#xff0c;马斯克目前的净资产约为1923亿美元&#xff0c;超过前世界首富Bernard Arnault的1866亿美元&#xff0c;重回世界首富。 马斯克一直以来都是科技领域…