ROS2编译Python节点来发布和订阅的实践《2》

通过熟悉:ROS2对比ROS1的一些变化与优势(全新安装ROS2以及编译错误处理)《1》
我们大概了解到了ROS2的重新设计带来的巨大优势,最核心的就是去掉了roscore,这样就避免了因为节点管理器崩溃而使整个系统都崩溃的场景出现,通过DDS的传输协议进行数据的通信,真正做到了去中心化的设计。
虽然很多命令跟ROS1比较都有了新的变化,但很容易接受并熟悉它,也处理了在编译C++与Python的过程中常遇到的一些问题。这节主要来看下,通过Python来定义发布节点与订阅节点。

1、创建工作空间

1.1、ROS2环境

同样,我们新建一个工作空间和创建一个名叫my_pub_sub的package包,然后在这个包下面来写我们的节点。当然如果说环境包含了ROS1的情况,我们先设置ROS2的环境

source /opt/ros/dashing/setup.bash

当然最好的方法还是前面介绍的自行来选择环境:gedit ~/.bashrc

echo "ROS melodic (1) or ROS2 dashing (2)?"
read edition
if [ "$edition" -eq "1" ];then
  source /opt/ros/melodic/setup.bash
  echo using ros melodic
else
  source /opt/ros/dashing/setup.bash
  echo using ros2 dashing
fi

1.2、创建包

创建包之前,首先建立工作空间 

mkdir -p ~/my_pub_sub_ws/src
cd ~/my_pub_sub_ws/src

对于Python包的创建,生成类型--build-type需指定为ament_python,而编译C++文件指定为ament_cmake
所以这里我们的Python创建包的命令,如下:

ros2 pkg create --build-type ament_python my_pub_sub

如下图,我们将会看到自动生成了my_pub_sub/my_pub_sub的目录,以及一些配置相关文件,诸如:package.xml,setup.cfg,setup.py 

2、测试节点

我们还是使用上节的例子,来测试下新建的环境,这次也是试图没有使用rclpy依赖项,也就是没有指定参数--dependencies rclpy

2.1、PYNode.py

 新建一个Python节点文件

cd ~/my_pub_sub_ws/src/my_pub_sub/my_pub_sub
gedit PYNode.py
#!/usr/bin/env python3

import rclpy
from rclpy.node import Node

def main(args=None):
    rclpy.init(args=args)
    node = Node("ChyiChin_Node")
    node.get_logger().info("Python TEST")
    rclpy.spin(node)
    rclpy.shutdown()

if __name__ == '__main__':
    main()

加个可执行权限:chmod +x PYNode.py

当然对文件是否加可执行权限,取决于你的运行方式,这里是运行节点可以不加,有的时候如果是需要直接运行这个Python文件,比如这样的操作:./PYNode.py 就需要加上可执行权限,不然会报权限错误:bash: ./PYNode.py: Permission denied

2.2、修改setup.cfg

cd ~/my_pub_sub_ws/src/my_pub_sub
gedit setup.cfg

将 破折号 修改为 下划线 _,修改为script_dirinstall_scripts
修改之后的内容如下:

script_dir=$base/lib/my_pub_sub
[install]
install_scripts=$base/lib/my_pub_sub

2.3、修改setup.py 

cd ~/my_pub_sub_ws/src/my_pub_sub
gedit setup.py

入口处填写:"ChyiChin_Node=my_pub_sub.PYNode:main"

2.4、编译

修改好了之后,我们就开始编译这个my_pub_sub包

cd ~/my_pub_sub_ws
colcon build --packages-select my_pub_sub
source install/setup.bash

 执行节点:ros2 run my_pub_sub ChyiChin_Node

[INFO] [ChyiChin_Node]: Python TEST

一切OK,没有发现问题,看来只需要指定Python的入口函数的位置,就可以正常的执行Python文件了。所以对于在package.xml里面做修改也是不需要的,因为网上有些是在这个xml文件中做了依赖项的配置,不设置也是可以的,也能正常运行。

cd ~/my_pub_sub_ws/src/my_pub_sub
gedit package.xml
/*
<exec_depend>rclpy</exec_depend>
<exec_depend>std_msgs</exec_depend>
*/

代码比较简单,这里的rclpy库,类似ROS1中rospy的用法,主要是对节点的创建与管理,ROS2的底层是使用C语言写的,名字就是rcl库,而这个rclpy就是在这个基础上做的对Python的封装接口,对C++做的封装就是rclcpp,这样的好处就是Python与C++在调用API的时候更加的统一相似,同时对ROS2进行功能更新时,直接更新rcl库,再新增cpp与python的支持即可。

3、发布节点

