ros运行管理
一个完整的ros系统可对应一/多台主机
每台主机可对应一/多个工作空间
每个工作空间可对应一/多个功能包
每个功能包可对应一/多个节点
每个节点可对应一/多个话题
元功能包(MetaPackage)使用语法:
元功能包里面没有实质性的内容(所以在创建功能包的时候就不需要添加rospy,roscpp,std_msgs等依赖),它依赖了其他的软件包,通过这种方法可以把其他包组合起来,我们可以认为它是目录索引,告诉我们这个包集合中有哪些子包,并且该去哪里下载。在”sudo apt install ros-noetic-desktop-full“命令时利用了元功能包,其中含有turtlesim的功能包
具体实现:创建一个MetaPackage,包含plumbing_pub_sub,plumbing_server_client,plumbing_param
1,在当下workplace下新建一个功能包,且不添加依赖
2,修改package.xml文件:
#在<buildtool_depend>catkin</buildtool_depend>后面添加
<exec_depend>被集成的功能包</exec_depend>
.....
#在 <export>...</export>之间添加<metapackage />
3,修改cmakelist.txt文件
cmake_minimum_required(VERSION 3.0.2)
project(plumbing_my) #功能包包名
find_package(catkin REQUIRED)
catkin_metapackage() #添加函数
#CMakeLists.txt 中不可以有换行
类似的元功能包的实现,navigation:https://github.com/ros-planning/navigation
launch文件的使用:
launch 文件是一个 XML 格式的文件
**注意:**roslaunch 命令执行launch文件时,首先会判断是否启动了 roscore,如果启动了,则不再启动,否则,会自动调用 roscore
launch文件调用:
roslaunch 功能包名 xxx.launch
文件标签:
-
launch:
<launch>
标签是所有 launch 文件的根标签,充当其他标签的容器 属性:deprecated = “弃用声明”告知用户当前 launch 文件已经弃用
子级标签:所有其它标签都是launch的子级
<launch deprecated=“声明”>#运行时也会发出警告 <!--turtle--> <node pkg="turtlesim" type="turtlesim_node" name="turtle_GUI" /> <node pkg="turtlesim" type="turtle_teleop_key" name="turtle_key" /> <node pkg="plumbing_test" type="demo08_hangin_p.py" name="work01" /> <node pkg="plumbing_test" type="test03_client_p.py" name="work02" /> </launch>
-
node:因为节点运行运行是多进程的,所以节点的启动未必会按照声明顺序
常用属性:
pkg:“节点所属的包名”
type:节点类型(与之相同名称的可执行文件)
name:节点名称(在 ROS 网络拓扑中节点的名称)
output:“log | screen” (可选)默认是 log但屏幕就不可见
respawn=“true | false” (可选)如果节点退出,Ture就自动重启。(应用于雷达等较为重要的设备,如机器人的雷达因意外退出了,是需要自动重启的)
(respawn_delay=” N” (可选) 如果 respawn 为 true, 那么延迟 N 秒后启动节点
<launch> <!--turtle--> <node pkg="turtlesim" type="turtlesim_node" name="turtle_GUI" output="screen" respawn="true" respawn_delay="10" /> #每10s自动重启节点 <node pkg="turtlesim" type="turtle_teleop_key" name="turtle_key" required="true" /> #节点关闭后kill整个系统退出 <node pkg="plumbing_test" type="demo08_hangin_p.py" name="work01" /> <node pkg="plumbing_test" type="test03_client_p.py" name="work02" /> </launch>
属性:
args 将参数传递给节点
machine在指定机器上启动节点
required=“true | false” (可选)该节点是否必须,如果为 true,那么如果该节点退出,将kill roslaunch
ns namespace
clear_params=“true | false” (可选)在启动前,删除节点的私有空间的所有参数
子集标签
env remap rosparam param
-
include
1.属性
<launch> <include file="$(find plumbing_test)/launch/start_turtle.launch" /> </launch>
file=”$(find 包名)/文件夹名/文件名.launch” 要包含的文件路径(注意是要三层关系)
ns=“xxx” (可选) 在指定命名空间导入文件
2.子级标签
env arg
-
remap(常用)
用于话题重命名
1.属性
from=“xxx” 原始话题名称
to=“yyy” 目标名称
具体实现
rosrun teleop_twist_keyboard teleop_twist_keyboard.py
通过rostopic list 发现小乌龟的话题是turtle1/cmd_vel
但是键盘作为publisher的话题是cmd_vel故无法进行通信控制,那么可以采用remap的标签设置对话题进行重命名
<launch deprecated="don not use it!">
<!--turtle-->
#对需要重命名的节点进行remap
<node pkg="turtlesim" type="turtlesim_node" name="turtle_GUI" >
<remap from="/turtle1/cmd_vel" to="/cmd_vel" />
</node>
<node pkg="turtlesim" type="turtle_teleop_key" name="turtle_key" />
<node pkg="plumbing_test" type="demo08_hangin_p.py" name="work01" />
<node pkg="plumbing_test" type="test03_client_p.py" name="work02" />
</launch>
-
param
<param>`标签主要用于在参数服务器上设置参数,参数源可以在标签中通过 value 指定,也可以通过外部文件加载,在`<node>`标签中时,相当于私有命名空间。
属性:
name=“命名空间/参数名” 参数名称,可以包含命名空间
value=“xxx” (可选) 定义参数值,如果此处省略,必须指定外部文件作为参数源
type=“str | int | double | bool | yaml” (可选) 指定参数类型,rosparam
属性
command=“load | dump | delete” (可选,默认 load) 加载、导出或删除参数
file=”$(find xxxxx)/xxx/yyy…” 加载或导出到的 yaml 文件
param=“参数名称”
ns=“命名空间” (可选)
-
group
`<group>`标签可以对节点分组,具有 ns 属性,可以让节点归属某个命名空间
1.属性
ns=“名称空间” (可选)
clear_params=“true | false” (可选) 启动前,是否删除组名称空间的所有参数(慎用…此功能危险)
2.子级标签
除了launch 标签外的其他标签
-
arg
标签是用于动态传参,类似于函数的参数,可以增强launch文件的灵活性
1.属性
name=“参数名称”
default=“默认值” (可选)
value=“数值” (可选) 不可以与 default 并存
doc=“描述” 参数说明
ROS工作空间覆盖
在 ~/.bashrc 文件下添加当前工作空间的 bash 格式如下:
source /home/用户/路径/demo01_ws/devel/setup.bash
source /home/用户/路径/demo02_ws/devel/setup.bash#再次添加顺序为demo01再demo02,而调用时后配置的文件优先级更高,所以再工作空间重名的情况下,后刷新的工作空间将被先检索,即工作空间的覆盖
在设置时需要遵循一定的原则:后配置的优先级更高,如果更改自定义空间A与自定义空间B的source顺序,那么调用时,将进入工作空间A。
ros中内置了个包路径的查看命令:
echo $ROS_PACKAGE_PATH
节点名称重名时的处理方式;
rosrun设置法一:通过设置命名空间来区分两个重名节点,(rosrun设置命名空间)
rosrun turtlesim turtlesim_node __ns:=xiaohong
rosrun turtlesim turtlesim_node __ns:=xiaoming
通过对节点设置命名空间,以达到区分的效果
ros设置法二:可以通过对节点的重命名来达到区分(rosrun名称重映射)
rosrun turtlesim turtlesim_node __name:=dagui
rosrun turtlesim turtlesim_node __name:=xiaogui
launch文件设置:
<launch >
<!--turtle-->
<node pkg="turtlesim" type="turtlesim_node" name="t1" />
<node pkg="turtlesim" type="turtlesim_node" name="t2" />名称重映射
<node pkg="turtlesim" type="turtlesim_node" name="turtlesim" />名称重映射
<node pkg="turtlesim" type="turtlesim_node" name="t1" ns="xiaohong"/>设置命名空间
</launch>
编码方式设置
rospy.init_node("lisi",anonymous=True)#对节点初始化进行设置了命名空间
话题名称重名时的处理方式
-
rosrun 命令
话题重映射前要通过rostopic list来检查话题 publisher话题的重映射 rosrun teleop_twist_keyboard teleop_twist_keyboard.py /cmd_vel:=/turtle1/cmd_vel#把原话题换成新话题 subscriber话题重映射 rosrun turtlesim turtlesim_node /cmd_vel:=/turtle1/cem_vel
-
launch 文件
<launch> <node pkg="turtlesim" type="turtlesim_node" name="t1" /> <node pkg="teleop_twist_keyboard" type="teleop_twist_keyboard.py" name="key"> <remap from="/cmd_vel" to="/turtle1/cmd_vel" /> </node> </launch>
-
编码实现
话题名称大致可以分为三种类型:(例如cmd_vel的话题)
- 全局(话题参考ROS系统,与节点命名空间平级)(/cmd_vel)(/demo01_ws/cmd_vel)或(/turtlesim/cmd_vel)
- 相对(话题参考的是节点的命名空间,与节点名称平级)(demo01_ws/cmd_vel)或(turtlesim/cmd_vel)
- 私有(话题参考节点名称,是节点名称的子级)(demo01_ws/turtle/cmd_vel)(/命名空间/节点名/话题名)
#! /usr/bin/env python
import rospy
from std_msgs.msg import String
if __name__ == '__main__':
rospy.init_node("hello")
#设置全局话题
pub = rospy.Publisher("/topic",String,queue_size=10)
pub = rospy.Publisher("/yyy/topic",String,queue_size=10)#yyy为自定义的命名空间
#设置相对话题
pub = rospy.Publisher("topic",String,queue_size=10)
pub = rospy.Publisher("yyy/topic",String,queue_size=10)#yyy为自定义的命名空间
#设置私有话题
pub = rospy.Publisher("~topic",String,queue_size=10)
pub = rospy.Publisher("~yyy/topic",String,queue_size=10)
while not rospy.is_shutdown():
pass
'''终端运行时都可以在rosrun plumbing_test topic_name_p.py后面加上命名空间__ns:= xxx'''
参数名称重名时的处理方式
rosrun 在启动节点时,也可以设置参数: rosrun 包名 节点名称 _参数名:=参数值
<!--set param-->
<launch>
<!--全局.在<node>外是全局的,在内是私有的·-->
<param name="radius" value="0.2" />
<node pkg="turtlesim" type="turtlesim_node" name="t1" ns="xxx">
<!--私有-->
<param name="radius" value="0.08" />
</node>
</launch>
rospy.init_node("hello")
rospy.set_param("/radius_A",100) #全局,和命名空间以及节点名称无关
rospy.set_param("radius_B",100) #相对,参考命名空间
rospy.set_param("~radius_C",100) #私有,参考命名空间与节点名称
'''运行时,假设设置的 namespace 为 xxx,节点名称为 hello,使用 rosparam list 查看:
/a.py 和命名空间以及节点名称无关
/xxx/b.py 参考命名空间
/xxx/hello/c.py 参考命名空间与节点名称'''
alue=“0.08” />
```python
rospy.init_node("hello")
rospy.set_param("/radius_A",100) #全局,和命名空间以及节点名称无关
rospy.set_param("radius_B",100) #相对,参考命名空间
rospy.set_param("~radius_C",100) #私有,参考命名空间与节点名称
'''运行时,假设设置的 namespace 为 xxx,节点名称为 hello,使用 rosparam list 查看:
/a.py 和命名空间以及节点名称无关
/xxx/b.py 参考命名空间
/xxx/hello/c.py 参考命名空间与节点名称'''