Dashing Diademata (dashing)

Dashing Diademata 是 ROS 2 的第四个版本。

支持的平台

Dashing Diademata 主要支持以下平台:

第 1 层平台:

  • Ubuntu 18.04 (Bionic):“amd64”和“arm64”

  • Mac macOS 10.12 (Sierra)

  • Windows 10 (Visual Studio 2019)

第 2 层平台:

  • Ubuntu 18.04 (Bionic):“arm32”

第 3 层平台:

  • Debian Stretch (9):“amd64”、“arm64”和“arm32”

  • OpenEmbedded Thud (2.6) / webOS OSE:“arm32”和“x86”

有关 RMW 实现、编译器/解释器版本和系统依赖项版本的更多信息,请参阅“REP 2000 <https://www.ros.org/reps/rep-2000.html#dashing-diademata-may-2019-may-2021>”__。

安装

Install Dashing Diademata

此 ROS 2 版本中的新功能

我们想强调一些功能和改进:

  • 组件 现在是编写节点的推荐方式。

它们可以独立使用,也可以在进程内组合使用,并且这两种方式都完全受 launch 文件的支持。 * 进程内通信 <../Tutorials/Demos/Intra-Process-Communication>`(仅限 C++)已得到改进 - 无论是在延迟方面还是在最小化副本方面。 * Python 客户端库已更新以匹配大多数 C++ 等效库,并且已经实现了一些与内存使用和性能相关的重要错误修复和改进。 * 参数现在是 ROS 1 中 ``dynamic_reconfigure` 的完整替代方案,包括范围或只读等约束。 * 通过依赖(子集)`IDL 4.2 <https://www.omg.org/spec/IDL/4.2>`__ 作为消息生成管道,现在可以使用 .idl 文件(除了 .msg / .srv / .action 文件)。 此更改支持普通字符串的可选 UTF-8 编码以及 UTF-16 编码的多字节字符串(请参阅``宽字符串设计文章 <https://design.ros2.org/articles/wide_strings.html>`__)。 * 与``actions``和``components``相关的命令行工具。 * 支持 Deadline、Lifespan 和 Liveliness 服务质量设置。 * MoveIt 2 alpha 版本

请参阅 GitHub 上的“Dashing 元票证 <https://github.com/ros2/ros2/issues/607>”,其中包含更多信息以及带有更多详细信息的特定票证的引用。

自 Crystal 发布以来的变化

声明参数

从 Dashing 开始,参数的行为发生了一些变化,这也导致了一些新的 API 和其他 API 的弃用。 有关 API 更改的更多信息,请参阅下面的“rclcpp”和“rclpy”部分。

获取和设置未声明的参数

从 Dashing 开始,现在需要在访问或设置参数之前声明参数。

在 Dashing 之前,您可以调用 get_parameter(name) 并获取一个值(如果之前已设置)或 PARAMETER_NOT_SET 类型的参数。

您还可以随时调用 set_parameter(name, value),即使该参数之前未设置。

从 Dashing 开始,您需要先声明一个参数,然后才能获取或设置它。

如果您尝试获取或设置未声明的参数,您将会得到一个异常,例如 ParameterNotDeclaredException,或者在某些情况下,您将以各种方式传达不成功的结果(有关更多详细信息,请参阅特定函数)。

但是,您可以获得通过在创建节点时使用 allow_undeclared_pa​​rameters 选项来恢复旧行为(大多数情况下,请参阅下一段中的注释)。 您可能希望这样做以避免暂时更改代码,或者为了满足一些不常见的用例。 例如,“全局参数服务器”或“参数黑板”可能希望允许外部节点在不先声明新参数的情况下自行设置新参数,因此它可以使用 allow_undeclared_pa​​rameters 选项来实现这一点。 但是,在大多数情况下,不建议使用此选项,因为它会使其余参数 API 不太安全,容易出现参数名称拼写错误和“设置前使用”逻辑错误等错误。

请注意,使用 allow_undeclared_pa​​rameters 将使您获得大多数旧行为,特别是针对“get”和“set”方法,但它不会将与参数相关的所有行为更改恢复为 ROS Crystal 的状态。 为此,您还需要将 automatically_declare_parameters_from_overrides 选项设置为 true,如下文 使用 YAML 文件 <parameter-configuration-using-a-yaml-file> 进行参数配置` 中所述。

使用 ParameterDescriptor 声明参数

在使用参数之前声明参数的另一个好处是,它允许您同时声明参数描述符。

现在,在声明参数时,您可以包含自定义“ParameterDescriptor”以及名称和默认值。 “ParameterDescriptor”在“rcl_interfaces/msg/ParameterDescriptor”中定义为一条消息,包含元数据(如“description”)和约束(如“read_only”或“integer_range”)。 这些约束可用于在设置参数时拒绝无效值和/或作为对外部工具的提示,提示给定参数的有效值。 “read_only”约束将防止参数的值在声明后发生变化,并防止其被取消声明。

作为参考,以下是撰写本文时的 ParameterDescriptor 消息的链接:

https://github.com/ros2/rcl_interfaces/blob/0aba5a142878c2077d7a03977087e7d74d40ee68/rcl_interfaces/msg/ParameterDescriptor.msg#L1

使用 YAML 文件进行参数配置

从 Dashing 开始,YAML 配置文件中的参数(例如通过命令行参数 __params:= 传递给节点的参数)仅用于在声明参数时覆盖参数的默认值。

在 Dashing 之前,任何参数您通过 YAML 文件传递​​的参数将隐式设置在节点上。

自 Dashing 以来,情况不再如此,因为需要声明参数才能在节点上显示给外部观察者,例如“ros2 参数列表”。

旧行为可以在创建节点时使用“automatically_declare_parameters_from_overrides”选项实现。 如果将此选项设置为“true”,则在构建节点时将自动声明输入 YAML 文件中的所有参数。 这可用于避免对现有代码进行重大更改或用于特定用例。 例如,“全局参数服务器”可能希望在启动时使用任意参数进行播种,而它无法提前声明这些参数。 但是,大多数情况下不建议使用此选项,因为它可能导致在 YAML 文件中设置参数,并假设节点将使用它,即使节点实际上不使用它。

我们希望将来能有一个检查器,如果您将参数传递给节点,而节点没有预料到,它会向您发出警告。

YAML 文件中的参数将继续影响首次声明时参数的值。

ament_cmake

CMake 函数 ament_index_has_resource 返回 TRUEFALSE

此版本 开始,它返回前缀路径(如果找到资源)或 FALSE

如果您在 CMake 条件中使用返回值,如下所示:

ament_index_has_resource(var ...)
if(${var})

您需要更新条件以确保它将字符串值视为“TRUE”:

if(var)

rclcpp

Node::get_node_names() 的行为变化

函数 NodeGraph::get_node_names(),以及 Node::get_node_names(),现在返回一个 std::vector<std::string>,其中包含完全限定的节点名称及其命名空间,而不仅仅是节点名称。

更改了将选项传递给节点的方式

rclcpp::Node() 构造函数的扩展参数(除名称和命名空间外)已被替换为 rclcpp::NodeOptions 结构。

有关选项的结构和默认值的详细信息,请参阅 ros2/rclcpp#622

如果您使用 rclcpp::Node() 的任何扩展参数,如下所示:

auto context = rclcpp::contexts::default_context::get_global_default_context();
std::vector<std::string> args;
std::vector<rclcpp::Parameter> params = { rclcpp::Parameter("use_sim_time", true) };
auto node = std::make_shared<rclcpp::Node>("foo_node", "bar_namespace", context, args, params);

您需要更新才能使用“NodeOptions”结构

std::vector<std::string> args;
std::vector<rclcpp::Parameter> params = { rclcpp::Parameter("use_sim_time", true) };
rclcpp::NodeOptions node_options;
node_options.arguments(args);
node_options.parameter_overrides(params);
auto node = std::make_shared<rclcpp::Node>("foo_node", "bar_namespace", node_options);

创建发布者和订阅的变更

Dashing 中对创建发布者和订阅进行了一些新变更:

  • QoS 设置现在使用新的 rclcpp::QoS 类传递,并且 API 鼓励用户至少指定历史深度。

  • 选项现在作为对象传递,即 rclcpp::PublisherOptionsrclcpp::SubscriptionOptions

所有变更都向后兼容(无需更改代码),但已弃用几种现有的调用样式。

鼓励用户更新到新签名。


过去,在创建发布者或订阅时,您可以不指定任何 QoS 设置(例如,只提供发布者的主题名称),也可以指定“qos 配置文件”数据结构(类型为“rmw_qos_profile_t”),其中已设置所有设置。

现在,您必须使用新的“rclcpp::QoS”对象来指定您的 QoS 以及至少您的 QoS 的历史记录设置。

这鼓励用户在使用“KEEP_LAST”时指定历史记录深度,而不是将其默认为可能合适也可能不合适的值。

在 ROS 1 中,这被称为“queue_size”,并且在 C++ 和 Python 中都是必需的。

我们正在更改 ROS 2 API 以恢复此要求。


此外,之前在创建发布者或订阅时可以传递的任何选项现在分别封装在 rclcpp::PublisherOptionsrclcpp::SubscriptionOptions 类中。 这样可以缩短签名,使用起来更方便,并且可以在不破坏 API 的情况下添加新的未来选项。


一些用于创建发布者和订阅者的签名现已弃用,并添加了新的签名以允许您使用新的 rclcpp::QoS 和发布者/订阅选项类。

这些是新的和推荐的 API:

template<
  typename MessageT,
  typename AllocatorT = std::allocator<void>,
  typename PublisherT = ::rclcpp::Publisher<MessageT, AllocatorT>>
std::shared_ptr<PublisherT>
create_publisher(
  const std::string & topic_name,
  const rclcpp::QoS & qos,
  const PublisherOptionsWithAllocator<AllocatorT> & options =
  PublisherOptionsWithAllocator<AllocatorT>()
);

template<
  typename MessageT,
  typename CallbackT,
  typename AllocatorT = std::allocator<void>,
  typename SubscriptionT = rclcpp::Subscription<
    typename rclcpp::subscription_traits::has_message_type<CallbackT>::type, AllocatorT>>
std::shared_ptr<SubscriptionT>
create_subscription(
  const std::string & topic_name,
  const rclcpp::QoS & qos,
  CallbackT && callback,
  const SubscriptionOptionsWithAllocator<AllocatorT> & options =
  SubscriptionOptionsWithAllocator<AllocatorT>(),
  typename rclcpp::message_memory_strategy::MessageMemoryStrategy<
    typename rclcpp::subscription_traits::has_message_type<CallbackT>::type, AllocatorT
  >::SharedPtr
  msg_mem_strat = nullptr);

以下是已弃用的:

template<
  typename MessageT,
  typename AllocatorT = std::allocator<void>,
  typename PublisherT = ::rclcpp::Publisher<MessageT, AllocatorT>>
[[deprecated("use create_publisher(const std::string &, const rclcpp::QoS &, ...) instead")]]
std::shared_ptr<PublisherT>
create_publisher(
  const std::string & topic_name,
  size_t qos_history_depth,
  std::shared_ptr<AllocatorT> allocator);

template<
  typename MessageT,
  typename AllocatorT = std::allocator<void>,
  typename PublisherT = ::rclcpp::Publisher<MessageT, AllocatorT>>
[[deprecated("use create_publisher(const std::string &, const rclcpp::QoS &, ...) instead")]]
std::shared_ptr<PublisherT>
create_publisher(
  const std::string & topic_name,
  const rmw_qos_profile_t & qos_profile = rmw_qos_profile_default,
  std::shared_ptr<AllocatorT> allocator = nullptr);

template<
  typename MessageT,
  typename CallbackT,
  typename Alloc = std::allocator<void>,
  typename SubscriptionT = rclcpp::Subscription<
    typename rclcpp::subscription_traits::has_message_type<CallbackT>::type, Alloc>>
[[deprecated(
  "use create_subscription(const std::string &, const rclcpp::QoS &, CallbackT, ...) instead"
)]]
std::shared_ptr<SubscriptionT>
create_subscription(
  const std::string & topic_name,
  CallbackT && callback,
  const rmw_qos_profile_t & qos_profile = rmw_qos_profile_default,
  rclcpp::callback_group::CallbackGroup::SharedPtr group = nullptr,
  bool ignore_local_publications = false,
  typename rclcpp::message_memory_strategy::MessageMemoryStrategy<
    typename rclcpp::subscription_traits::has_message_type<CallbackT>::type, Alloc>::SharedPtr
  msg_mem_strat = nullptr,
  std::shared_ptr<Alloc> allocator = nullptr);

template<
  typename MessageT,
  typename CallbackT,
  typename Alloc = std::allocator<void>,
  typename SubscriptionT = rclcpp::Subscription<
    typename rclcpp::subscription_traits::has_message_type<CallbackT>::type, Alloc>>
[[deprecated(
  "use create_subscription(const std::string &, const rclcpp::QoS &, CallbackT, ...) instead"
)]]
std::shared_ptr<SubscriptionT>
create_subscription(
  const std::string & topic_name,
  CallbackT && callback,
  size_t qos_history_depth,
  rclcpp::callback_group::CallbackGroup::SharedPtr group = nullptr,
  bool ignore_local_publications = false,
  typename rclcpp::message_memory_strategy::MessageMemoryStrategy<
    typename rclcpp::subscription_traits::has_message_type<CallbackT>::type, Alloc>::SharedPtr
  msg_mem_strat = nullptr,
  std::shared_ptr<Alloc> allocator = nullptr);

QoS 传递方式的改变最有可能对用户产生影响。

对于发布商来说,典型的改变如下:

- pub_ = create_publisher<std_msgs::msg::String>("chatter");
+ pub_ = create_publisher<std_msgs::msg::String>("chatter", 10);

订阅如下:

- sub_ = create_subscription<std_msgs::msg::String>("chatter", callback);
+ sub_ = create_subscription<std_msgs::msg::String>("chatter", 10, callback);

如果您不知道要使用什么深度,并且现在也不关心(可能只是原型设计),那么我们建议使用“10”,因为这是之前的默认值,应该保留现有行为。

有关如何选择合适深度的更多深入文档即将发布。

这是一个稍微复杂一些的更改示例,旨在避免使用新弃用的 API:

- // Creates a latched topic
- rmw_qos_profile_t qos = rmw_qos_profile_default;
- qos.depth = 1;
- qos.durability = RMW_QOS_POLICY_DURABILITY_TRANSIENT_LOCAL;
-
  model_xml_.data = model_xml;
  node_handle->declare_parameter("robot_description", model_xml);
  description_pub_ = node_handle->create_publisher<std_msgs::msg::String>(
-   "robot_description", qos);
+   "robot_description",
+   // Transient local is similar to latching in ROS 1.
+   rclcpp::QoS(1).transient_local());

请参阅引入 QoS 更改的拉取请求(以及连接的拉取请求)以获取更多示例和详细信息:

由于声明参数更改而导致的更改

有关实际行为更改的详细信息,请参阅上面的`声明参数`_。

rclcpp::Node 的接口中有几个新的 API 调用:

  • 声明给定名称、可选默认值、可选描述符的参数并返回实际设置的值的方法:

    const rclcpp::ParameterValue &
    rclcpp::Node::declare_parameter(
      const std::string & name,
      const rclcpp::ParameterValue & default_value = rclcpp::ParameterValue(),
      const rcl_interfaces::msg::ParameterDescriptor & parameter_descriptor =
      rcl_interfaces::msg::ParameterDescriptor());
    
    template<typename ParameterT>
    auto
    rclcpp::Node::declare_parameter(
      const std::string & name,
      const ParameterT & default_value,
      const rcl_interfaces::msg::ParameterDescriptor & parameter_descriptor =
      rcl_interfaces::msg::ParameterDescriptor());
    
    template<typename ParameterT>
    std::vector<ParameterT>
    rclcpp::Node::declare_parameters(
      const std::string & namespace_,
      const std::map<std::string, ParameterT> & parameters);
    
    template<typename ParameterT>
    std::vector<ParameterT>
    rclcpp::Node::declare_parameters(
      const std::string & namespace_,
      const std::map<
        std::string,
        std::pair<ParameterT, rcl_interfaces::msg::ParameterDescriptor>
      > & parameters);
    
  • 取消声明参数并检查参数是否已声明的方法:

    void
    rclcpp::Node::undeclare_parameter(const std::string & name);
    
    bool
    rclcpp::Node::has_parameter(const std::string & name) const;
    
  • 一些以前不存在的便捷方法:

    rcl_interfaces::msg::SetParametersResult
    rclcpp::Node::set_parameter(const rclcpp::Parameter & parameter);
    
    std::vector<rclcpp::Parameter>
    rclcpp::Node::get_parameters(const std::vector<std::string> & names) const;
    
    rcl_interfaces::msg::ParameterDescriptor
    rclcpp::Node::describe_parameter(const std::string & name) const;
    
  • 一种设置回调的新方法,每当参数发生变化时就会调用该方法,让您有机会拒绝它:

    using OnParametersSetCallbackType =
      rclcpp::node_interfaces::NodeParametersInterface::OnParametersSetCallbackType;
    
    OnParametersSetCallbackType
    rclcpp::Node::set_on_parameters_set_callback(
      OnParametersSetCallbackType callback);
    

还有几种已弃用的方法:

template<typename ParameterT>
[[deprecated("use declare_parameter() instead")]]
void
rclcpp::Node::set_parameter_if_not_set(
  const std::string & name,
  const ParameterT & value);

template<typename ParameterT>
[[deprecated("use declare_parameters() instead")]]
void
rclcpp::Node::set_parameters_if_not_set(
  const std::string & name,
  const std::map<std::string, ParameterT> & values);

template<typename ParameterT>
[[deprecated("use declare_parameter() and it's return value instead")]]
void
rclcpp::Node::get_parameter_or_set(
  const std::string & name,
  ParameterT & value,
  const ParameterT & alternative_value);

template<typename CallbackT>
[[deprecated("use set_on_parameters_set_callback() instead")]]
void
rclcpp::Node::register_param_change_callback(CallbackT && callback);

内存策略

接口 rclcpp::memory_strategy::MemoryStrategy 在各种方法签名中使用 typedef WeakNodeVector

从 Dashing 开始,typedef 已更改为 WeakNodeList,并且各种方法中的参数类型也随之更改。

任何自定义内存策略都需要更新以匹配修改后的接口。

相关 API 更改可在 ros2/rclcpp#741 中找到。

rclcpp_components

在 Dashing 中实现组合的正确方法是利用 rclcpp_components 包。

必须对节点进行以下更改才能正确实现运行时组合:

Node 必须有一个接受的构造函数``rclcpp::NodeOptions``:

class Listener: public rclcpp::Node {
  Listener(const rclcpp::NodeOptions & options)
  : Node("listener", options)
  {
  }
};

C++ 注册宏(如果存在)需要更新以使用 rclcpp_components 等效项。 如果不存在,则必须在一个翻译单元中添加注册宏。

// Insert at bottom of translation unit, e.g. listener.cpp
#include "rclcpp_components/register_node_macro.hpp"
// Use fully-qualifed name in registration
RCLCPP_COMPONENTS_REGISTER_NODE(composition::Listener);

CMake 注册宏(如果存在)需要更新。 如果不存在,则必须将注册宏添加到项目的 CMake。

add_library(listener src/listener.cpp)
rclcpp_components_register_nodes(listener "composition::Listener")

有关组合的更多信息,请参阅`教程 <../Tutorials/Intermediate/Writing-a-Composable-Node>`

rclpy

创建发布者、订阅和 QoS 配置文件的更改

在 Dashing 之前,您可以选择在创建发布者或订阅时提供 QoSProfile 对象。

为了鼓励用户指定消息队列的历史深度,我们现在**要求**在创建发布者或订阅时提供深度值或 QoSProfile 对象。

要创建发布者,以前您需要编写:

node.create_publisher(Empty, 'chatter')
# Or using a keyword argument for QoSProfile
node.create_publisher(Empty, 'chatter', qos_profile=qos_profile_sensor_data)

在 Dashing 中,优先使用以下 API,它提供深度值或“QoSProfile”对象作为第三个位置参数:

# Assume a history setting of KEEP_LAST with depth 10
node.create_publisher(Empty, 'chatter', 10)
# Or pass a QoSProfile object directly
node.create_publisher(Empty, 'chatter', qos_profile_sensor_data)

同样,对于订阅,以前你会这样写:

node.create_subscription(BasicTypes, 'chatter', lambda msg: print(msg))
# Or using a keyword argument for QoSProfile
node.create_subscription(BasicTypes, 'chatter', lambda msg: print(msg), qos_profile=qos_profile_sensor_data)

在 Dashing 中:

# Assume a history setting of KEEP_LAST with depth 10
node.create_subscription(BasicTypes, 'chatter', lambda msg: print(msg), 10)
# Or pass a QoSProfile object directly
node.create_subscription(BasicTypes, 'chatter', lambda msg: print(msg), qos_profile_sensor_data)

为了简化过渡,不使用新 API 的用户将看到弃用警告。

此外,我们还要求在构造“QoSProfile”对象时设置历史策略和/或深度。

如果提供了“KEEP_LAST”的历史策略,则还需要深度参数。 例如,这些调用是有效的:

QoSProfile(history=QoSHistoryPolicy.RMW_QOS_POLICY_HISTORY_KEEP_ALL)
QoSProfile(history=QoSHistoryPolicy.RMW_QOS_POLICY_HISTORY_KEEP_LAST, depth=10)
QoSProfile(depth=10)  # equivalent to the previous line

这些调用将导致弃用警告:

QoSProfile()
QoSProfile(reliability=QoSReliabilityPolicy.RMW_QOS_POLICY_RELIABILITY_BEST_EFFORT)
# KEEP_LAST but no depth
QoSProfile(history=QoSHistoryPolicy.RMW_QOS_POLICY_HISTORY_KEEP_LAST)

有关更多详细信息,请参阅与引入此更改相关的问题和拉取请求:

由于声明参数更改而导致的更改

有关实际行为更改的详细信息,请参阅上面的`声明参数`_。这些更改类似于``rclcpp``中的更改。

这些是``rclpy.node.Node``接口中可用的新API方法:

  • 要声明给定名称、可选默认值(由``rcl_interfaces.msg.ParameterValue``支持)和可选描述符的参数,返回实际设置的值:

    def declare_parameter(
        name: str,
        value: Any = None,
        descriptor: ParameterDescriptor = ParameterDescriptor()
    ) -> Parameter
    
    def declare_parameters(
      namespace: str,
      parameters: List[Union[
          Tuple[str],
          Tuple[str, Any],
          Tuple[str, Any, ParameterDescriptor],
      ]]
    ) -> List[Parameter]
    
  • 取消声明先前声明的参数并检查参数是否已预先声明:

    def undeclare_parameter(name: str) -> None
    
    def has_parameter(name: str) -> bool
    
  • 获取和设置参数描述符:

    def describe_parameter(name: str) -> ParameterDescriptor
    
    def describe_parameters(names: List[str]) -> List[ParameterDescriptor]
    
    def set_descriptor(
        name: str,
        descriptor: ParameterDescriptor,
        alternative_value: Optional[ParameterValue] = None
    ) -> ParameterValue
    
  • 获取可能未声明的参数的便捷方法:

    def get_parameter_or(name: str, alternative_value: Optional[Parameter] = None) -> Parameter
    

其他变化

rclpy.parameter.Parameter 现在无需明确设置就可以猜测其类型(只要它是“rcl_interfaces.msg.ParameterValue”支持的类型之一)。例如,此代码:

p = Parameter('myparam', Parameter.Type.DOUBLE, 2.41)

相当于此代码:

p = Parameter('myparam', value=2.41)

此更改不会破坏现有的 API。

rosidl

直到 Crystal 出现之前,每个消息生成器包都使用 ament_cmake 扩展点 rosidl_generate_interfaces 注册自身,并传递一组 .msg / .srv / .action 文件。 从 Dashing 开始,消息生成管道基于 .idl 文件。

任何消息生成器包都需要更改并使用新的扩展点 rosidl_generate_idl_interfaces 注册自身,该扩展点仅传递 .idl 文件。 常用支持的语言 C、C++ 和 Python 的消息生成器以及用于自省、Fast RTPS、Connext 和 OpenSplice 的类型支持包已经更新(请参阅 ros2/rosidl#334)。 调用 rosidl_generate_interfaces() 的 CMake 代码可以直接传递 .idl 文件,也可以传递 .msg / .srv / .action,然后这些文件将在内部转换为 .idl 文件,然后再传递给每个消息生成器。

.msg / .srv / .action 文件的格式将来不会再发展。 .msg / .srv / .action 文件和 .idl 文件之间的映射在 本设计文章 <https://design.ros2.org/articles/legacy_interface_definition.html>`__ 中描述。 ``第二篇设计文章 <https://design.ros2.org/articles/idl_interface_definition.html>`__ 描述了 ``.idl 文件中支持的功能。 为了利用任何新功能,需要转换现有接口(例如,使用命令行工具“msg2idl”/“srv2idl”/“action2idl”)。

为了区分相同类型名称但具有不同命名空间,自省结构现在包含一个替换包名称的命名空间字段(请参阅“ros2/rosidl#335 <https://github.com/ros2/rosidl/pull/355/files>”)。

.msg 文件中 char 的映射

ROS 1 中,char 已弃用很长时间,并被映射到 uint8

在 ROS 2 中,直到 Crystal,char 被映射到单个字符(C/C++ 中为 char,Python 中长度为 1 的 str),以提供更自然的映射。

从 Dashing 开始,ROS 1 语义已恢复,并且 char 再次映射到 uint8

rosidl_generator_cpp

为消息、服务和操作生成的 C++ 数据结构为每个字段提供设置器方法。 直到 Crystal,每个设置器都返回指向数据的指针结构本身以启用命名参数习语。 从 Dashing 开始,这些 setter 改为“返回引用 <https://github.com/ros2/rosidl/pull/353>”__,因为这似乎是更常见的签名,并且它澄清了返回的值不能是“nullptr”。

rosidl_generator_py

直到 Crystal 之前,消息中的数组(固定大小)或序列(动态大小,可选具有上边界)字段在 Python 中存储为“列表”。 从 Dashing 开始,数值数组/序列的 Python 类型已发生改变:

  • 数值数组存储为 numpy.ndarray``(选择 ``dtype 以匹配数值类型)

  • 数值序列存储为 array.array``(选择 ``typename 以匹配数值类型)

与之前一样,非数值类型的数组/序列在 Python 中仍表示为 list

此更改带来了许多好处:

  • 新的数据结构确保数组/序列中的每个项目都符合数值类型的值范围限制。

  • 数值可以更有效地存储在内存中,从而避免每个项目的 Python 对象开销。

  • 两种数据结构的内存布局都允许在单个操作中读取和写入数组/序列的所有项目,这使得从 Python 到 Python 的转换速度明显更快/更高效。

launch

launch_testing 包赶上了 Bouncy Bolson 中对 launch 包的重新设计。 已移入 launch.legacy 子模块的旧版 Python API 因此已被弃用并删除。

有关如何使用其新 API 的参考,请参阅 launch 示例文档

有关如何使用新 launch_testing API 的参考,请参阅 demos 测试

rmw

Crystal Clemmys 发布以来的变化:

  • rmw 中的新 API,rmw_context_t 的 fini 函数:

  • 修改“rmw”,现在将“rmw_context_t”传递给“rmw_create_wait_set”:

  • rmw 中的新 API 用于为发布和订阅的消息预分配空间:

  • 修改“rmw”,现在分别将“rmw_publisher_allocation_t”或“rmw_subscription_allocation_t”传递给“rmw_publish”和“rmw_take”。

请注意,此参数可以是“NULL”或“nullptr”,以保留现有的 Crystal 行为。

  • rmw_get_*_names_and_types* 函数返回的类型名称应该具有完全限定的命名空间。

例如,返回的类型名称应该是 rcl_interface/msg/Parameterrcl_interfaces/srv/GetParameters,而不是 rcl_interfaces/Parameterrcl_interfaces/GetParameters

行动

  • rclcpp_action::Client 签名的更改:

rclcpp_action::Client::async_send_goal 的签名已更改。 现在,用户可以使用新的 SendGoalOptions 结构体,选择性地为**目标响应**和**结果**提供回调函数。 当操作服务器接受或拒绝目标时,将调用目标响应回调;当收到目标结果时,将调用结果回调。 可选回调也已添加到 rclcpp_action::Client::async_cancel_goalrclcpp_action::Client::async_get_result

  • 目标转换名称的更改:

目标状态转换的名称已重构以反映设计文档。 这会影响 rcl_actionrclcpp_actionrclpy。 以下是事件名称更改的列表(旧名称 -> 新名称):

  • GOAL_EVENT_CANCEL -> GOAL_EVENT_CANCEL_GOAL

  • GOAL_EVENT_SET_SUCCEEDED -> GOAL_EVENT_SUCCEED

  • GOAL_EVENT_SET_ABORTED -> GOAL_EVENT_ABORT

  • GOAL_EVENT_SET_CANCELED -> GOAL_EVENT_CANCELED

  • CancelGoal.srv 的更改:

CancelGoal 服务的响应消息中添加了 return_code 字段。 这是为了更好地传达服务调用失败的原因。 有关详细信息,请参阅 pull 请求 和相关问题。

rviz

  • 插件应使用完全限定的类型名称,否则将记录警告。

例如 <https://github.com/ros2/rviz/blob/dfceae319d49546f1e4ad39689853c18fef0001e/rviz_default_plugins/plugins_description.xml#L13>`_,使用类型 sensor_msgs/msg/Image 而不是 sensor_msgs/Image。 有关更多详细信息,请参阅 PR 介绍此更改

已知问题

  • [ros2/rclcpp#715] There is an inconsistency in the way that parameter YAML files are loaded between standalone ROS 2 nodes and composed ROS 2 nodes. Currently available workarounds are noted in an issue comment

  • [ros2/rclpy#360] rclpy nodes ignore ctrl-c when using OpenSplice on Windows.

  • [ros2/rosidl_typesupport_opensplice#30] There is a bug preventing nesting a message inside of a service or action definition with the same name when using OpenSplice.

  • [ros2/rclcpp#781] Calling get_parameter/list_parameter from within on_set_parameter_callback causes a deadlock on Dashing. This is fixed for Eloquent, but is an ABI break so has not been backported to Dashing.

  • [ros2/rclcpp#912] Inter-process communication forces a message copy when intra-process communication takes place between an std::unique_ptr publisher and a single std::unique_ptr subscription (published std::unique_ptr is internally being promoted to an std::shared_ptr).

  • [ros2/rosbag2#125] Topics with unreliable QOS are not recorded.

  • [ros2/rclcpp#715] Composable nodes cannot receive parameters via remapping. Supplying parameters to composable nodes can be accomplished using the methods described in [this comment].

  • [ros2/rclcpp#893] rclcpp::Context is not destroyed because of a reference cycle with rclcpp::GraphListener. This causes a memory leak. A fix has not been backported because of the risk of breaking ABI.

发布前的时间线

发布前的一些里程碑:

4 月 8 日星期一(alpha 版) 核心软件包的首批发布可用。 从现在开始可以进行测试(某些功能可能尚未实现)。

5 月 2 日星期四 核心软件包的 API 冻结

5 月 6 日星期一(beta 版) 核心软件包的更新版本可用。 最新功能的额外测试。

5 月 16 日星期四 功能冻结。 在此之后,只应发布错误修复版本。 新软件包可以独立发布。

5 月 20 日星期一(候选版本) 核心软件包的更新版本可用。

5 月 29 日星期三 冻结 rosdistro。 rosdistro 存储库上的 Dashing PR 将不会合并(发布公告后重新打开)。