ROS2与ROS1比较及移植指南

0. 简介

本文档用于记录现ROS1与ROS2之间的区别,以及如何向ROS2移植。整体架构基于该文章

ROS2的教程参见:https://docs.ros.org/en/ros2_packages/rolling/api/


1 工程构建

1.1 CMakeList的编写

ROS2采用ament cmake系统,最主要的区别是原先的catkin Cmake宏被取代

find_package(catkin REQUIRED COMPONENTS 
...)

catkin_package(
  INCLUDE_DIRS 
  LIBRARIES 
  CATKIN_DEPENDS)
  
add_library(controller src/controller.cpp)
add_dependencies(obot_controller obot_msgs_generate_messages_cpp)

install(TARGETS 
          obot_controller
          obot_controller_node
  LIBRARY DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION}
  RUNTIME DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}
)

############################################ 改变为

find_package(ament_cmake REQUIRED)
find_package(... REQUIRED)

ament_export_include_directories(include)# 标记导出的include目录对应的目录(这是通过目标install调用中的INCLUDES DESTINATION来实现)。
ament_export_libraries(my_library)# 标记安装的库的位置(这是由ament_export_targets调用中的HAS_LIBRARY_TARGET参数来完成)
ament_export_dependencies(some_dependency)
ament_target_dependencies(${PROJECT_NAME} ${DEPS})

ament_package()

install(TARGETS ${PROJECT_NAME}_node
  ARCHIVE DESTINATION lib
  LIBRARY DESTINATION lib
  RUNTIME DESTINATION bin)

若想构建一个兼容ROS1/2的CMakeList.txt,在不同ROS版本有区别的部分通过环境变量触发条件编译

if($ENV{ROS_VERSION} EQUAL 2)
########################
## BULD VERSION: ROS2 ##
########################
else()
########################
## BULD VERSION: ROS1 ##
########################
endif()

1.2 package.xml

<buildtool_depend>catkin</buildtool_depend>
<!--对应的包-->
<build_depend>message_generation</build_depend>
<exec_depend>message_runtime</exec_depend>
<!--##################-->
<buildtool_depend>ament_cmake</buildtool_depend>
<build_type>ament_cmake</build_type>
<!--对应的包-->
<build_export_depend>rclpy</build_export_depend>
<exec_depend>rclpy</exec_depend>

若想构建一个兼容ROS1/2的package.xml,在不同ROS版本有区别的部分通过环境变量设置条件

  <export>
    <build_type condition="$ROS_VERSION == 1">catkin</build_type>
    <build_type condition="$ROS_VERSION == 2">ament_cmake</build_type>
  </export>

1.3 launch 文件

ROS2较ROS1,在launch方面进行了比较大的改动。原先ROS1是使用xml格式来编写launch文件,而ROS2却是用python来编写launch文件.

# 导入库
from launch import LaunchDescription
from launch_ros.actions import Node
from ament_index_python.packages import get_package_share_directory
import os

# 定义函数名称为:generate_launch_description
def generate_launch_description():
    ns = os.environ.get('ROBOT_ID')##read namespace from env
    return LaunchDescription([
        Node(
        	# 创建Node对象fusion_localizer_node,标明所在位置fusion_localizer,将可执行文件重命名为fusion_localizer_nodes,同时可以将运行节点node放在同一个自定义的命名空间ns当中。
            package='fusion_localizer',
            namespace=ns,
            executable='fusion_localizer_node',
            name='fusion_localizer_nodes',
            parameters,
        ),
    ])

##少量parameters也可以用以下方法
parameters=[    {'use_sim_time': True},
                {'lane_filename': "tianjin_special_lanes.yaml"},
                {'qc_info_topic': "/b_info"},
                {'service_lane_in_buffer': 3.0}]

在这里插入图片描述
或者通过以下办法来实现多个节点的调用

def generate_launch_description():
    # 创建Actions.Node对象li_node,标明李四所在位置
    li4_node = Node(
        package="village_li",
        executable="li4_node"
        )
    # 创建Actions.Node对象wang2_node,标明王二所在位置
    wang2_node = Node(
        package="village_wang",
        executable="wang2_node"
        )
    # 创建LaunchDescription对象launch_description,用于描述launch文件
    launch_description = LaunchDescription([li4_node,wang2_node])
    # 返回让ROS2根据launch描述执行节点
    return launch_description

对于ROS1而言,launch文件的编写则比较简单


<launch> 
       <node pkg="beginner1" name="tempspeak" type="speak" output="screen">
       <remap from="speaker" to="listener"/>
       </node> 
       <node pkg="beginner1" name="templisten" type="listen" output="screen">
       <remap from="listener" to="listener"/>
       </node> 
        
       <group ns="demo_1">
           <node name="demo_1" pkg="demo_1" type="demo_pub_1" output="screen"/>
           <node name="demo_1" pkg="demo_1" type="demo_sub_1" output="screen"/>
       </group>
       <group ns="demo_2">
           <node name="demo_2" pkg="demo_2" type="demo_pub_2" output="screen"/>
           <node name="demo_2" pkg="demo_2" type="demo_sub_2" output="screen"/>
       </group>
       
	   <rosparam file="***.yaml" command="load" ns="XXX">
</launch>

1.4 parameter参数

我们可以在1.3中看到在launch文件中同样可以对parameter进行少量的赋值,但是大量的parameter参数则是需要通过yaml文件来进行读取

launch形式

# 导入库
from launch import LaunchDescription
from launch_ros.actions import Node
from ament_index_python.packages import get_package_share_directory
import os

# 定义函数名称为:generate_launch_description
def generate_launch_description():
    para_dir = os.path.join(get_package_share_directory('fusion_localizer'), 'config', 'turtlesim.yaml')##yaml file contains parameters
    ns = os.environ.get('ROBOT_ID')##read namespace from env
    return LaunchDescription([
        Node(
        	# 创建Node对象fusion_localizer_node,标明所在位置fusion_localizer,将可执行文件重命名为fusion_localizer_nodes,同时可以将运行节点node放在同一个自定义的命名空间ns当中。
            package='fusion_localizer',
            namespace=ns,
            executable='fusion_localizer_node',
            name='fusion_localizer_nodes',
            parameters=[para_dir]
        ),
    ])

命令行形式

ros2 run turtlesim turtlesim_node --ros-args --params-file ./turtlesim.yaml

在ROS2中yaml文件格式则是不一样的:第一层为你的namespace第二层为你的node_name第三层为ros__parameters,该层名称为固定不可修改的,第四层为具体的参数,接收包括int, double, bool, string等类型。同一namespace的node应放置于同一层相邻。

your_node_namespace:
  your_node_name_1:
    ros__parameters:
      ip: "192.168.0.10"
      port: 12002
      output: false

  your_node_name_2:
     ros__parameters:
        subscribe_topic: "/node_namespace_1/topic"

而在ROS1中则是很简单的yaml格式,直接是**namespace层(可省略)**对应的具体的参数。

local_costmap:
  global_frame: odom
  robot_base_frame: base_link

  update_frequency: 5.0
  publish_frequency: 5.0
  transform_tolerance: 0.5  

同时,在ROS1中,Parameter参数机制默认是无法实现动态监控的(需要配合专门的动态机制),比如正在使用的参数被其他节点改变了,如果不重新查询的话,就无法确定改变之后的值。ROS2最新版本中添加了参数的事件触发机制ParameterEventHandler, 当参数被改变后,可以通过回调函数的方式,动态发现参数修改结果。这里古月老师讲的很详细了,具体参照这篇文章


…详情请参照古月居

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

敢敢のwings

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值