配置环境和编译没有问题之后,接下来就是常见的发布与订阅操作,我们先来写一个发布的节点。 

cd ~/my_pub_sub_ws/src/my_pub_sub/my_pub_sub
gedit pub_test.py
#!/usr/bin/env python3

import rclpy
from rclpy.node import Node
from std_msgs.msg import String

class Publisher(Node):
    def __init__(self,name):
        super().__init__(name)
        self.publisher = self.create_publisher(String,"talker_topic",10)
        timer_period = 5
        self.timer = self.create_timer(timer_period,self.timer_callback)
        self.get_logger().info("hello,I'm %s!" %name)
        self.i = 0

    def timer_callback(self): 
        msg = String()
        msg.data = 'NO.%d,hello!' %(self.i)
        self.publisher.publish(msg)
        self.get_logger().info("Publishing: %s"%msg.data)
        self.i += 1

def main(args=None):
    rclpy.init(args=args)
    node = Publisher("talker") 
    rclpy.spin(node)
    rclpy.shutdown()

if __name__ == '__main__':
    main()
cd ~/my_pub_sub_ws/src/my_pub_sub
gedit setup.py

入口处填写(这个跟前面的使用逗号进行隔开):"talker=my_pub_sub.pub_test:main"

 编译:

cd ~/my_pub_sub_ws
colcon build --packages-select my_pub_sub
source install/setup.bash

运行发布节点:ros2 run my_pub_sub talker

[INFO] [talker]: hello,I'm talker!
[INFO] [talker]: Publishing: NO.0,hello!
[INFO] [talker]: Publishing: NO.1,hello!
[INFO] [talker]: Publishing: NO.2,hello!
[INFO] [talker]: Publishing: NO.3,hello!
[INFO] [talker]: Publishing: NO.4,hello!
...

 查看下话题:ros2 topic list

/parameter_events
/rosout
/talker_topic

 查看talker_topic话题当前传输的信息:ros2 topic echo /talker_topic

data: NO.9,hello!
---
data: NO.10,hello!
---
data: NO.11,hello!
---
data: NO.12,hello!

代码也比较简单,初始化一个talker节点,里面创建一个类型是String的talker_topic的话题,队列长度为10,另外在上述代码基础上增加了一个定时器,每隔5秒调用一次timer_callback函数,这个函数的作用是发布String类型的字符串。

4、订阅节点

发布节点创建好了,接下来写一个订阅这个发布信息的节点

cd ~/my_pub_sub_ws/src/my_pub_sub/my_pub_sub
gedit sub_test.py

 

#!/usr/bin/env python3

import rclpy
from rclpy.node import Node
from std_msgs.msg import String

class Subscriber(Node):
    def __init__(self,name):
        super().__init__(name)
        self.subscriber = self.create_subscription(String,"talker_topic",self.sub_callback,10)
        self.count = 0

    def sub_callback(self,msg):
        self.get_logger().info("I heard: %s" %msg.data)
        if self.count >= 3 : self.destroy_node()

def main(args=None):
    rclpy.init(args=args)
    node = Subscriber("listener")
    rclpy.spin(node)
    rclpy.shutdown()
 
if __name__ == "__main__":
    main()
cd ~/my_pub_sub_ws/src/my_pub_sub
gedit setup.py

入口处增加,同样使用逗号跟前面的隔开:"listener=my_pub_sub.sub_test:main"
这个setup.py文件的截图如下所示:

cd ~/my_pub_sub_ws
colcon build --packages-select my_pub_sub
source install/setup.bash

运行订阅节点:ros2 run my_pub_sub listener

如果关闭了发布节点,重新运行即可,这样就监听到发布的消息了: 

[INFO] [listener]: I heard: NO.0,hello!
[INFO] [listener]: I heard: NO.1,hello!
[INFO] [listener]: I heard: NO.2,hello!
[INFO] [listener]: I heard: NO.3,hello!
[INFO] [listener]: I heard: NO.4,hello!

发布与订阅,截图如下:

查看节点: ros2 node list

/talker
/listener 

恩,没有问题,正确显示一个发布节点talker和一个订阅节点listener

5、混合环境的错误

在这种混合版本的环境,很容易出现下面这样的错误:

ROS_DISTRO was set to 'dashing' before. Please make sure that the environment does not mix paths from different distributions.
ROS_DISTRO was set to 'melodic' before. Please make sure that the environment does not mix paths from different distributions.

如果使用ROS2版本: 

sudo gedit /opt/ros/melodic/share/ros_environment/catkin_env_hook/1.ros_distro.sh

将其内容注释即可:

if [ -n "$ROS_DISTRO" -a "$ROS_DISTRO" != "melodic" ]; then
  echo "ROS_DISTRO was set to '$ROS_DISTRO' before. Please make sure that the environment does not mix paths from different distributions."
fi
export ROS_DISTRO=melodic

如果使用ROS1版本:

sudo gedit /opt/ros/dashing/share/ros_environment/environment/1.ros_distro.sh

将其内容注释即可:

if [ -n "$ROS_DISTRO" -a "$ROS_DISTRO" != "dashing" ]; then
  echo "ROS_DISTRO was set to '$ROS_DISTRO' before. Please make sure that the environment does not mix paths from different distributions."
fi
export ROS_DISTRO=dashing

测试环境如果经常有ROS1和ROS2的测试的情况,那就混合环境,当然最好的情况还是只有一个版本的环境,避免一些不必要的错误出现。而且是在编译之前做这个操作,不然将会在所在工作空间的install/setup.bash中出现混合环境:

COLCON_CURRENT_PREFIX="/opt/ros/melodic"
_colcon_prefix_chain_bash_source_script "$COLCON_CURRENT_PREFIX/local_setup.bash"
COLCON_CURRENT_PREFIX="/opt/ros/dashing"
_colcon_prefix_chain_bash_source_script "$COLCON_CURRENT_PREFIX/local_setup.bash"

甚至出现下面这样的错误: 

AttributeError: type object 'type' has no attribute '_TYPE_SUPPORT' This might be a ROS 1 message type but it should be a ROS 2 message type. Make sure to source your ROS 2 workspace after your ROS 1 workspace.

所以最好的设置就是前面说的修改 ~/.bashrc 自行进行环境的选择。 

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

机器学习/sklearn 笔记:K-means,kmeans++,MiniBatchKMeans,二分Kmeans

1 K-means介绍 1.0 方法介绍 KMeans算法通过尝试将样本分成n个方差相等的组来聚类&#xff0c;该算法要求指定群集的数量。它适用于大量样本&#xff0c;并已在许多不同领域的广泛应用领域中使用。KMeans算法将一组样本分成不相交的簇&#xff0c;每个簇由簇中样本的平均值描…

【ChatGLM2-6B】Docker下部署及微调

【ChatGLM2-6B】小白入门及Docker下部署 一、简介1、ChatGLM2是什么2、组成部分3、相关地址 二、基于Docker安装部署1、前提2、CentOS7安装NVIDIA显卡驱动1&#xff09;查看服务器版本及显卡信息2&#xff09;相关依赖安装3&#xff09;显卡驱动安装 2、 CentOS7安装NVIDIA-Doc…

idea 问题合集

调试按钮失效&#xff1a; 依次点击&#xff1a;Modules-web-src-Sources&#xff0c;重启IDEA即可&#xff08;网上看到的方法&#xff0c;原因呢未明&#xff09;

Modbus故障码速查手册(故障码含义、分析原因、详细解读)

Modbus故障码速查手册 文章目录 Modbus故障码速查手册引言故障码表故障详解0x01 IllegalFunction0x02 IllegalDataAddress0x03 IllegalDataValue0x04 SlaveDeviceFailure0x05 Acknowledge0x06 SlaveDeviceBusy0x08 MemoryParityError0x0A GatewayPathUnavailable0x0B GatewayTa…

java spring-boot 修改打包的jar包名称

修改pom文件 <finalName>lzwd</finalName><build><finalName>lzwd</finalName><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plu…

IP地址定位的误差问题及解析

随着互联网的普及&#xff0c;IP地址定位成为了数字时代中不可或缺的一部分&#xff0c;被广泛应用于各种场景&#xff0c;从位置服务到网络安全。然而&#xff0c;尽管IP地址定位提供了便利&#xff0c;但其准确性仍然受到多种因素的影响&#xff0c;存在一定的误差。本文将深…

【AI考证笔记】NO.1人工智能的基础概念

以下部分内容来自于百度智能云人才认证培训讲义&#xff0c;腾讯等也有人工智能类似的讲义&#xff0c;限时免费&#xff0c;也就是不报考&#xff0c;也能系统学习&#xff0c;课程做的都是不错的。有感兴趣的朋友&#xff0c;可以去检索学习。 本系列是学习笔记&#xff0c;…

thinkphp6生成PDF自动换行

