ROS2 launch文件中remappings设置项的使用

ROS中topic、service、action、parameter实现数据的传递,关键是通过其本身的名称来实现,而与节点名无直接关系,但是topic、service、action的名称定义是在节点的代码中定义的,而节点的可执行文件进行迁移使用时,有可能与别的节点的可执行文件中的对topic、service、action、parameter的名称定义重名,虽然ROS允许在重名的条件下实现topic等通信机制,但是也容易出现混乱,因此在重名的情况下进行改名,就成为开发者需要做的工作了。当然,最基本的方法就是打开代码,直接修改topic等通信机制的名称。
ROS在launch文件中提供remappings设置项,可以在不修改代码的条件下实现对topic、service、action的名称的改名,这种方式更加快捷、方便。

关于launch文件中namespace与topic名关系的实例:

publish节点1代码:

import rclpy                                  
from rclpy.node import Node                    
from std_msgs.msg import String        

from std_msgs.msg import Int32

class PublisherNode(Node):
    
    def __init__(self, name):
        super().__init__(name)           
        self.pub = self.create_publisher(String, "chatter1", 10)   
        self.i=0
        self.timer = self.create_timer(0.5, self.timer_callback) 
        
    def timer_callback(self):      
        msg = String()
        s='hello world'+str(self.i)   
        msg.data = s                        
        self.i+=1                                  
        self.pub.publish(msg)           
        self.get_logger().info('Publishing: "%s"' % msg.data)   
        
def main(args=None):                          
    rclpy.init(args=args)                      
    node = PublisherNode("topic_helloworld_pub")  
    rclpy.spin(node)                                
    node.destroy_node()                           
    rclpy.shutdown()

publish节点2代码:

import rclpy                            
from rclpy.node import Node                
from std_msgs.msg import String         

from std_msgs.msg import Int32

class PublisherNode(Node):
    
    def __init__(self, name):
        super().__init__(name)          
        self.pub = self.create_publisher(String, "chatter1", 10)  
        self.i=0
        self.timer = self.create_timer(0.5, self.timer_callback) 
        
    def timer_callback(self):       
        msg = String()
        s='how are u'+str(self.i)     
        msg.data = s                  
        self.i+=1                                  
        self.pub.publish(msg)       
        self.get_logger().info('Publishing: "%s"' % msg.data)  
        
def main(args=None):       
    rclpy.init(args=args)    
    node = PublisherNode("topic_helloworld_pub") 
    rclpy.spin(node)      
    node.destroy_node()     
    rclpy.shutdown()

subscription节点代码:

import rclpy                    
from rclpy.node   import Node            
from std_msgs.msg import String             

class SubscriberNode(Node):
    
    def __init__(self, name):
        super().__init__(name)
        self.sub = set.create_subscription(\
                String, "chatter1", self.listener_callback, 10)    

    def listener_callback(self, msg):   
        self.get_logger().info('I heard: "%s"' % msg.data)     
        
def main(args=None):          
    rclpy.init(args=args)        
    node = SubscriberNode("topic_helloworld_sub")   
    rclpy.spin(node)                      
    node.destroy_node()          
    rclpy.shutdown()  

第1个publish节点发布的消息是“hello world”,第2个publish节点发布的消息是“how are u”,2个节点的topic名都为chatter1,subscription节点则订阅名为chatter1的话题。
定义的launch文件为:

from launch import LaunchDescription
from launch_ros.actions import Node

def generate_launch_description():
    node0 = Node(package='pkg_test_py',executable='tp_hellopub_node',
                 namespace='ns_test_1', name='node_pub')
    node1 = Node(package='pkg_test_py',executable='tp_hellopub_node',
                 namespace='ns_test_2', name='node_pub')
    node2 = Node(package='pkg_test_py',executable='tp_hellosub_node',
                 namespace='ns_test_1', name='node_sub')
    return LaunchDescription([node0,node1,node2])

通过这个launch文件可以看到,启动了2个node_pub节点,namespace分别为ns_test_1和ns_test_2,启动了1个node_sub节点,namespace为ns_test_1。运行launch文件,启动节点的结果如图所示:
在这里插入图片描述
在这里插入图片描述
从这个结果中可以看到3个节点都启动了,特别是topic list,这里显示的topic名称附加上了namespace的名字了,而subscription只接收到“hello world”,这是因为publish节点1与subscription节点在同一个namespace中,二者的topic名称是一致的,而publish节点2则在另外一个namespace中,经过launch文件运行后topic名称不再与subscription节点的topic名称一致,因此subscription节点无法接收到publish节点2所发出的消息。
将launch文件中这一句代码修改为:

node2 = Node(package='pkg_test_py',executable='tp_hellosub_node',
                 namespace='ns_test_2', name='node_sub')

也就意味着subscription节点将于publish节点2在同一namespace中,下面再看一下运行结果:
在这里插入图片描述
在这里插入图片描述可以看到通过改变node2的namespace与node1一致,现在接收到的是 “how are u”。

使用remappings的实例

在上面那个实例中,更改launch文件代码,如下:

from launch import LaunchDescription
from launch_ros.actions import Node
def generate_launch_description():
    node0 = Node(package='pkg_test_py',executable='tp_hellopub_node',
                 namespace='ns_test_1', name='node_pub',
                 remappings=('chatter1','newtopic'))
    node1 = Node(package='pkg_test_py',executable='tp_hellopub_node',
                 namespace='ns_test_2', name='node_pub')
    node2 = Node(package='pkg_test_py',executable='tp_hellosub_node',
                 namespace='ns_test_2', name='node_sub',
                 remappings=('chatter1','newtopic'))
    return LaunchDescription([node0,node1,node2])

运行的结果如下:
在这里插入图片描述
在这里插入图片描述
从结果中可以看到,只是通过launch文件的remappings设置,node0和node1的topic改为了新的topic名称:newtopic,并且实现了数据传递,而node1的topic名称保持不变,实现了同名topic的区分。

总结remappings设置项的使用:

(1) 在remapping设置项的使用中,只要将节点代码中原来的topic(service,action)名称,和新指定的topic(service,action)名称放在一个括号中(实际上是Python的tuple数据类型),需要修改多个topic(service,action)名称就需要多个tuple,就可以完成设置;
(2) 通过remapping新指定的topic名,在launch文件运行后,会自动加上namespace。

<think>好的,用户之前问过如何更改小海龟的形状和颜色,现在又转向了ROS 2launch文件。我需要先理解他们的背景和需求。他们可能正在学习ROS 2,已经掌握了基础操作,现在想了解更高级的自动化部署,比如用launch文件来管理多个节点和配置。 用户可能是学生或刚入门的开发者,正在做一个小项目,需要同时启动多个节点,比如turtlesim和键盘控制节点。手动启动每个节点效率低,容易出错,所以他们想用launch文件来简化流程。此外,他们可能想了解launch文件的语法和功能,以便复用和分享配置。 接下来,我需要解释launch文件的基本结构、常用组件和实际例子。要确保内容结构清晰,分点说明,比如XML结构、Python编写方式、常用标签和功能。还要注意对比XML和Python的差异,以及高级功能,这样用户能根据项目需求选择合适的方法。 可能用户还想知道如何调试launch文件,或者如何处理依赖和参数传递,所以需要包含常见问题解答。同时,之前的问题涉及参数设置和服务调用,在launch文件中如何实现这些操作也是需要强调的点,比如设置参数、调用服务、启动节点等。 最后,给出一个实际案例,结合他们之前的小海龟例子,展示如何用launch文件启动模拟器和键盘控制,这样用户能直接看到应用场景,加深理解。总结部分要强调launch文件的优势,比如自动化、可维护性,以及如何促进团队协作。</think>以下是 ROS 2 launch 文件的详细解析: --- ### 一、Launch 文件核心作用 通过 **XML/Python/YAML** 格式定义: - 批量启动多个节点 - 配置节点参数 - 管理节点依赖关系 - 设置环境变量 - 控制启动顺序 - 实现条件分支逻辑 --- ### 二、XML 格式基础结构 ```xml <launch> <!-- 注释示例 --> <node pkg="包名" exec="可执行文件" name="节点名称"> <param name="参数名" value="参数值"/> <remap from="原话题" to="新话题"/> </node> </launch> ``` --- ### 三、Python 格式优势(ROS 2 推荐) ```python from launch import LaunchDescription from launch_ros.actions import Node def generate_launch_description(): return LaunchDescription([ Node( package='包名', executable='可执行文件', name='节点别名', parameters=[{'参数名': '参数值'}], remappings=[('原话题', '新话题')] ) ]) ``` --- ### 四、关键功能对比 | 功能 | XML 实现 | Python 实现 | |---------------------|-----------------------------------|-----------------------------------| | **启动节点** | `<node>` 标签 | `Node()` 对象 | | **参数传递** | `<param>` 或 YAML 文件 | `parameters` 参数 | | **话题重映射** | `<remap>` 标签 | `remappings` 列表 | | **条件启动** | `<if>`/`<unless>` 条件判断 | Python 的 `if` 语句 | | **包含其他launch** | `<include>` 标签 | `IncludeLaunchDescription()` | --- ### 五、实际应用案例(以 turtlesim 为例) ```python from launch import LaunchDescription from launch_ros.actions import Node def generate_launch_description(): return LaunchDescription([ Node( package='turtlesim', executable='turtlesim_node', name='simulator', parameters=[{'background_r': 100}] ), Node( package='turtlesim', executable='turtle_teleop_key', name='keyboard_control', output='screen', prefix='xterm -e' ) ]) ``` --- ### 六、高级功能 1. **参数文件加载** ```python parameters=[os.path.join(get_package_share_directory('包名'), 'config/params.yaml')] ``` 2. **环境变量设置** ```python SetEnvironmentVariable(name='ROS_LOG_DIR', value='~/custom_logs') ``` 3. **生命周期控制** ```python from launch.actions import RegisterEventHandler from launch.event_handlers import OnProcessExit ``` --- ### 七、常用调试命令 ```bash ros2 launch 包名 launch文件名.py # 启动launch文件 ros2 run launch_ros ls `ros2 pkg prefix launch_ros`/share/launch_ros # 查看launch工具 ``` --- ### 八、最佳实践建议 1. 优先使用 **Python 格式**(官方推荐,功能更强大) 2. 复杂项目采用 **模块化设计**(拆分为多个子launch文件) 3. 参数管理推荐使用 **YAML 配置文件** 4. 通过 `ros2 launch --show-args` 查看可配置参数 --- 通过合理使用 launch 文件,可以实现: - **一键启动** 多节点系统 - **参数隔离**(不同场景使用不同配置文件) - **自动化测试**(集成到 CI/CD 流程) - **部署标准化**(团队共享统一配置)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值