启动launch文件可以同时启动多个节点
<launch>
(1)<launch>
标签----所有 launch 文件的根标签,所有其它标签都是launch的子级标签。
(2)<node>
标签----指定 ROS 节点 ,语法如下:
<node pkg="节点包名" type="nodeType" name="nodeName" />
// 在某些情况下,还有可能用到以下属性:
// output="log | screen" 日志发送目标
// respawn = "true" 复位属性,该节点停止时,会自动重启,默认为false
// ns = "namespace" 命名空间,为节点内的相对名称添加命名空间前缀
// args = "arguments" 节点需要的输入参数
'''
(3)<arg>
标签是用于动态传参,类似于函数的参数
<name="参数名称" default="默认值" (可选) value="数值" (可选),不可以与 default 并存 />
(4)<group>
标签可以对节点分组,可以让节点归属某个命名空间
(5)<rosparam>
标签可以从 YAML 文件导入参数,或将参数导出到 YAML 文件,也可以用来删除参数,且在<node>
标签中时被视为私有。
<command="load | dump | delete" file="$(find xxxxx)/xxx/yyy....",加载或导出到的 yaml 文件 param="参数名称" ns="命名空间" (可选) />
(6)<param>
标签主要用于在参数服务器上设置参数,参数源可以在标签中通过 value 指定,也可以通过外部文件加载,在标签中时,相当于私有命名空间。
<name="命名空间/参数名" value="xxx" (可选)定义参数值 type="指定参数类型(str | int | double | bool | yaml)" (可选) />
(7)<remap>
标签–用于话题重映射名称
<remap from="原始话题名称" to="目标名称" />
(8)<include>
标签–用于将另一个 xml 格式的 launch 文件导入到当前文件
<inlude file="$(find 包名)/xxx/xxx.launch"要包含的文件路径 ns="xxx" (可选)在指定命名空间导入文件 />
- 功能包重名
在工作空间A和B下都有turtlesim功能包,ros中还内置turtlesim包,,格式如下:
//在 ~/.bashrc 文件下追加当前工作空间的 bash
source /home/用户/路径/工作空间A/devel/setup.bash
source /home/用户/路径/工作空间B/devel/setup.bash
//在终端下输入:
source .bashrc
rosrun turtlesim xxx
ROS可以解析.bashrc文件,使得工作空间会按照一定的优先级被执行,如上是优先级B>A>内置turtlesim包,故会默认执行B下的turtlesim包的文件
-
节点重名
不可以启动重名节点或者同一节点启动多次,否则会将之前已经启动的节点关闭, 解决策略是使用命名空间或名称重映射,命名空间就是为名称添加前缀,名称重映射是为名称起别名。 实现途径有三种:
3.1 rosrun设置命名空间与重映射
设置命名空间:
rosrun 包名 节点名 __ns:=新名称
设置重映射:
rosrun 包名 节点名 __name:=新名称
二者叠加:
rosrun 包名 节点名 __ns:=新名称 __name:=新名称
3.2 launch文件
在<node>
标签中有两个属性: name 和 ns,二者分别是用于实现名称重映射与命名空间设置的
3.3编码实现重映射(关键代码)
C++:ros::init(argc,argv,"lili",ros::init_options::AnonymousName);
Python:rospy.init_node("lili",anonymous=True)
最后执行结果会在节点名称后面缀上时间戳 -
话题重名
4.1 rosrun设置重映射
语法:rorun 包名 节点名 话题名:=新话题名称
例如实现键盘控制节点与乌龟显示节点通信方案有两种:
(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) 将乌龟显示节点的话题设置为 /cmd_vel
启动键盘控制节点:
rosrun teleop_twist_keyboard teleop_twist_keyboard.py
启动乌龟显示节点:rosrun turtlesim turtlesim_node /turtle1/cmd_vel:=/cmd_vel
4.2 launch文件设置
语法:
<launch>
<node pkg="xxx" type="xxx" name="xxx">
<remap from="原话题" to="新话题" />
</node>
</launch>
-
4.3 编码设置
话题名称可以分为三种类型:全局(话题参考ROS系统,与节点命名空间平级)、相对(话题参考的是节点的命名空间,与节点名称平级)、私有(话题参考节点名称,是节点名称的子级)演示准备:初始化节点名称"hello" ; ns:= xxx
-
4.3.1 全局名称
格式:以/开头的名称,和节点名称无关
ros::Publisher pub =nh.advertise<std_msgs::String>("/chatter",1000);
pub = rospy.Publisher("/chatter",String,queue_size=1000)
执行结果1:/chatter
4.3.2 相对名称
格式:非/开头的名称,参考命名空间(与节点名称平级)来确定话题名称
ros::Publisher pub =nh.advertise<std_msgs::String>("chatter",1000);
pub = rospy.Publisher("chatter",String,queue_size=100)
执行结果1:/xxx/chatter
4.3.3 私有名称
格式:以~开头的名称
ros::NodeHandle nh("~");
ros::Publisher pub = nh.advertise<std_msgs::String>("chatter",1000);
pub = rospy.Publisher("~chatter",String,queue_size=100)
执行结果:/xxx/hello/chatter
注:当使用~,而话题名称有/开头时,那么话题名称是全局的
- 5.参数名称设置
在ROS中参数名称也可能重名。当参数名称重名时,就会产生覆盖。 为了尽量的避免参数重名,都是使用为参数名添加前缀的方式,实现类似于话题名称,有全局、相对、和私有三种类型之分。
5.1 rosrun设置参数
语法:rosrun 包名 节点名称 _参数名:=参数值
结果显示,参数前缀节点名称,即:/节点名/参数名
5.2 launch文件设置参数
通过 launch 文件设置参数的方式,可以在 node 标签外或 node 标签中通过 param 或 rosparam 来设置参数。在 node 标签外设置的参数是全局的,参考的是 / ,在 node 标签中设置的参数是私有的,参考的是 /命名空间/节点名称。
以 param 标签为例
<launch>
<!-- 格式1 全局,参考 /-->
<param name="radius" value="1.2" />
<node pkg="turtlesim" type="turtlesim_node" name="t1">
<!-- 格式2 私有,参考的是 /命名空间/节点名称 -->
<param name="radius" value="0.2" />
</node>
</launch>
- 5.3 编码设置参数
5.3.1 C++实现
在 C++ 中,可以使用 ros::param 或者 ros::NodeHandle 来设置参数。代码示例:
//ros::param设置参数----------
//设置参数调用API是ros::param::set,该函数中,参数1传入参数名称,参数2是传入参数。
ros::param::set("/radiusA",100); //全局,和命名空间以及节点名称无关
ros::param::set("radiusB",100); //相对,参考命名空间
ros::param::set("~radiusC",100); //私有,参考命名空间与节点名称
// ros::NodeHandle设置参数--------------
//设置参数时,首先需要创建 NodeHandle 对象,然后调用该对象的 setParam 函数,该函数参数1为参数名,参数2为要设置的参数值。
ros::NodeHandle nh;
nh.setParam("/nh_A",100); //全局,和命名空间以及节点名称无关
nh.setParam("nh_B",100); //相对,参考命名空间
ros::NodeHandle nh_private("~");
nh_private.setParam("nh_C",100);//私有,参考命名空间与节点名称
5.3.2 python实现
python 中关于参数设置的语法实现比 C++ 简洁一些,调用的API时 rospy.set_param,该函数中,参数1传入参数名称,参数2是传入参数值
代码示例:
rospy.set_param("/radius_A",100) #全局,和命名空间以及节点名称无关
rospy.set_param("radius_B",100) #相对,参考命名空间
rospy.set_param("~radius_C",100) #私有,参考命名空间与节点名称
运行时,假设设置的 namespace 为 xxx,节点名称为 yyy,使用 rosparam list 查看,两种实现结果一样:
/radiusA
/xxx/radiusB
/xxx/yyy/radiusC