警告
您正在阅读的 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_package 是
CONFIG_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 的依赖。
线程/特例
ROS 代码库中另一个常用的 boost 部分是 boost::线程
.
更换
boost::mutex::scoped_lock(锁定)
与std::unique_lock<std::mutex>;
更换
boost::mutex
与std::mutex
更换
#include <boost/thread/mutex.hpp>;
与#include mutex>;
无序地图
更换:
#include <boost/unordered_map.hpp>;
与#include <unordered_map>;
boost::unordered_map
与std::unordered_map
功能
更换:
#include <boost/function.hpp>;
与#include 功能强大;
boost::function
与std::function
参数
在 ROS 1 中,参数与中央服务器相关联,允许在运行时通过使用网络应用程序接口检索参数。在 ROS 2 中,参数与每个节点相关联,并可在运行时通过 ROS 服务进行配置。
参见 ROS 2 参数设计文件 了解有关系统模型的更多详情。
参见 ROS 2 CLI 使用方法 以更好地了解 CLI 工具的工作原理及其与 ROS 1 工具的区别。
参见 从 ROS 1 迁移 YAML 参数文件到 ROS 2 来了解 ROS 2 如何解析 YAML 参数文件,以及它们与 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 1 XML 启动文件转换为 ROS 2 Python 启动文件: https://github.com/aws-robotics/ros2-launch-file-migrator
亚马逊公开了将 ROS 1 机器人移植到 ROS 2 的工具 https://github.com/awslabs/ros2-migration-tools/tree/master/porting_tools
许可
在 ROS 2 中,我们推荐使用 Apache 2.0 许可.在 ROS 1 中,我们推荐的许可证是 3 条款 BSD 许可.
对于任何新项目,无论是 ROS 1 还是 ROS 2,我们都建议使用 Apache 2.0 许可。
不过,在将代码从 ROS 1 移植到 ROS 2 时,我们不能简单地更改许可证。任何已有的贡献都必须保留现有的许可证。
为此,如果要迁移软件包,我们建议保留现有许可证,并继续根据现有的 OSI 许可证为该软件包做出贡献,我们希望该许可证成为核心元素的 BSD 许可证。
这将使事情清晰易懂。
更改许可证
更改许可证是可能的,但需要联系所有贡献者并获得许可。对于大多数软件包来说,这可能是一项艰巨的工作,不值得考虑。如果软件包的贡献者较少,则可能可行。