在Jetson Nano上学习ROS的记录(版本Ubuntu18.04,课程来源赵虚左老师的《ROS理论与实践》)第九章 重名问题、分布式通信

系列文章目录

第一章 ROS空间创建、helloworld的实现、开启多个节点
第二章 话题通信
第三章 服务通信
第四章 参数服务器
第五章 常用指令
第六章 通信机制实操
第七章 ROS通信机制进阶(常用API、Python模块的导入)
第八章 元功能包、节点运行管理launch文件(teleop_twist安装方法)
第九章 重名问题、分布式通信
第十章-第一节 TF坐标变换(内含PyKDL 和PyInit__tf2功能缺失等解决)
第十章-第二节 TF坐标变换实操
第十章-第三节 rosbag、rqt工具箱
第十一章-第一节 机器人系统仿真(URDF相关)
第十一章-第二节 机器人系统仿真(Gazebo相关)
第十二章 机器人导航(仿真)


前言

现在大二,之前大一有幸参加了2021的国赛,很壮烈的拿了个江苏赛区的二等奖。但发现无人机这个题,真的是往堆钱上走了。不上ROS不行,现在来记录一下一个纯小白学习ROS的过程和遇到的问题。防止学弟、学妹们再走我走过的弯路。板子用的是学长给的Jetson Nano(4GB),版本是Ubuntu18.04(已配置好基础ROS所需配置)

一、ROS工作空间覆盖(目前没有解决方法一定要避免!!)

所谓工作空间覆盖,是指不同工作空间中,存在重名的功能包的情形。

1.建立同名功能包

  1. 初始操作
mkdir -p 自定义空间名称/src   #创建空间
cd 自定义空间名称             #进入空间
catkin_make        	     #初始化
cd src			     #进入src
catkin_create_pkg 自定义ROS包名 roscpp rospy std_msgs
cd ros包
touch 自定义文件名.cpp	#建立一个c++文件
  1. 编辑 ros 包下的 CamkeList.txt 文件
    136行:add_executable(hello_ws1 src/hello_ws1.cpp)
    149行:
 target_link_libraries(hello_ws1
   ${catkin_LIBRARIES}
)
  1. 编译运行
cd 自定义空间名称
catkin_make

按以上方法在两个不同的工作空间中建立两个重名的功能包(我建立的是turtlesim)

2.编辑.bashrc

进入主目录,ctrl+h打开隐藏的文件
编辑.bashrc文件
加上:

source /home/lzl/工作空间1/devel/setup.bash
source /home/lzl/工作空间2/devel/setup.bash

先启动命令行1:roscore
再启动命令行2:rosrun turtlesim TAB补齐

发现:会补齐后刷新的
原因:
ROS 会解析 .bashrc 文件,并生成 ROS_PACKAGE_PATH ROS包路径,该变量中按照 .bashrc 中配置设置工作空间优先级,在设置时需要遵循一定的原则:ROS_PACKAGE_PATH 中的值,和 .bashrc 的配置顺序相反—>后配置的优先级更高,如果更改自定义空间A与自定义空间B的source顺序,那么调用时,将进入工作空间A。

结论:
功能包重名时,会按照 ROS_PACKAGE_PATH 查找,配置在前的会优先执行。

二、ROS节点名称重名

在ROS中给出的解决策略是使用命名空间或名称重映射。
命名空间就是为名称添加前缀,名称重映射是为名称起别名。这两种策略都可以解决节点重名问题,两种策略的实现途径有多种:

  • rosrun 命令
  • launch 文件
  • 编码实现
    以上三种途径都可以通过命名空间或名称重映射的方式,来避免节点重名,本节将对三者的使用逐一演示,三者要实现的需求类似。

案例
启动两个 turtlesim_node 节点

1.rosrun设置命名空间与重映射

  1. 实现策略1设置命名空间:rosrun 包名 节点名 __ns:=新名称
    新开一个命令行:roscore
    新开一个命令行:rosrun turtlesim turtlesim_node __ns:=ergouzi
    新开一个命令行:rosrun turtlesim turtlesim_node __ns:=maolv
    新开一个命令行:rosnode list
    响应:
/ergouzi/turtlesim
/maolv/turtlesim
/rosout
/turtlesim
  1. 实现策略2为节点起别名:rosrun 包名 节点名 __name:=新名称
    新开一个命令行:roscore
    新开一个命令行:rosrun turtlesim turtlesim_node __name:=daqiang
    新开一个命令行:rosrun turtlesim turtlesim_node __name:=xiaoqiang
    新开一个命令行:rosnode list
    响应:
/daqiang
/ergouzi/turtlesim
/maolv/turtlesim
/rosout
/turtlesim
/xiaoqiang
  1. 实现策略3设置命名空间同时名称重映射:rosrun 包名 节点名 __ns:=新名称 __name:=新名称

2.launch文件设置命名空间与重映射

  1. 介绍 launch 文件的使用语法时,在 node 标签中有两个属性: name 和 ns,二者分别是用于实现名称重映射与命名空间设置的。使用launch文件设置命名空间与名称重映射也比较简单。
    建立功能包,在功能包下添加 launch目录, 目录下新建 xxxx.launch 文件,编辑 launch 文件。
    代码如下:
<!--需要启动多个乌龟GUI节点-->
<launch>
     <node pkg="turtlesim" type="turtlesim_node" name="turtlesim"/>
    <!--名称重映射-->
    <node pkg="turtlesim" type="turtlesim_node" name="t1"/>
     <!--命名空间-->
     <node pkg="turtlesim" type="turtlesim_node" name="turtlesim" ns="ergouzi"/>
     <!--命名空间+名称重映射-->
    <node pkg="turtlesim" type="turtlesim_node" name="t2" ns="maolvzi"/>
</launch>
  1. 编译运行
    新开一个命令行roscore
    新开一个命令行:
cd 工作空间
source ./devel/setup.bash
roslaunch rename01_node start_turtle.launch

新开一个命令行:

rosnode cleanup  #清除之前例子中开过的节点,现在他们是僵尸节点
rosnode list

查看节点信息,显示结果:

/ergouzi/turtlesim
/maolvzi/t2
/rosout
/t1
/turtlesim

3.编码设置命名空间与重映射

名称别名设置,会在节点名称后缀时间戳
核心代码:rospy.init_node("lisi",anonymous=True)

三、ROS话题名称设置

在实际应用中,按照逻辑,有些时候可能需要将相同的话题名称设置为不同,也有可能将不同的话题名设置为相同。在ROS中给出的解决策略与节点名称重命类似,也是使用名称重映射或为名称添加前缀。根据前缀不同,有全局、相对、和私有三种类型之分。

  • 全局(参数名称直接参考ROS系统,与节点命名空间平级)
  • 相对(参数名称参考的是节点的命名空间,与节点名称平级)
  • 私有(参数名称参考节点名称,是节点名称的子级)

名称重映射是为名称起别名,为名称添加前缀,该实现比节点重名更复杂些,不单是使用命名空间作为前缀、还可以使用节点名称最为前缀。两种策略的实现途径有多种:

  • rosrun 命令
  • launch 文件
  • 编码实现

1.rosrun设置话题重映射

rosrun名称重映射语法: rorun 包名 节点名 话题名:=新话题名称
实现teleop_twist_keyboard与乌龟显示节点通信(两个话题不一样,一个是/turtle1/cmd_vel,一个是/cmd_vel)

  1. 方案1
    将 teleop_twist_keyboard 节点的话题设置为/turtle1/cmd_vel
    启动键盘控制节点:rosrun teleop_twist_keyboard teleop_twist_keyboard.py /cmd_vel:=/turtle1/cmd_vel
    启动乌龟显示节点: rosrun turtlesim turtlesim_node
  2. 方案2
    将乌龟显示节点的话题设置为 /cmd_vel
    启动键盘控制节点:rosrun teleop_twist_keyboard teleop_twist_keyboard.py
    启动乌龟显示节点: rosrun turtlesim turtlesim_node /turtle1/cmd_vel:=/cmd_vel

2.launch文件设置话题重映射

  1. 建立功能包,在功能包下添加 launch目录, 目录下新建 xxxx.launch 文件,编辑 launch 文件。
    代码如下:
<!--实现键盘控制乌龟运动-->
<launch>
    <!--将乌龟的话题设置为与键盘控制一致-->
    <node pkg="turtlesim" type="turtlesim_node" name="t1">
        <remap from="/turtle1/cmd_vel" to ="/cmd_vel" />
    </node>
    <node pkg="teleop_twist_keyboard" type="teleop_twist_keyboard.py" name="key"/>
    <!--将键盘控制的话题设置为与乌龟一致-->

</launch>
  1. 编译运行
    新开一个命令行roscore
    新开一个命令行:
cd 工作空间
source ./devel/setup.bash
roslaunch rename02_topic start.launch

3.编码设置话题名称

话题的名称与节点的命名空间、节点的名称是有一定关系的,话题名称大致可以分为三种类型:

  • 全局(话题参考ROS系统,与节点命名空间平级)
  • 相对(话题参考的是节点的命名空间,与节点名称平级)
  • 私有(话题参考节点名称,是节点名称的子级)
  • 节点名称:
    /命名空间/节点名
    第一个/代表根目录
    在这里插入图片描述
  1. 建立功能包,并建立scripts文件夹,建立相关python文件,并给予权限。
    代码实例讲解如下:
#! /usr/bin/env python3

import rospy
from std_msgs.msg import String

if __name__ == "__main__":
    rospy.init_node("hello")
    """
        需求:实现不同类型的话题设置

    """
    #1.全局
    #pub = rospy.Publisher("/chatter",String,queue_size=10)
    #2.相对
    #pub = rospy.Publisher("chatter",String,queue_size=10)
    #3.私有
    pub = rospy.Publisher("~chatter",String,queue_size=10)
    while not rospy.is_shutdown():
        pass
        #避免节点启动之后被关闭的情况
  1. 修改cmakelists
    编译运行
    新开一个命令行:
cd 工作空间
source ./devel/setup.bash
rosrun rename02_topic topic_name_p.py __ns:=xxx

新开一个命令行:rostopic list

  • 全局:/chatter
  • 相对:/xxx/chatter
  • 私有:/xxx/hello/chatter

四、ROS参数名称设置

在ROS中节点名称话题名称可能出现重名的情况,同理参数名称也可能重名。

关于参数重名的处理,没有重映射实现,为了尽量的避免参数重名,都是使用为参数名添加前缀的方式,实现类似于话题名称,有全局、相对、和私有三种类型之分。

  • 全局(参数名称直接参考ROS系统,与节点命名空间平级)
  • 相对(参数名称参考的是节点的命名空间,与节点名称平级)
  • 私有(参数名称参考节点名称,是节点名称的子级)

1.rosrun设置参数

rosrun 在启动节点时,也可以设置参数:(私有)
语法: rosrun 包名 节点名称 _参数名:=参数值

2.launch文件设置参数

通过 launch 文件设置参数的方式前面已经介绍过了,可以在 node 标签外,或 node 标签中通过 param 或 rosparam 来设置参数。在 node 标签外设置的参数是全局性质的,参考的是 / ,在 node 标签中设置的参数是私有性质的,参考的是 /命名空间/节点名称。

  1. 建立功能包,在功能包下添加 launch目录, 目录下新建 xxxx.launch 文件,编辑 launch 文件。
    代码如下:
<!--设置参数-->
<launch>
    <!--格式1:全局-->
    <param name="radius" value="0.2" />
    <node pkg="turtlesim" type="turtlesim_node" name="t1" ns="xxx">
        <!--格式2:私有-->
        <param name="radius" value="0.08" />
    </node>
</launch>
  1. 编译运行
    新开一个命令行roscore
    新开一个命令行:
cd 工作空间
source ./devel/setup.bash
roslaunch rename03_param test_param.launch

新开一个命令行:

rosparam get /radius
rosparam get /xxx/t1/radius

3.编码设置参数

  1. 建立功能包,并建立scripts文件夹,建立相关python文件,并给予权限。
    代码实例讲解如下:
#! /usr/bin/env python3

import rospy

if __name__ == "__main__":
    rospy.init_node("hello")
    """
        设置不同类型的参数
    """
    #1.全局
    rospy.set_param("/radiusA",100)
    #2.相对
    rospy.set_param("radiusB",100)
    #3.私有
    rospy.set_param("~radiusC",100)
  1. 修改cmakelists
    编译运行
    新开一个命令行:
cd 工作空间
source ./devel/setup.bash
rosrun rename03_param param_name_p.py  __ns:=xxx

新开一个命令行:rosparam list

五、ROS分布式通信

ROS是一个分布式计算环境。一个运行中的ROS系统可以包含分布在多台计算机上多个节点。根据系统的配置方式,任何节点可能随时需要与任何其他节点进行通信。
因此,ROS对网络配置有某些要求:
所有端口上的所有机器之间必须有完整的双向连接。
每台计算机必须通过所有其他计算机都可以解析的名称来公告自己。

操作:

  1. 打开命令行:ifconfig
    eth0: 有线连接
    wlan0: wifi连接

在网络中,将ipv4相关配置
inet 地址 netmask 子网掩码 网关是地址前三位+.1

  1. 分别修改不同计算机的 /etc/hosts 文件,在该文件中加入对方的IP地址和计算机名:(计算机名称查看: hostname
    主机端:从机的IP 从机计算机名
    从机端:主机的IP 主机计算机名
    重启两台机子
    验证通信是否正常ping +IP

  2. 配置主机的 IP 地址
    在:~/.bashrc 追加

export ROS_MASTER_URI=http://主机IP:11311
export ROS_HOSTNAME=主机IP

配置从机的 IP 地址
在:~/.bashrc 追加

export ROS_MASTER_URI=http://主机IP:11311
export ROS_HOSTNAME=从机IP

测试:

主机启动 roscore(必须)
主机启动订阅节点,从机启动发布节点,测试通信是否正常
反向测试,主机启动发布节点,从机启动订阅节点,测试通信是否正常

六、本章小结

本章的重点是"重名"相关的内容:

  • 包名重复,会导致覆盖。
  • 节点名称重复,会导致先启动的节点关闭
  • 话题名称重复,无语法异常,但是可能导致通信实现出现逻辑问题
  • 参数名称重复,会导致参数设置的覆盖

解决重名问题的实现方案有两种:

  • 重映射(重新起名字)
  • 为命名添加前缀

总结

以上就是今天要讲的内容,本文仅仅简单记录了RO重名问题、分布式通信,如果有问题请在博客下留言或者咨询邮箱:layraliu@foxmail.com。

  • 6
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值