composer安装 composer require tecnickcom/tcpdf 示例 use TCPDF;public function info($university,$performance,$grade,$major){//获取到当前域名$domain request()->domain();//实例化$pdf new TCPDF(P, mm, A4, true, UTF-8, false);// 设置文档信息$pdf->SetCr…

短视频账号矩阵系统saas化批量管理部署搭建/技术

一、短视频矩阵系统建模----技术api接口--获取用户授权 技术文档分享&#xff1a; 本系统采用MySQL数据库进行存储&#xff0c;数据库设计如下&#xff1a; 1.用户表&#xff08;user&#xff09;&#xff1a; - 用户ID&#xff08;user_id&#xff09; - 用户名&#xff08;…

AIOps探索 | 应急处置中排障的降本增效方法探索(下)

文章来源&#xff1a;公众号ID-布博士&#xff08;擎创科技资深产品专家&#xff09; 哈喽~上期内容我们分享了传统调用链系统与CMDB系统的缺陷、服务所有权模型是什么、服务所有权模型分类。这期我们来说一说如何落地服务所有权模型&#xff0c;以及好用的模型推荐&#xff0…

H5(uniapp)中使用echarts

1,安装echarts npm install echarts 2&#xff0c;具体页面 <template><view class"container notice-list"><view><view class"aa" id"main" style"width: 500px; height: 400px;"></view></v…

将form表单中的省市区的3个el-select下拉框的样式调成统一的间隔距离和长度,vue3项目iot->供应商管理

省市区是用3个el-select组成的 在表单中用el-col&#xff0c;会导致3个下拉的距离不统一&#xff0c;市和区的前面也是不需要文字label的 如何解决:用vue3的:deep()进行样式穿透&#xff0c;由于el-form-item标签都是一样的&#xff0c;为了能准确的找到市的el-form-item&…

C语言众数问题(ZZULIOJ1201:众数问题)

题目描述 给定含有n个元素的多重集合S&#xff0c;每个元素在S中出现的次数称为该元素的重数。多重集S中重数最大的元素称为众数。 例如&#xff0c;S{1&#xff0c;2&#xff0c;2&#xff0c;2&#xff0c;3&#xff0c;5}。多重集S的众数是2&#xff0c;其重数为3。 编程任务…

部署系列六基于nndeploy的深度学习 图像降噪unet部署

文章目录 1.直接在源代码demo中修改2. 如何修改呢&#xff1f; https://github.com/DeployAI/nndeploy https://nndeploy-zh.readthedocs.io/zh/latest/introduction/index.html 1.直接在源代码demo中修改 如果你想运行yolo5: onnxruntime:115ms ./install/lib/demo_nndeploy_…

【华为数通HCIP | 网络工程师】821-IGP高频题、易错题之OSPF(5)

个人名片&#xff1a; &#x1f43c;作者简介&#xff1a;一名大三在校生&#xff0c;喜欢AI编程&#x1f38b; &#x1f43b;‍❄️个人主页&#x1f947;&#xff1a;落798. &#x1f43c;个人WeChat&#xff1a;hmmwx53 &#x1f54a;️系列专栏&#xff1a;&#x1f5bc;️…

Android 提示框代码 java语言

在Android中&#xff0c;你可以使用 AlertDialog 类来创建提示框。以下是一个简单的Java代码示例&#xff0c;演示如何创建和显示一个基本的提示框&#xff1a; import android.app.AlertDialog; import android.content.Context; import android.content.DialogInterface; im…

EXIT外部中断 HAL库+cubeMX

一.cubeMX外部中断配置 1.系统内核 2.中断管理 3.选择抢占优先级和响应优先级&#xff0c;共有5个等级&#xff0c;在这里就使用库函数编写代码时最常用的2位抢占优先级2位响应优先级。 4.勾选使能选项&#xff0c;后面的两个零&#xff0c;第一个代表抢占优先级的等级&#xf…

怎么申请IP地址证书?

IP地址证书&#xff0c;也称为SSL证书&#xff0c;是一种数字证书&#xff0c;用于在网络传输过程中对IP地址进行加密和解密。它是由受信任的证书颁发机构&#xff08;CA&#xff09;颁发的&#xff0c;用于证明网站所有者身份的真实性和合法性。 一、选择证书颁发机构。首先需…

图片上传加时水印

做园区巡检需求时&#xff0c;需要巡检打卡拍照上传功能&#xff0c;并且在照片上添加当前时间的水印 创建canvas拍照后拿着图片画到canvas上同时获取当前时间也画到canvas上&#xff0c;再将canvas生成base64的url拿着合成的图片url进行下面的逻辑上代码 function addWaterm…

HR9110H 单通道低压 H 桥电机驱动芯片

HR9110H为消费类产品、玩具和其它低电压或者电池供电的运动控制类应用提供了一个集成的电机驱动器解决方案。HR9110H是SOP8封装&#xff0c;且是无铅产品&#xff0c;符合环保标准。 HR9110H能够驱动一个直流有刷电机或其他诸如螺线管的器件。输出驱动模块由PMOSNMOS功率管构成…