先附上个人总结:
-
remap
在node标签<node> ... </node>
之外的作用域是其之后的所有节点;<node> ... </node> <!-- 不受remap影响 --> <remap /> <node> ... </node> <!-- 受remap影响 -->
-
remap
在node标签<node> ... </node>
之间的作用域是当前节点;<node> ... </node> <!-- 不受remap影响 --> <node> <remap /> </node> <!-- 受remap影响 --> <node> ... </node> <!-- 不受remap影响 -->
-
如果launch之间没有调用,某一个launch中的
remap
不会在其它launch中生效; -
如果launch间存在调用,某一个被调用的launch中的
remap
不会在其它launch中生效;<!-- 被调用.launch --> <launch> <node> ... </node> <!-- 不受remap影响 --> <remap /> <node> ... </node> <!-- 受remap影响 --> </launch> <!-- 集成.launch --> <launch> <include file="$(find xxx)被调用.launch"/> <node> ... </node> <!-- 不受<被调用.launch>中的remap影响 --> <include file="$(find xxx)其它.launch"/> <!-- 不受<被调用.launch>中的remap影响 --> </launch> ```xml
-
如果launch间存在调用,集成launch中的
remap
按照launch文件中node的顺序考虑remap
的作用域;<launch> <include file="$(find xxx)xxx1.launch"/> <!-- 不受remap影响 --> <remap /> <node> ... </node> <!-- 受remap影响 --> <include file="$(find xxx)xxx2.launch"/> <!-- 受remap影响 --> </launch>
-
<include> ... </include>
标签内插入remap
不起任何作用,不会像arg
那样发生传递。<include file="$(find xxx)xxx.launch"> <remap /> <!-- 不起任何作用 --> </include>
remap-wiki中的解释
Remapping allows you to “trick” a ROS node so that when it thinks it is subscribing to or publishing to /some_topic it is actually subscribing to or publishing to /some_other_topic, for instance.
其它节点已经订阅或者发布的topic(姑且称为target_topic
)满足不了我的需求,通过瞒天过海、易容术(remap),使我以为我发布或者订阅到了期望的(node中预定义好的)topic(姑且称为source_topic
),但是实际却不是(虽然化妆或者整容了,但是还是原来的那个)。所以如果remap成功,只能看到target_topic
,看不到source_topic
。
- 官方表达
from="original-name"
Remapped topic: name of the ROS topic that you are remapping FROM.
to="new-name"
Target name: name of the ROS topic that you are pointing the from topic TO.
this means that if you remap FROM topic “A” TO topic “B”, then whenever a node thinks it is subscribing to topic “A”, it is actually subscribing to topic “B”, so anyone publishing to topic “B” will end up getting their message to this node!
- 简单例子
For example, you are given a node that says it subscribes to the “chatter” topic, but you only have a node that publishes to the “hello” topic. They are the same type, and you want to pipe your “hello” topic into the new node which wants “chatter”. You can do this with this remap:<remap from="chatter" to="hello"/>
Again, this example is from the perspective of the receiving node which subscribes to the topic. So, when this node subscribes to topic “chatter” in its source code, it is remapped to actually subscribe to “hello”, so that it ends up receiving any messages published by other ROS nodes to “hello”.
代码验证
通过实际代码案例验证
-
用于实验的node及lauch文件
-
三个node:
- node
talker
发布topic/chatter
; - node
listener_1
希望接收topic/chatter
; - node
listener_2
希望接收topic/good/chatter
:
- node
-
几个launch:
-
talker.launch
<launch> <node name="talker" pkg="beginner_tutorials" type="talker" output="screen" /> </launch>
-
listener_1.launch
<launch> <node name="listener_1" pkg="beginner_tutorials" type="listener_1" output="screen" /> </launch>
-
listener_2.launch
<launch> <node name="listener_2" pkg="beginner_tutorials" type="listener_2" output="screen" /> </launch>
-
listener_1_2.launch
:node1调用在前,node2调用在后<launch> <include file="$(find beginner_tutorials)/launch/listener_1.launch"> <include file="$(find beginner_tutorials)/launch/listener_2.launch"> </launch>
现通过在launch文件中插入
remap
,以实现节点通讯。remap
的插入位置文字定义如下:-
node标签内插入
<node> <remap /> </node>
-
node上插入
<remap /> <node> </node>
-
node下插入
<node> </node> <remap />
-
实验结果:
序号 remap位置 remap方向 listener_1通讯结果 listener_2通讯结果 结论 1 不插入 <remap from="/good/chatter" to="/chatter"/>
成功 失败 - 2 listener_2.launch,node标签内插入 <remap from="/good/chatter" to="/chatter"/>
成功 成功 - 3 listener_2.launch,node上插入 <remap from="/good/chatter" to="/chatter"/>
成功 成功 - 4 listener_2.launch,node下插入 <remap from="/good/chatter" to="/chatter"/>
成功 失败 node标签之外的作用域是其之后的节点,所以 remap
并生效,nodelistener_2
还是订阅/good/chatter
5 talker.launch,node标签内插入 <remap from="/chatter" to="/good/chatter"/>
失败 成功 - 6 talker.launch,node上插入 <remap from="/chatter" to="/good/chatter"/>
失败 成功 node标签之外的作用域是其之后的节点,所以 remap
生效7 talker.launch,node下插入 <remap from="/chatter" to="/good/chatter"/>
失败 失败 node标签之外的作用域是其之后的节点,但是此处 remap
之后没有节点8 listener_1.launch,node标签内插入 <remap from="/good/chatter" to="/chatter"/>
成功 失败 在node中的作用域是当前节点,所以node listener_2
还是订阅/good/chatter
9 listener_1.launch,node上插入 <remap from="/good/chatter" to="/chatter"/>
成功 失败 如果launch之间没有调用,某一个launch中的 remap
不会在其它launch中生效,所以nodelistener_2
还是订阅/good/chatter
10 listener_1.launch,node下插入 <remap from="/good/chatter" to="/chatter"/>
成功 失败 如果launch之间没有调用,某一个launch中的 remap
不会在其它launch中生效,所以nodelistener_2
还是订阅/good/chatter
11 listener_1.launch,node标签内插入 <remap from="/chatter" to="/good/chatter"/>
失败 失败 两个listener都订阅 /good/chatter
,但talker发布/chatter
12 listener_1.launch,node上插入 <remap from="/chatter" to="/good/chatter"/>
失败 失败 两个listener都订阅 /good/chatter
,但talker发布/chatter
13 listener_1.launch,node下插入 <remap from="/chatter" to="/good/chatter"/>
成功 失败 node标签之外的作用域是其之后的节点,所以 remap
并生效,nodelistener_1
还是订阅/chatter
14 listener_1_2.launch, listener_1
的include
标签内插入<remap from="/chatter" to="/good/chatter"/>
成功 失败 include
标签内插入remap
不起任何作用,不会像arg
那样发生传递,所以nodelistener_1
还是订阅/chatter
15 listener_1_2.launch, listener_2
的include
标签内插入<remap from="/good/chatter" to="/chatter"/>
成功 失败 include
标签内插入remap
不起任何作用,不会像arg
那样发生传递,所以nodelistener_2
还是订阅/good/chatter
16 listener_1_2.launch, listener_1
上插入<remap from="/chatter" to="/good/chatter"/>
失败 失败 如果launch存在调用,按照launch文件中node的顺序考虑 remap
的作用域,所以两个listener都订阅/good/chatter
,但talker发布/chatter
17 listener_1_2.launch, listener_1
、listener_2
之间插入<remap from="/good/chatter" to="/chatter"/>
成功 成功 如果launch存在调用,按照launch文件中node的顺序考虑 remap
的作用域 & node标签之外的作用域是其之后的节点,所以nodelistener_2
订阅了/chatter
-
参考链接: