警告

您正在阅读的 ROS 2 文档版本已达到 EOL(生命周期结束),不再受官方支持。如果您想了解最新信息,请访问 Jazzy.

从 ROS 1 移植指南

有两种不同的软件包迁移:

  • 将现有软件包的源代码从 ROS 1 迁移到 ROS 2,目的是使源代码的大部分保持不变或至少相似。例如 插件库 在这种情况下,源代码保存在同一版本库的不同分支中,必要时可以在这些分支之间移植常用补丁。

  • 为 ROS 2 实现与 ROS 1 软件包相同或相似的功能,但假设源代码会有很大不同。例如 roscpp 在 ROS 1 和 rclcpp 在 ROS 2 中,它们是独立的软件源,不共享任何代码。

本文主要针对前一种情况,介绍将 ROS 1 软件包迁移到 ROS 2 的高级步骤。 终局 "解决方案"。未来版本的目标是让迁移更顺畅、更省力,甚至为 ROS 1 和 ROS 2 维护来自同一分支的单一软件包。

先决条件

在将 ROS 1 软件包迁移到 ROS 2 之前,其所有依赖项都必须在 ROS 2 中可用。

迁移步骤

软件包清单

ROS 2 不支持软件包规范的格式 1,只支持较新的格式版本(2 及更高)。因此 package.xml 由于 ROS 1 支持所有格式,因此在 ROS 1 软件包中执行转换是安全的。

有些软件包在 ROS 2 中可能有不同的名称,因此可能需要相应地更新依赖关系。

元软件包

ROS 2 并没有为元软件包提供特殊的软件包类型。元软件包仍然可以作为只包含运行时依赖关系的普通软件包存在。从 ROS 1 迁移元软件包时,只需移除 元软件包 />; 标签。

信息、服务和操作定义

信息文件必须以 .msg 必须位于子文件夹 信息.服务文件必须以 .srv 必须位于子文件夹 服务.操作文件必须以 .行动 必须位于子文件夹 行动.

这些文件可能需要更新,以符合 ROS 接口定义.删除了一些原始类型,并删除了 会期时间 在 ROS 1 中是内建类型,现在已被普通的消息定义所取代,必须从 内置接口 软件包。此外,一些命名约定也比 ROS 1 更严格。

在您的 package.xml:

  • 添加 <buildtool_depend>rosidl_default_generators</buildtool_depend>;.

  • 添加 <exec_depend>rosidl_default_runtime</exec_depend>;.

  • 为每个从属报文包添加 <依赖>消息包</依赖>;.

在您的 CMakeLists.txt:

  • 从启用 C++14 开始

设置(cmake_cxx_standard 14)
  • 添加 find_package(rosidl_default_generators) 必填)

  • 为每个从属报文包添加 find_package(message_package 必填) 并将 CMake 函数调用替换为 生成消息生成接口.

这将取代 添加信息文件添加服务文件 可删除的所有信息和服务文件的列表。

构建系统

ROS 2 中的构建系统称为 动情 而构建工具是 胶管.Ament 基于 CMake 生成: ament_cmake 提供了 CMake 函数,使编写 CMakeLists.txt 文件更容易。

构建工具

而不是使用 catkin_make, catkin_make_isolated柔荑花序 构建 ROS 2 使用命令行工具 胶管 来构建和安装一组软件包。

纯 Python 软件包

如果 ROS 1 软件包仅使用 CMake 来调用 setup.py 文件,且不包含 Python 代码以外的任何内容(例如,也不包含消息、服务等),则应在 ROS 2 中转换为纯 Python 软件包:

  • package.xml 锉刀

    <export>;
      <构建类型>;ament_python</build_type>;
    </export>;
    
  • 取下 CMakeLists.txt 文件

  • 更新 setup.py 文件是一个标准的 Python 设置脚本

ROS 2 仅支持 Python 3。虽然每个软件包都可以选择同时支持 Python 2,但如果使用其他 ROS 2 软件包提供的任何 API,就必须使用 Python 3 来调用可执行文件。

更新 CMakeLists.txt 使用 ament_cmake

作出以下更改以使用 ament_cmake 而不是 柔荑花序:

  • 中设置构建类型 package.xml 文件导出部分:

    <export>;
      <构建类型>;ament_cmake</build_type>;
    </export>;
    
  • 更换 查找软件包 调用 柔荑花序组件 用:

    查找软件包(ament_cmake 要求)
    查找软件包(组件1 要求)
    # ...
    查找软件包(分量N 要求)
    
  • 移动和更新 柔荑包装 调用:

    • 调用 ament_package 而是 所有目标都已注册。

    • 唯一有效的论据是 ament_packageCONFIG_EXTRAS.所有其他参数都由单独的函数涵盖,这些函数都需要调用 之前 ament_package:

      • 而不是通过 CATKIN_DEPENDS ... 致电 ament_export_dependencies(...) 之前。

      • 而不是通过 INCLUDE_DIRS ... 致电 ament_export_include_directories(...) 之前。

      • 而不是通过 图书馆 ... 致电 ament_export_libraries(...) 之前。

    • TODO 文档 ament_export_targets(Eloquent 及更早版本中的 ``ament_export_interfaces`` )?

  • 替换调用 添加信息文件, 添加服务文件生成消息生成接口.

    • 第一个参数是 目标名称.如果您只创建一个图书馆,那么 ${project_name} 项目名称

    • 随后是相对于软件包根目录的信息文件名列表。

      • 如果要多次使用文件名列表,建议编写一个信息文件列表,并将该列表传递给函数,这样会更清晰。

    • 最后的多值关键字参数 fpr 生成消息依赖 需要依赖的信息包列表。

      生成接口(${项目名称}
        ${msg_files}
        依赖 std_msgs
      )
      
  • 删除任何出现的 开发空间.相关 CMake 变量,如 catkin_devel_prefix 不复存在。

    • "(《世界人权宣言》) CATKIN_DEPENDS取决于 参数传递给新函数 ament_export_dependencies.

    • catkin_global_bin_destination: 箱柜

    • catkin_global_include_destination: 包括

    • catkin_global_lib_destination: lib

    • catkin_global_libexec_destination: lib

    • catkin_global_share_destination: 份额

    • catkin_package_bin_destination: lib/${PROJECT_NAME}

    • catkin_package_include_destination: include/${PROJECT_NAME}

    • catkin_package_lib_destination: lib

    • 柔荑包装共享目的地: 共享/${PROJECT_NAME}。

单元测试

如果使用的是 gtest:

更换 catkin_enable_testing构建测试.替换 catkin_add_gtest添加测试.

- 如果 (CATKIN_ENABLE_TESTING)
- find_package(GTest REQUIRED) # 或 rostest
- include_directories(${GTEST_INCLUDE_DIRS})
- catkin_add_gtest(${PROJECT_NAME}-some-test src/test/some_test.cpp)
- target_link_libraries(${PROJECT_NAME}-some-test
- ${PROJECT_NAME}_some_dependency
- ${catkin_LIBRARIES}
- ${gtest_libraries})
- endif()
+ if (BUILD_TESTING)
+ find_package(ament_cmake_gtest REQUIRED)
+ ament_add_gtest(${PROJECT_NAME}-some-test src/test/test_something.cpp)
+ ament_target_dependencies(${PROJECT_NAME)-some-test
+ "rclcpp";
+ "std_msgs")
+ target_link_libraries(${PROJECT_NAME}-some-test
+ ${PROJECT_NAME}_some_dependency)
+ endif()

添加 <test_depend>amment_cmake_gtest</test_depend>; 到您的 package.xml.

- <test_depend>rostest</test_depend>;
+ <测试依赖>amment_cmake_gtest</test_depend>;

林特斯

在 ROS 2 中,我们正在努力使用衬垫来维护代码的整洁。不同语言的样式在我们的 开发人员指南.

如果你要从头开始一个项目,建议遵循样式指南,并通过添加下面这几行来开启自动林特单元测试 if(BUILD_TESTING) (在 alpha 5 之前是 ament_enable_testing).

查找软件包(自动 要求)
ament_lint_auto_find_test_dependencies()

您还需要将以下依赖项添加到您的 package.xml:

<test_depend>;自动</test_depend>;
<test_depend>;ament_lint_common</test_depend>;

继续使用 柔荑花序 在 CMake 中

ROS 2 使用 ament 作为构建系统,但为了向后兼容,ROS 2 有一个名为 柔荑花序 提供了与 ROS 1 中 catkin 几乎相同的应用程序接口。 CMakeLists.txt 必须仅在调用函数 catkin_ament_package() 所有目标。

注意:此功能尚未实施,目前只是一个想法。由于与依赖关系相关的更改较多,因此尚未确定该兼容性 API 是否有用,是否值得为此付出努力。

更新源代码

信息、服务和行动

ROS 2 消息、服务和操作的命名空间使用子命名空间 (信息, 服务行动分别)放在软件包名称之后。因此,include 看起来像 #include <my_interfaces/msg/my_message.hpp>;.然后对 C++ 类型进行命名: my_interfaces::msg::MyMessage.

共享指针类型作为类型定义在消息结构体中提供: my_interfaces::msg::MyMessage::SharedPtr 以及 my_interfaces::msg::MyMessage::ConstSharedPtr.

更多详情,请参阅有关 生成的 C++ 界面.

迁移要求通过以下方式进行更改:

  • 插入子文件夹 信息 在软件包名称和消息数据类型之间

  • 将包含的文件名从驼峰字母分隔改为下划线分隔

  • *.h*.hpp

// ROS 1 的样式在注释中,ROS 2 紧随其后,未加注释。
// # include <geometry_msgs/PointStamped.h>;
#include <geometry_msgs/msg/point_stamped.hpp>;

// geometry_msgs::PointStamped point_stamped;
几何参数::信息::点戳 点戳记;

迁移需要代码插入 信息 命名空间到所有实例中。

服务对象的使用

ROS 2 中的服务回调没有布尔返回值。建议不要在失败时返回 false,而是抛出异常。

// ROS 1 的样式在注释中,ROS 2 紧随其后,未加注释。
// #include "nav_msgs/GetMap.h";
#include "nav_msgs/srv/get_map.hpp";

// bool service_callback(
// nav_msgs::GetMap::Request & request、
// nav_msgs::GetMap::Response & response)
空白 服务回调(
   标准::共享_ptr<;nav_msgs::服务::获取地图::要求>; 要求,
  标准::共享_ptr<;nav_msgs::服务::获取地图::回应>; 回应)
{
  // ...
  // 返回 true; // 失败则返回 false
}

ros::Time 的用法

用于 ros::时间:

  • 替换所有 ros::时间rclcpp::Time

  • 如果您的信息或代码使用了 std_msgs::Time.Time,那么您就会发现

    • 将 std_msgs::Time 的所有实例转换为 builtin_interfaces::msg::Time

    • 转换所有 #include "std_msgs/time.h#include "builtin_interfaces/msg/time.hpp";

    • 使用 std_msgs::Time 字段转换所有实例 nsec 到内置接口::msg::时间字段 纳米

ros::Rate 的用法

有一个等价类型 rclcpp::Rate 对象,它基本上可以替代 ros::Rate.

ROS 客户端库

注:其他有待编写

提升

之前由 Boost 提供的许多功能已被集成到 C++ 标准库中。因此,我们希望利用新的核心功能,尽可能避免对 boost 的依赖。

共享指针

要将共享指针从 boost 转换为标准 C++,请替换以下实例:

  • #include <boost/shared_ptr.hpp>;#include <内存>;

  • boost::shared_ptrstd::shared_ptr

还有一些变体,例如 弱_ptr 您也想转换它。

此外,建议使用 使用 而不是 类型化. 使用 能在模板逻辑中更好地工作。详细信息 参见此处

线程/特例

ROS 代码库中另一个常用的 boost 部分是 boost::线程.

  • 更换 boost::mutex::scoped_lock(锁定)std::unique_lock<std::mutex>;

  • 更换 boost::mutexstd::mutex

  • 更换 #include <boost/thread/mutex.hpp>;#include mutex>;

无序地图

更换:

  • #include <boost/unordered_map.hpp>;#include <unordered_map>;

  • boost::unordered_mapstd::unordered_map

功能

更换:

  • #include <boost/function.hpp>;#include 功能强大;

  • boost::functionstd::function

参数

在 ROS 1 中,参数与中央服务器相关联,允许在运行时通过使用网络应用程序接口检索参数。在 ROS 2 中,参数与每个节点相关联,并可在运行时通过 ROS 服务进行配置。

启动文件

在 ROS 1 中,启动文件总是使用 .xml 文件,ROS 2 支持 Python 脚本,使其更具灵活性(参见 发射包) 以及 XML 和 YAML 文件。参见 单独教程 将启动文件从 ROS 1 移植到 ROS 2。

示例:将现有的 ROS 1 软件包转换为使用 ROS 2

假设我们有一个简单的 ROS 1 软件包,名为 话匣子 使用 roscpp 在一个节点中,称为 话匣子.该软件包在 catkin 工作区中,位于 ~/ros1_talker.

ROS 1 代码

这是我们柔荑花序工作区的目录布局:

$ CD ~/ros1_talker $ 找到 ../src ./src/talker ./src/talker/package.xml ./src/talker/CMakeLists.txt ./src/talker/talker.cpp

以下是这三个文件的内容:

src/talker/package.xml:

<package>;
  <名称>;话匣子</名称>;
  版本>;0.0.0</version>;
  <描述>;话匣子</description>;
  维护者 电子邮件="[email protected]";>;布莱恩 格基维护人员</maintainer>;
  许可证阿帕奇 2.0</license>;
  构建工具的依赖关系<buildtool_depend>;柔荑花序</buildtool_depend>;
  构建依赖关系;roscpp</build_depend>;
  构建依赖关系;std_msgs</build_depend>;
  <run_depend>;roscpp</run_depend>;
  <run_depend>;std_msgs</run_depend>;
</package>;

src/talker/CMakeLists.txt:

cmake_minimum_required(版本 2.8.3)
项目(话匣子)
查找软件包(柔荑花序 要求 组件 roscpp std_msgs)
柔荑包装()
包含目录(${catkin_INCLUDE_DIRS})
添加可执行(话匣子 talker.cpp)
目标链接库(话匣子 ${柔荑_藏书})
安装(目标 话匣子
  运行时间 目的地 ${catkin_package_bin_destination})

src/talker/talker.cpp:

#include 流>;
#include "ros/ros.h";
#include "std_msgs/String.h";
int 主要(int 参数, 烧焦 **参数)
{
  玫瑰::启动(参数, 参数, 健谈;);
  玫瑰::节点句柄 n;
  玫瑰::出版商 喋喋不休_pub = n.登广告<;std_msgs::字符串>;(唠叨";, 1000);
  玫瑰::费率 循环速率(10);
  int 计数 = 0;
  std_msgs::字符串 信息;
  虽然 (玫瑰::好的())
  {
    标准::字符串流 ss;
    ss <<; 你好世界; <<; 计数++;
    信息.数据 = ss.字符串();
    ROS_INFO("%s";, 信息.数据.c_str());
    喋喋不休_pub.发布(信息);
    玫瑰::自旋一次();
    循环速率.睡眠();
  }
  返回 0;
}

构建 ROS 1 代码

我们为环境设置文件(本例中为使用 bash 的 Jade)提供源代码,然后使用 catkin_make 安装:

. /opt/ros/jade/setup.bash
CD ~/ros1_talker catkin_make 安装

运行 ROS 1 节点

如果还没有运行,我们会启动一个 玫瑰核首先从我们的 柔荑花序 安装树(位于 /opt/ros/jade/setup.bash 在这里也适用):

. ~/ros1_talker/install/setup.bash roscore

在另一个 shell 中,我们从 柔荑花序 使用安装空间 玫瑰在这种情况下,它必须是我们工作区中的文件):

. ~/ros1_talker/install/setup.bash rosrun 话匣子 话匣子

迁移到 ROS 2

首先,让我们创建一个新的工作区:

mkdir ~/ros2_talker
CD ~/ros2_talker

我们将把 ROS 1 软件包中的源代码树复制到该工作区,然后对其进行修改:

mkdir src cp -a ~/ros1_talker/src/talker 来源

现在我们要修改节点中的 C++ 代码。ROS 2 C++ 库名为 rclcpp提供了与 roscpp.这两个库的概念非常相似,因此更改起来相当简单。

包括页眉

代替 ros/ros.h这使我们能够访问 roscpp 库应用程序接口,我们需要将 rclcpp/rclcpp.hpp这样我们就可以访问 rclcpp 库应用程序接口:

//#include "ros/ros.h";
#include "rclcpp/rclcpp.hpp";

要获得 std_msgs/String 消息定义,以代替 std_msgs/String.h我们需要包括 std_msgs/msg/string.hpp:

//#include "std_msgs/String.h";
#include "std_msgs/msg/string.hpp";

更改 C++ 库调用

我们不将节点名称传递给库初始化调用,而是先进行初始化,然后在创建节点对象时传递节点名称(我们可以使用 汽车 关键字,因为现在我们需要使用 C++14 编译器):

// ros::init(argc, argv, "talker");
// ros::NodeHandle n;
    rclcpp::启动(参数, 参数);
    汽车 网站 = rclcpp::节点::共享(健谈;);

发布者和费率对象的创建过程非常相似,只是名称空间和方法的名称有些变化。

// ros::Publisher chatter_pub = n.advertise<std_msgs::String>("chatter", 1000);
// ros::Rate loop_rate(10);
  汽车 喋喋不休_pub = 网站->;创建出版商<;std_msgs::信息::字符串>;(唠叨";,
    1000);
  rclcpp::费率 循环速率(10);

为了进一步控制信息传送的处理方式,服务质量 (服务质量) 配置文件。默认配置文件是 rmw_qos_profile_default.更多详情,请参阅 设计文件概念概述.

在命名空间中,外发消息的创建是不同的:

// std_msgs::String msg;
  std_msgs::信息::字符串 信息;

代替 ros::ok()我们称之为 rclcpp::ok():

// while (ros::ok())
  虽然 (rclcpp::好的())

在发布循环中,我们访问 数据 字段:

信息.数据 = ss.字符串();

要打印控制台信息,请不要使用 ROS_INFO()我们使用 RCLCPP_INFO() 及其各种同类产品。主要区别在于 RCLCPP_INFO() 的第一个参数是一个日志记录器对象。

// ROS_INFO("%s", msg.data.c_str());
    RCLCPP_INFO(网站->;get_logger(), "%s\n";, 信息.数据.c_str());

发布信息的方式和以前一样:

喋喋不休_pub->;发布(信息);

旋转(即让通信系统处理任何待处理的传入/传出信息)的不同之处在于,调用现在将节点作为参数:

// ros::spinOnce();
    rclcpp::旋转(网站);

使用速率对象进行睡眠的情况不变。

综上所述,新的 talker.cpp 看起来是这样的

#include 流>;
// #include "ros/ros.h";
#include "rclcpp/rclcpp.hpp";
// #include "std_msgs/String.h";
#include "std_msgs/msg/string.hpp";
int 主要(int 参数, 烧焦 **参数)
{
// ros::init(argc, argv, "talker");
// ros::NodeHandle n;
  rclcpp::启动(参数, 参数);
  汽车 网站 = rclcpp::节点::共享(健谈;);
// ros::Publisher chatter_pub = n.advertise<std_msgs::String>("chatter", 1000);
// ros::Rate loop_rate(10);
  汽车 喋喋不休_pub = 网站->;创建出版商<;std_msgs::信息::字符串>;(唠叨";, 1000);
  rclcpp::费率 循环速率(10);
  int 计数 = 0;
// std_msgs::String msg;
  std_msgs::信息::字符串 信息;
// while (ros::ok())
  虽然 (rclcpp::好的())
  {
    标准::字符串流 ss;
    ss <<; 你好世界; <<; 计数++;
    信息.数据 = ss.字符串();
// ROS_INFO("%s", msg.data.c_str());
    RCLCPP_INFO(网站->;get_logger(), "%s\n";, 信息.数据.c_str());
    喋喋不休_pub->;发布(信息);
// ros::spinOnce();
    rclcpp::旋转(网站);
    循环速率.睡眠();
  }
  返回 0;
}

改变 package.xml

ROS 2 不支持软件包规范的格式 1,只支持较新的格式版本(2 及更高)。我们首先在 包装 标签

<!-- <package> -->;
<package 格式="2";>;

ROS 2 使用更新版本的 柔荑花序称为 ament_cmake我们在 buildtool_depend 标签

<!-- <buildtool_depend>catkin</buildtool_depend> -->;
  构建工具的依赖关系<buildtool_depend>;ament_cmake</buildtool_depend>;

在我们的构建依赖项中,用 roscpp 我们使用 rclcpp提供了我们使用的 C++ 应用程序接口。

<!-- <build_depend>roscpp</build_depend> -->;
  构建依赖关系;rclcpp</build_depend>;

我们在运行依赖项中添加了同样的内容,并从 运行依赖 标记到 执行依赖 标记(软件包格式升级到第 2 版的一部分):

<!-- <run_depend>roscpp</run_depend> -->;
  执行依赖关系;rclcpp</exec_depend>;
<!-- <run_depend>std_msgs</run_depend> -->;
  执行依赖关系;std_msgs</exec_depend>;

在 ROS 1 中,我们使用 <依赖>; 来简化编译时和运行时的依赖关系。我们也可以在 ROS 2 中这样做:

<依赖>;rclcpp依赖</depend>;
<依赖>;std_msgs依赖</depend>;

我们还需要告诉构建工具 一种 这样它就知道如何构建我们。因为我们使用 动情 和 CMake,我们添加以下几行来声明我们的编译类型是 ament_cmake:

<export>;
  <构建类型>;ament_cmake</build_type>;
</export>;

综上所述,我们的 package.xml 现在看起来是这样的

<!-- <package> -->;
<package 格式="2";>;
  <名称>;话匣子</名称>;
  版本>;0.0.0</version>;
  <描述>;话匣子</description>;
  维护者 电子邮件="[email protected]";>;布莱恩 格基维护人员</maintainer>;
  许可证阿帕奇 许可证 2.0</license>;
<!-- <buildtool_depend>catkin</buildtool_depend> -->;
  构建工具的依赖关系<buildtool_depend>;ament_cmake</buildtool_depend>;
<!-- <build_depend>roscpp</build_depend> -->;
<!-- <run_depend>roscpp</run_depend> -->;
<!-- <run_depend>std_msgs</run_depend> -->;
  <依赖>;rclcpp依赖</depend>;
  <依赖>;std_msgs依赖</depend>;
  <export>;
    <构建类型>;ament_cmake</build_type>;
  </export>;
</package>;

TODO: 仅使用 ``<depend>`` 标记来显示该文件的简化版本,第 2 版软件包格式启用了该标记(``catkin`` 中也支持该标记,因此严格来说,与 ROS 2 无关)。

更改 CMake 代码

ROS 2 依赖于更高版本的 CMake:

#cmake_minimum_required(VERSION 2.8.3)
cmake_minimum_required(版本 3.5)

ROS 2 依赖于 C++14 标准。根据您使用的编译器,默认情况下可能不会启用对 C++14 的支持。使用 gcc 5.3(即 Ubuntu Xenial 上使用的版本),我们需要明确启用它,方法是在文件顶部附近添加这一行:

设置(cmake_cxx_standard 14)

在所有平台上的首选工作方式是这样的:

如果(不是 cmake_cxx_standard)
  设置(cmake_cxx_standard 14)
endif()
如果(cmake_compiler_is_gnucxx  cmake_cxx_compiler_id 比赛 "Clang";)
  添加编译选项(-墙 -Wextra -Wpedantic)
endif()

使用 柔荑花序,我们以 组件 在最初发现 柔荑花序 它本身。与 ament_cmake,我们逐个找到每个软件包,从 ament_cmake:

#find_package(catkin 必要组件 roscpp std_msgs)
查找软件包(ament_cmake 要求)
查找软件包(rclcpp 要求)
查找软件包(std_msgs 要求)

可以像以前一样找到系统依赖项:

查找软件包(提升 要求 组件 系统 文件系统 线程)

我们称之为 catkin_package() 来自动生成诸如 CMake 配置文件之类的东西,供其他使用我们软件包的软件包使用。而调用 之前 我们现在调用类似的 ament_package() 目标:

# catkin_package()
# 在文件底部:
ament_package()

唯一需要手动包含的目录是本地目录和非软件包的依赖项:

#include_directories(${catkin_INCLUDE_DIRS})
包含目录(包括 ${Boost_INCLUDE_DIRS})

更好的办法是为每个目标分别指定包含目录,而不是包含所有目标的所有目录:

目标包含目录(目标 公众 包括 ${Boost_INCLUDE_DIRS})

与我们分别找到每个依赖包的方法类似,我们需要将每个依赖包链接到联编目标。要与作为附加软件包的依赖软件包链接,请不要使用 target_link_libraries(), ament_target_dependencies() 是一种更简洁、更彻底的构建标记处理方法。它会自动处理在 _INCLUDE_DIRS 中定义的链接库 _图书.

#target_link_libraries(talker ${catkin_LIBRARIES})
ament_target_dependencies(话匣子
  rclcpp
  std_msgs)

链接非附件软件包,如系统依赖包,如 提升或在同一地点建造图书馆 CMakeLists.txt使用 target_link_libraries():

目标链接库(目标 ${Boost_LIBRARIES})

用于安装、 柔荑花序 定义了如下变量 catkin_package_bin_destination.与 ament_cmake我们只需给出一个相对于安装根目录的路径,例如 箱柜 可执行文件:

#install(TARGETS talker
# 运行时目的地 ${catkin_package_bin_destination})
安装(目标 话匣子
  目的地 lib/${项目名称})

作为选项,我们可以为下游软件包安装和导出包含的目录:

安装(目录 包括
  目的地 包括)
ament_export_include_directories(包括)

作为选项,我们可以导出下游软件包的依赖关系:

ament_export_dependencies(std_msgs)

综上所述,新的 CMakeLists.txt 看起来是这样的

#cmake_minimum_required(VERSION 2.8.3)
cmake_minimum_required(版本 3.5)
项目(话匣子)
如果(不是 cmake_cxx_standard)
  设置(cmake_cxx_standard 14)
endif()
如果(cmake_compiler_is_gnucxx  cmake_cxx_compiler_id 比赛 "Clang";)
  添加编译选项(-墙 -Wextra -Wpedantic)
endif()
#find_package(catkin 必要组件 roscpp std_msgs)
查找软件包(ament_cmake 要求)
查找软件包(rclcpp 要求)
查找软件包(std_msgs 要求)
#catkin_package()
#include_directories(${catkin_INCLUDE_DIRS})
包含目录(包括)
添加可执行(话匣子 talker.cpp)
#target_link_libraries(talker ${catkin_LIBRARIES})
ament_target_dependencies(话匣子
  rclcpp
  std_msgs)
#install(TARGETS talker
# 运行时目的地 ${catkin_package_bin_destination})
安装(目标 话匣子
  目的地 lib/${项目名称})
安装(目录 包括
  目的地 包括)
ament_export_include_directories(包括)
ament_export_dependencies(std_msgs)
ament_package()

TODO: 展示使用 ``ament_auto`` 时的效果。

构建 ROS 2 代码

我们将一个环境设置文件作为源文件(在本例中,环境设置文件是根据 ROS 2 安装教程生成的,它以 ~/ros2_ws然后我们使用 胶管 构建:

. ~/ros2_ws/install/setup.bash
CD ~/ros2_talker colcon 构建

运行 ROS 2 节点

因为我们安装了 话匣子 可执行 箱柜在从安装树中获取设置文件后,我们可以直接调用它的名称(另外,ROS 2 中还没有与 玫瑰):

. ~/ros2_ws/install/setup.bash talker

更新脚本

ROS CLI 参数

因为 ROS Eloquent,ROS 参数的作用域应为 --ros-args 和后面的 -- (如果后面没有参数,后面的双破折号可以省略)。

重映射名称与 ROS 1 类似,形式为 从:=到,但必须在它前面加上一个 --remap (或 -r) 标志。例如

玫瑰2 运行 某些软件包 some_ros_executable --ros-args -r foo:=酒吧

我们对参数使用类似的语法,使用 --参数 (或 -p)标志:

玫瑰2 运行 某些软件包 some_ros_executable --ros-args -p 我的参数=价值

注意,这与在 ROS 1 中使用下划线不同。

要更改节点名称,请使用 节点 (等效的 ROS 1 是 姓名):

玫瑰2 运行 某些软件包 some_ros_executable --ros-args -r __节点:=新节点名称

注意使用 -r 标志。更改命名空间时也需要使用同样的重映射标志 n:

玫瑰2 运行 某些软件包 some_ros_executable --ros-args -r __ns:=/new/namespace

下列 ROS 1 按键在 ROS 2 中没有对应的功能:

  • 日志 (但是 --日志配置文件 可用于提供记录仪配置文件)

  • __ip

  • __主机名

  • __校长

更多信息,请参阅 设计文件.

快速参考

特点

ROS 1

ROS 2

重映射

foo:=bar

-r foo:=bar

参数

_foo:=bar

-p foo:=bar

节点名

___名:=foo

-r __node:=foo

命名空间

__ns:=foo

-r __ns:=foo

更多示例和工具

许可

在 ROS 2 中,我们推荐使用 Apache 2.0 许可.在 ROS 1 中,我们推荐的许可证是 3 条款 BSD 许可.

对于任何新项目,无论是 ROS 1 还是 ROS 2,我们都建议使用 Apache 2.0 许可。

不过,在将代码从 ROS 1 移植到 ROS 2 时,我们不能简单地更改许可证。任何已有的贡献都必须保留现有的许可证。

为此,如果要迁移软件包,我们建议保留现有许可证,并继续根据现有的 OSI 许可证为该软件包做出贡献,我们希望该许可证成为核心元素的 BSD 许可证。

这将使事情清晰易懂。

更改许可证

更改许可证是可能的,但需要联系所有贡献者并获得许可。对于大多数软件包来说,这可能是一项艰巨的工作,不值得考虑。如果软件包的贡献者较少,则可能可行。