第一章 ROS空间创建、helloworld的实现、开启多个节点
第二章 话题通信
第三章 服务通信
第四章 参数服务器
第五章 常用指令
第六章 通信机制实操
第七章 ROS通信机制进阶(常用API、Python模块的导入)
第八章 元功能包、节点运行管理launch文件(teleop_twist安装方法)
第九章 重名问题、分布式通信
第十章-第一节 TF坐标变换(内含PyKDL 和PyInit__tf2功能缺失等解决)
现在大二,之前大一有幸参加了2021的国赛,很壮烈的拿了个江苏赛区的二等奖。但发现无人机这个题,真的是往堆钱上走了。不上ROS不行,现在来记录一下一个纯小白学习ROS的过程和遇到的问题。防止学弟、学妹们再走我走过的弯路。板子用的是学长给的Jetson Nano(4GB),版本是Ubuntu18.04(已配置好基础ROS所需配置)
所谓工作空间覆盖,是指不同工作空间中,存在重名的功能包的情形。
mkdir -p 自定义空间名称/src #创建空间
cd 自定义空间名称 #进入空间
catkin_make #初始化
cd src #进入src
catkin_create_pkg 自定义ROS包名 roscpp rospy std_msgs
cd ros包
touch 自定义文件名.cpp #建立一个c++文件
add_executable(hello_ws1 src/hello_ws1.cpp)
target_link_libraries(hello_ws1
${catkin_LIBRARIES}
)
cd 自定义空间名称
catkin_make
按以上方法在两个不同的工作空间中建立两个重名的功能包(我建立的是turtlesim)
进入主目录,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中给出的解决策略是使用命名空间或名称重映射。
命名空间就是为名称添加前缀,名称重映射是为名称起别名。这两种策略都可以解决节点重名问题,两种策略的实现途径有多种:
案例
启动两个 turtlesim_node 节点
roscore
rosrun turtlesim turtlesim_node __ns:=ergouzi
rosrun turtlesim turtlesim_node __ns:=maolv
rosnode list
/ergouzi/turtlesim
/maolv/turtlesim
/rosout
/turtlesim
roscore
rosrun turtlesim turtlesim_node __name:=daqiang
rosrun turtlesim turtlesim_node __name:=xiaoqiang
rosnode list
/daqiang
/ergouzi/turtlesim
/maolv/turtlesim
/rosout
/turtlesim
/xiaoqiang
<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>
roscore
cd 工作空间
source ./devel/setup.bash
roslaunch rename01_node start_turtle.launch
新开一个命令行:
rosnode cleanup #清除之前例子中开过的节点,现在他们是僵尸节点
rosnode list
查看节点信息,显示结果:
/ergouzi/turtlesim
/maolvzi/t2
/rosout
/t1
/turtlesim
名称别名设置,会在节点名称后缀时间戳
核心代码:rospy.init_node("lisi",anonymous=True)
在实际应用中,按照逻辑,有些时候可能需要将相同的话题名称设置为不同,也有可能将不同的话题名设置为相同。在ROS中给出的解决策略与节点名称重命类似,也是使用名称重映射或为名称添加前缀。根据前缀不同,有全局、相对、和私有三种类型之分。
名称重映射是为名称起别名,为名称添加前缀,该实现比节点重名更复杂些,不单是使用命名空间作为前缀、还可以使用节点名称最为前缀。两种策略的实现途径有多种:
rosrun名称重映射语法: rorun 包名 节点名 话题名:=新话题名称
实现teleop_twist_keyboard与乌龟显示节点通信(两个话题不一样,一个是/turtle1/cmd_vel,一个是/cmd_vel)
rosrun teleop_twist_keyboard teleop_twist_keyboard.py /cmd_vel:=/turtle1/cmd_vel
rosrun turtlesim turtlesim_node
rosrun teleop_twist_keyboard teleop_twist_keyboard.py
rosrun turtlesim turtlesim_node /turtle1/cmd_vel:=/cmd_vel
<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>
roscore
cd 工作空间
source ./devel/setup.bash
roslaunch rename02_topic start.launch
话题的名称与节点的命名空间、节点的名称是有一定关系的,话题名称大致可以分为三种类型:
#! /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
#避免节点启动之后被关闭的情况
cd 工作空间
source ./devel/setup.bash
rosrun rename02_topic topic_name_p.py __ns:=xxx
新开一个命令行:rostopic list
/chatter
/xxx/chatter
/xxx/hello/chatter
在ROS中节点名称话题名称可能出现重名的情况,同理参数名称也可能重名。
关于参数重名的处理,没有重映射实现,为了尽量的避免参数重名,都是使用为参数名添加前缀的方式,实现类似于话题名称,有全局、相对、和私有三种类型之分。
rosrun 在启动节点时,也可以设置参数:(私有)
语法: rosrun 包名 节点名称 _参数名:=参数值
通过 launch 文件设置参数的方式前面已经介绍过了,可以在 node 标签外,或 node 标签中通过 param 或 rosparam 来设置参数。在 node 标签外设置的参数是全局性质的,参考的是 / ,在 node 标签中设置的参数是私有性质的,参考的是 /命名空间/节点名称。
<launch>
<param name="radius" value="0.2" />
<node pkg="turtlesim" type="turtlesim_node" name="t1" ns="xxx">
<param name="radius" value="0.08" />
node>
launch>
roscore
cd 工作空间
source ./devel/setup.bash
roslaunch rename03_param test_param.launch
新开一个命令行:
rosparam get /radius
rosparam get /xxx/t1/radius
#! /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)
cd 工作空间
source ./devel/setup.bash
rosrun rename03_param param_name_p.py __ns:=xxx
新开一个命令行:rosparam list
ROS是一个分布式计算环境。一个运行中的ROS系统可以包含分布在多台计算机上多个节点。根据系统的配置方式,任何节点可能随时需要与任何其他节点进行通信。
因此,ROS对网络配置有某些要求:
所有端口上的所有机器之间必须有完整的双向连接。
每台计算机必须通过所有其他计算机都可以解析的名称来公告自己。
操作:
ifconfig
在网络中,将ipv4相关配置
inet 地址 netmask 子网掩码 网关是地址前三位+.1
分别修改不同计算机的 /etc/hosts 文件,在该文件中加入对方的IP地址和计算机名:(计算机名称查看: hostname
)
主机端:从机的IP 从机计算机名
从机端:主机的IP 主机计算机名
重启两台机子
验证通信是否正常ping +IP
配置主机的 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重名问题、分布式通信,如果有问题请在博客下留言或者咨询邮箱:[email protected]。