Dashing Diademata (fringant)

Dashing Diademata est la quatrième version de ROS 2.

Plates-formes prises en charge

Dashing Diademata est principalement pris en charge sur les plates-formes suivantes :

Plateformes de niveau 1 :

  • Ubuntu 18.04 (Bionic) : amd64 et arm64

  • Mac macOS 10.12 (Sierra)

  • Windows 10 (Visual Studio 2019)

Plateformes de niveau 2 :

  • Ubuntu 18.04 (Bionic) : arm32

Plateformes de niveau 3 :

  • Debian Stretch (9) : amd64, arm64 et arm32

  • OpenEmbedded Thud (2.6) / webOS OSE : arm32 et x86

Pour plus d’informations sur les implémentations RMW, les versions du compilateur/interpréteur et les versions de dépendance du système, consultez `REP 2000 <https://www.ros.org/reps/rep-2000.html#dashing-diademata-may-2019-may-2021 >`__.

Nouvelles fonctionnalités de cette version de ROS 2

Quelques fonctionnalités et améliorations que nous aimerions souligner :

  • Components sont maintenant la méthode recommandée pour écrire votre nœud. Ils peuvent être utilisés de manière autonome ou composés au sein d’un processus et les deux méthodes sont entièrement prises en charge à partir des fichiers de lancement.

  • La communication intra-processus (C++ uniquement) a été améliorée - à la fois en termes de latence et de réduction des copies.

  • La bibliothèque cliente Python a été mise à jour pour correspondre à la plupart des équivalents C++ et certaines corrections de bogues et améliorations importantes ont été apportées concernant l’utilisation de la mémoire et les performances.

  • Les paramètres sont désormais une alternative complète à dynamic_reconfigure de ROS 1, y compris des contraintes telles que des plages ou étant en lecture seule.

  • En s’appuyant sur (un sous-ensemble de) IDL 4.2 pour le pipeline de génération de messages, il est désormais possible d’utiliser des fichiers .idl (à côté .msg / .srv / .action fichiers). Cette modification s’accompagne de la prise en charge de l’encodage UTF-8 facultatif pour les chaînes ordinaires ainsi que des chaînes multi-octets encodées en UTF-16 (voir wide strings design article __).

  • Outils de ligne de commande liés aux actions et composants.

  • Prise en charge des paramètres de qualité de service Date limite, Durée de vie et vivacité.

  • MoveIt 2 version alpha.

Veuillez consulter le Dashing meta ticket sur GitHub, qui contient plus d’informations ainsi que des références à des tickets spécifiques avec des détails supplémentaires.

Changements depuis la sortie de Crystal

Déclaration des paramètres

Il y a eu quelques changements dans le comportement des paramètres à partir de Dashing, qui ont également conduit à de nouvelles API et à la dépréciation d’autres API. Voir les sections rclcpp et rclpy ci-dessous pour plus d’informations sur les modifications de l’API.

Obtenir et définir des paramètres non déclarés

Depuis Dashing, les paramètres doivent désormais être déclarés avant d’être consultés ou définis.

Avant Dashing, vous pouviez appeler get_parameter(name) et obtenir soit une valeur, si elle avait été précédemment définie, soit un paramètre de type PARAMETER_NOT_SET. Vous pouvez également appeler set_parameter(name, value) à tout moment, même si le paramètre n’était pas défini auparavant.

Depuis Dashing, vous devez d’abord déclarer un paramètre avant de l’obtenir ou de le définir. Si vous essayez d’obtenir ou de définir un paramètre non déclaré, vous obtiendrez soit une exception levée, par ex. ParameterNotDeclaredException, ou dans certains cas, vous obtiendrez un résultat infructueux communiqué de différentes manières (voir les fonctions spécifiques pour plus de détails).

Cependant, vous pouvez obtenir l’ancien comportement (pour la plupart, voir la note dans le paragraphe suivant) en utilisant l’option allow_undeclared_parameters lors de la création de votre nœud. Vous voudrez peut-être le faire afin d’éviter les changements de code pour le moment, ou afin de répondre à certains cas d’utilisation peu courants. Par exemple, un « serveur de paramètres globaux » ou un « tableau noir de paramètres » peut vouloir autoriser les nœuds externes à définir de nouveaux paramètres sur lui-même sans les déclarer au préalable, il peut donc utiliser l’option allow_undeclared_parameters pour accomplir cela. Dans la plupart des cas, cependant, cette option n’est pas recommandée car elle rend le reste de l’API de paramètre moins sûr pour les bogues tels que les fautes de frappe de nom de paramètre et les erreurs logiques « utiliser avant de définir ».

Notez que l’utilisation de allow_undeclared_parameters vous permettra d’obtenir la plupart de l’ancien comportement spécifiquement pour les méthodes « get » et « set », mais cela ne rétablira pas tous les changements de comportement liés aux paramètres tels qu’ils étaient pour ROS Crystal. Pour cela, vous devez également définir l’option automatically_declare_parameters_from_overrides sur true, qui est décrite ci-dessous dans Configuration des paramètres à l’aide d’un fichier YAML .

Déclarer un paramètre avec un ParameterDescriptor

Un autre avantage de déclarer vos paramètres avant de les utiliser est que cela vous permet de déclarer un descripteur de paramètre en même temps.

Désormais, lors de la déclaration d’un paramètre, vous pouvez inclure un ParameterDescriptor personnalisé ainsi qu’un nom et une valeur par défaut. Le ParameterDescriptor est défini comme un message dans rcl_interfaces/msg/ParameterDescriptor et contient des métadonnées comme description et des contraintes comme read_only ou integer_range. Ces contraintes peuvent être utilisées pour rejeter les valeurs non valides lors de la définition des paramètres et/ou comme conseils aux outils externes sur les valeurs valides pour un paramètre donné. La contrainte read_only empêchera la valeur du paramètre de changer après avoir été déclarée, ainsi que si elle n’est pas déclarée.

Pour référence, voici un lien vers le message ParameterDescriptor au moment de la rédaction de ceci :

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

Configuration des paramètres à l’aide d’un fichier YAML

Depuis Dashing, les paramètres d’un fichier de configuration YAML, par ex. transmis au nœud via l’argument de ligne de commande __params:=, ne sont utilisés que pour remplacer la valeur par défaut d’un paramètre lors de la déclaration du paramètre.

Avant Dashing, tous les paramètres que vous passiez via un fichier YAML étaient implicitement définis sur le nœud.

Depuis Dashing, ce n’est plus le cas, car les paramètres doivent être déclarés pour apparaître sur le nœud aux observateurs externes, comme ros2 param list.

L’ancien comportement peut être obtenu en utilisant l’option automatically_declare_parameters_from_overrides lors de la création d’un nœud. Cette option, si elle est définie sur true, déclarera automatiquement tous les paramètres dans le fichier YAML d’entrée lors de la construction du nœud. Cela peut être utilisé pour éviter des changements majeurs à votre code existant ou pour servir des cas d’utilisation spécifiques. Par exemple, un « serveur de paramètres globaux » peut souhaiter recevoir des paramètres arbitraires au lancement, qu’il n’aurait pas pu déclarer à l’avance. La plupart du temps, cependant, cette option n’est pas recommandée, car elle peut conduire à définir un paramètre dans un fichier YAML en supposant que le nœud l’utilisera, même si le nœud ne l’utilise pas réellement.

À l’avenir, nous espérons avoir un vérificateur qui vous avertira si vous passez un paramètre à un nœud qu’il n’attendait pas.

Les paramètres du fichier YAML continueront d’influencer la valeur des paramètres lors de leur première déclaration.

current_cmake

La fonction CMake ament_index_has_resource renvoyait soit TRUE ou FALSE. À partir de cette version, il renvoie soit le chemin du préfixe au cas où la ressource a été trouvée, soit FALSE.

Si vous utilisez la valeur de retour dans une condition CMake comme celle-ci :

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

vous devez mettre à jour la condition pour vous assurer qu’elle considère une valeur de chaîne comme TRUE :

if(var)

RCLCP

Changement de comportement pour Node::get_node_names()

La fonction NodeGraph::get_node_names(), et donc aussi Node::get_node_names(), renvoie désormais un std::vector<std::string> contenant des noms de nœuds complets avec leurs espaces de noms inclus, au lieu de simplement les noms de nœuds.

Modification de la manière dont les options sont transmises aux nœuds

Les arguments étendus (au-delà du nom et de l’espace de noms) du constructeur rclcpp::Node() ont été remplacés par une structure rclcpp::NodeOptions. Voir ros2/rclcpp#622 pour plus de détails sur la structure et les valeurs par défaut des options.

Si vous utilisez l’un des arguments étendus de rclcpp::Node() comme ceci :

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);

Vous devez mettre à jour pour utiliser la structure 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);

Modifications apportées à la création d’éditeurs et d’abonnements

Il y a eu quelques changements dans la création d’éditeurs et d’abonnements qui sont nouveaux dans Dashing :

  • Les paramètres QoS sont maintenant passés à l’aide de la nouvelle classe rclcpp::QoS, et l’API encourage l’utilisateur à spécifier au moins la profondeur de l’historique.

  • Les options sont maintenant passées en tant qu’objet, c’est-à-dire rclcpp::PublisherOptions et rclcpp::SubscriptionOptions.

Toutes les modifications sont rétrocompatibles (aucune modification de code n’est requise), mais plusieurs styles d’appel existants sont obsolètes. Les utilisateurs sont encouragés à mettre à jour les nouvelles signatures.


Dans le passé, lors de la création d’un éditeur ou d’un abonnement, vous pouviez soit ne spécifier aucun paramètre QoS (par exemple, fournir simplement le nom du sujet pour un éditeur), soit spécifier une structure de données de « profil qos » (de type rmw_qos_profile_t) avec tous les paramètres déjà définis. Vous devez maintenant utiliser le nouvel objet rclcpp::QoS pour spécifier votre QoS et au moins les paramètres d’historique de votre QoS. Cela encourage l’utilisateur à spécifier une profondeur d’historique lors de l’utilisation de KEEP_LAST, plutôt que de lui attribuer par défaut une valeur qui peut ou non être appropriée.

Dans ROS 1, cela s’appelait queue_size et était requis à la fois en C++ et en Python. Nous modifions l’API ROS 2 pour rétablir cette exigence.


De plus, toutes les options qui pouvaient auparavant être passées lors de la création d’un éditeur ou d’un abonnement ont maintenant été encapsulées dans une classe rclcpp::PublisherOptions et rclcpp::SubscriptionOptions respectivement. Cela permet des signatures plus courtes, une utilisation plus pratique et l’ajout de nouvelles options futures sans casser l’API.


Certaines signatures pour la création d’éditeurs et d’abonnés sont désormais obsolètes, et de nouvelles signatures ont été ajoutées pour vous permettre d’utiliser les nouvelles classes d’options rclcpp::QoS et éditeur/abonnement.

Voici les nouvelles API recommandées :

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);

Et ce sont ceux qui sont obsolètes :

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);

La modification de la façon dont la qualité de service est transmise est très susceptible d’avoir un impact sur les utilisateurs.

Un changement typique pour un éditeur ressemble à ceci :

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

Et pour un abonnement :

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

Si vous n’avez aucune idée de la profondeur à utiliser et que vous ne vous en souciez pas pour le moment (peut-être juste pour le prototypage), nous vous recommandons d’utiliser 10, car c’était la valeur par défaut auparavant et devrait préserver le comportement existant.

Une documentation plus détaillée sur la façon de sélectionner une profondeur appropriée est à venir.

Voici un exemple d’un changement légèrement plus complexe pour éviter les API nouvellement obsolètes :

- // 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());

Consultez la demande d’extraction (et les demandes d’extraction connectées) qui ont introduit le changement de QoS pour plus d’exemples et de détails :

Modifications dues à la déclaration de modification de paramètre

Pour plus de détails sur le changement de comportement réel, voir Déclaration des paramètres ci-dessus.

Il y a plusieurs nouveaux appels d’API dans l’interface rclcpp::Node :

  • Méthodes qui déclarent des paramètres avec un nom, une valeur par défaut facultative, un descripteur facultatif et renvoient la valeur réellement définie :

    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);
    
  • Une méthode pour annuler la déclaration des paramètres et vérifier si un paramètre a été déclaré :

    void
    rclcpp::Node::undeclare_parameter(const std::string & name);
    
    bool
    rclcpp::Node::has_parameter(const std::string & name) const;
    
  • Quelques méthodes de commodité qui n’existaient pas auparavant :

    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;
    
  • Une nouvelle méthode pour définir le rappel qui est appelé à chaque fois qu’un paramètre sera modifié, vous donnant la possibilité de le rejeter :

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

Il y avait aussi plusieurs méthodes obsolètes :

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);

Stratégie de mémoire

L’interface rclcpp::memory_strategy::MemoryStrategy utilisait le typedef WeakNodeVector dans diverses signatures de méthode. Depuis Dashing, le typedef a été changé en WeakNodeList et avec lui le type du paramètre dans diverses méthodes. Toute stratégie de mémoire personnalisée doit être mise à jour pour correspondre à l’interface modifiée.

Le changement d’API pertinent peut être trouvé dans ros2/rclcpp#741.

rclcpp_components

La bonne façon d’implémenter la composition dans Dashing est d’utiliser le package rclcpp_components.

Les modifications suivantes doivent être apportées aux nœuds afin d’implémenter correctement la composition d’exécution :

Le Node doit avoir un constructeur qui prend rclcpp::NodeOptions :

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

Les macros d’enregistrement C++ (si présentes) doivent être mises à jour pour utiliser l’équivalent rclcpp_components. Si elles ne sont pas présentes, les macros d’enregistrement doivent être ajoutées dans une unité de traduction.

// 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);

Les macros d’enregistrement CMake (le cas échéant) doivent être mises à jour. Si elles ne sont pas présentes, les macros d’enregistrement doivent être ajoutées au CMake du projet.

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

Pour plus d’informations sur la composition, consultez le tutoriel

rclpy

Modifications apportées à la création d’éditeurs, d’abonnements et de profils QoS

Avant Dashing, vous pouviez éventuellement fournir un objet QoSProfile lors de la création d’un éditeur ou d’un abonnement. Afin d’encourager les utilisateurs à spécifier une profondeur d’historique pour les files d’attente de messages, nous exigeons désormais qu’une valeur de profondeur ou un objet QoSProfile soit donné lors de la création d’éditeurs ou d’abonnements.

Pour créer un éditeur, auparavant vous auriez écrit :

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

Dans Dashing, préférez l’API suivante qui fournit une valeur de profondeur ou un objet QoSProfile comme troisième argument positionnel :

# 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)

De même pour les abonnements, auparavant vous auriez écrit :

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)

En Fringant :

# 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)

Pour faciliter la transition, les utilisateurs qui n’utilisent pas la nouvelle API verront des avertissements d’obsolescence.

De plus, nous exigeons également que lors de la construction des objets QoSProfile, une politique d’historique et/ou une profondeur soient définies. Si une politique d’historique de KEEP_LAST est fournie, un argument de profondeur est également requis. Par exemple, ces appels sont valides :

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

Et ces appels provoqueront un avertissement d’obsolescence :

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

Consultez le problème et la demande d’extraction liés à l’introduction de ce changement pour plus de détails :

Modifications dues à la déclaration de modification de paramètre

Pour plus de détails sur le changement de comportement réel, voir Déclaration des paramètres ci-dessus. Les changements sont analogues à ceux de rclcpp.

Voici les nouvelles méthodes API disponibles dans l’interface rclpy.node.Node :

  • Pour déclarer des paramètres donnés un nom, une valeur par défaut optionnelle (supportée par rcl_interfaces.msg.ParameterValue) et un descripteur optionnel, renvoyant la valeur réellement définie :

    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]
    
  • Pour annuler la déclaration de paramètres précédemment déclarés et vérifier si un paramètre a été déclaré au préalable :

    def undeclare_parameter(name: str) -> None
    
    def has_parameter(name: str) -> bool
    
  • Pour obtenir et définir des descripteurs de paramètres :

    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
    
  • Une méthode pratique pour obtenir des paramètres qui n’ont peut-être pas été déclarés :

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

Autres changements

rclpy.parameter.Parameter peut maintenant deviner son type sans le définir explicitement (tant qu’il est l’un de ceux pris en charge par rcl_interfaces.msg.ParameterValue). Par exemple, ce code :

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

Est équivalent à ce code :

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

Cette modification n’interrompt pas l’API existante.

rose

Jusqu’à Crystal, chaque package générateur de messages s’enregistrait en utilisant le point d’extension ament_cmake rosidl_generate_interfaces et recevait un ensemble de fichiers .msg / .srv / .action. Depuis Dashing, le pipeline de génération de messages est basé sur les fichiers .idl à la place.

Tout paquet de générateur de message doit changer et s’enregistrer en utilisant le nouveau point d’extension rosidl_generate_idl_interfaces qui ne transmet que les fichiers .idl à la place. Les générateurs de messages pour les langages couramment pris en charge C, C++ et Python ainsi que les packages de support de type pour l’introspection, Fast RTPS, Connext et OpenSplice ont déjà été mis à jour (voir ros2/rosidl#334). Le code CMake appelant rosidl_generate_interfaces() peut soit passer directement les fichiers .idl, soit passer .msg / .srv / .action qui sera ensuite converti en interne dans les fichiers .idl avant d’être transmis à chaque générateur de messages.

Le format des fichiers .msg / .srv / .action n’évoluera pas à l’avenir. Le mappage entre les fichiers .msg / .srv / .action et les fichiers .idl est décrit dans cet article de conception. Un deuxième article de conception décrit les fonctionnalités prises en charge dans les fichiers .idl. Afin de tirer parti des nouvelles fonctionnalités, les interfaces existantes doivent être converties (par exemple, en utilisant les outils de ligne de commande msg2idl / srv2idl / action2idl).

Pour distinguer les mêmes noms de type, mais avec des espaces de noms différents, les structures d’introspection contiennent désormais un champ d’espace de noms qui remplace le nom du package (voir `ros2/rosidl#335 <https://github.com/ros2/rosidl/pull/355/files >`_).

Mappage de caractères dans les fichiers .msg

Dans ROS 1 char est obsolète depuis longtemps et est mappé sur uint8. Dans ROS 2 jusqu’à Crystal, char était mappé sur un seul caractère (char en C / C++, str de longueur 1 en Python) dans le but de fournir un mappage plus naturel. Depuis Dashing, la sémantique ROS 1 a été restaurée et char est à nouveau mappé sur uint8.

rosidl_generator_cpp

Les structures de données C++ générées pour les messages, les services et les actions fournissent des méthodes de définition pour chaque champ. Jusqu’à Crystal, chaque setter renvoyait un pointeur vers la structure de données elle-même pour activer l’idiome du paramètre nommé. À partir de Dashing, ces setters renvoyent une référence à la place, car cela semble être la signature la plus courante et précise que la valeur renvoyée ne peut pas être un nullptr.

rosidl_generator_py

Jusqu’à Crystal, un tableau (taille fixe) ou un champ de séquence (taille dynamique, éventuellement avec une limite supérieure) dans un message était stocké sous forme de liste en Python. Depuis Dashing, le type Python pour les tableaux/séquences de valeurs numériques a été modifié :

  • un tableau de valeurs numériques est stocké sous la forme d’un numpy.ndarray (le dtype est choisi pour correspondre au type de la valeur numérique)

  • une séquence de valeurs numériques est stockée sous la forme d’un array.array (le typename est choisi pour correspondre au type de la valeur numérique)

Comme auparavant, un tableau/séquence de types non numériques est toujours représenté sous la forme d’une liste en Python.

Ce changement apporte plusieurs avantages :

  • Les nouvelles structures de données garantissent que chaque élément du tableau/séquence est conforme aux restrictions de plage de valeurs du type numérique.

  • Les valeurs numériques peuvent être stockées plus efficacement en mémoire, ce qui évite la surcharge d’objets Python pour chaque élément.

  • La disposition de la mémoire des deux structures de données permet de lire et d’écrire tous les éléments du tableau/de la séquence en une seule opération, ce qui rend la conversion de et vers Python beaucoup plus rapide/plus efficace.

lancement

Le paquet launch_testing a rattrapé la refonte du paquet launch faite dans Bouncy Bolson. L’ancienne API Python, déjà déplacée dans le sous-module launch.legacy, a donc été dépréciée et supprimée.

Voir launch exemples et documentation pour référence sur la façon d’utiliser sa nouvelle API.

Voir demos tests pour savoir comment utiliser la nouvelle API launch_testing.

rmw

Changements depuis la version Crystal Clemmys :

  • Nouvelle API dans rmw, une fonction fini pour rmw_context_t :

  • Modification de rmw, passe maintenant rmw_context_t à rmw_create_wait_set :

  • Nouvelles API dans rmw pour préallouer de l’espace pour les messages publiés et abonnés :

  • Modification de rmw, passe maintenant rmw_publisher_allocation_t ou rmw_subscription_allocation_t à rmw_publish et rmw_take, respectivement. Notez que cet argument peut être NULL ou nullptr, ce qui conserve le comportement existant de Crystal.

  • Les noms de type renvoyés par les fonctions rmw_get_*_names_and_types* doivent avoir un espace de noms complet. Par exemple, au lieu de rcl_interfaces/Parameter et rcl_interfaces/GetParameters, les noms de type retournés devraient être rcl_interface/msg/Parameter et rcl_interfaces/srv/GetParameters.

Actions

  • Modifications apportées aux signatures rclcpp_action::Client :

    La signature de rclcpp_action::Client::async_send_goal a changé. Désormais, les utilisateurs peuvent éventuellement fournir des fonctions de rappel pour la réponse de l’objectif et le résultat à l’aide des nouvelles SendGoalOptions structure. Le rappel de réponse d’objectif est appelé lorsqu’un serveur d’action accepte ou rejette l’objectif et le rappel de résultat est appelé lorsque le résultat de l’objectif est reçu. Des rappels facultatifs ont également été ajoutés à `rclcpp_action::Client::async_cancel_goal <https://github.com/ros2/rclcpp/blob/ef41059a751702274667e2164182c062b47c453d/rclcpp_action/include/rclcpp_action/client.hpp#L432-L434>`clpp_action/client.hpp#L432-L434>`_ et r ::Client::async_get_result.

  • Modifications apportées aux noms de transition d’objectif :

    Les noms des transitions d’état d’objectif ont été refactorisés pour refléter la documentation de conception. Cela affecte rcl_action, rclcpp_action et rclpy. Voici une liste des changements de nom d’événement (Ancien nom -> Nouveau nom) :

    • GOAL_EVENT_CANCEL -> GOAL_EVENT_CANCEL_GOAL

    • OBJECTIF_EVENT_SET_SUCCEED -> OBJECTIF_EVENT_SUCCEED

    • GOAL_EVENT_SET_ABORTED -> GOAL_EVENT_ABORT

    • GOAL_EVENT_SET_CANCELED -> GOAL_EVENT_CANCELED

  • Modifications apportées à CancelGoal.srv :

    Un champ return_code a été ajouté au message de réponse du service CancelGoal. Il s’agit de mieux communiquer la raison d’un appel de service ayant échoué. Voir la demande d’extraction et le problème connexe pour plus de détails.

voir

  • Les plugins doivent utiliser des noms de type complets, sinon un avertissement sera enregistré. Par exemple, utilisez le type sensor_msgs/msg/Image au lieu de ``sensor_msgs/Image ``. Voir PR présentant ce changement pour plus de détails.

Problèmes connus

  • [ros2/rclcpp#715] Il existe une incohérence dans la manière dont les fichiers YAML de paramètres sont chargés entre les nœuds ROS 2 autonomes et les nœuds ROS 2 composés . Les solutions de contournement actuellement disponibles sont notées dans un commentaire de problème

  • [ros2/rclpy#360] les nœuds rclpy ignorent ctrl-c lors de l’utilisation d’OpenSplice sous Windows.

  • [ros2/rosidl_typesupport_opensplice#30] Un bogue empêche l’imbrication d’un message dans une définition de service ou d’action portant le même nom lors de l’utilisation d’OpenSplice.

  • [ros2/rclcpp#781] Appeler get_parameter/list_parameter depuis on_set_parameter_callback provoque un blocage sur Fringant. Ceci est corrigé pour Eloquent, mais il s’agit d’une rupture ABI et n’a donc pas été rétroporté vers Dashing.

  • [ros2/rclcpp#912] La communication inter-processus force une copie de message lorsqu’une communication intra-processus a lieu entre un std::unique_ptr `` éditeur et un seul abonnement ``std::unique_ptr (le std::unique_ptr publié est promu en interne vers un std::shared_ptr).

  • [ros2/rosbag2#125] Les sujets avec un QOS non fiable ne sont pas enregistrés.

  • [ros2/rclcpp#715] Les nœuds composables ne peuvent pas recevoir de paramètres via le remappage. La fourniture de paramètres aux nœuds composables peut être effectuée à l’aide des méthodes décrites dans [ce commentaire].

  • [ros2/rclcpp#893] rclcpp::Context n’est pas détruit à cause d’un cycle de référence avec ``rclcpp::GraphListener ``. Cela provoque une fuite de mémoire. Un correctif n’a pas été rétroporté en raison du risque de casser l’ABI.

Chronologie avant la sortie

Quelques étapes menant à la sortie :

Mon. Apr 8th (alpha)

Premières versions des packages de base disponibles. Les tests peuvent avoir lieu à partir de maintenant (certaines fonctionnalités n’ont peut-être pas encore été ajoutées).

avec. peut et

Gel de l’API pour les packages de base

Lun. 6 mai (bêta)

Versions mises à jour des packages de base disponibles. Tests supplémentaires des dernières fonctionnalités.

Jeu. 16 mai

Gel des fonctionnalités. Seules les versions de correctifs de bogues doivent être effectuées après ce point. De nouveaux packages peuvent être publiés indépendamment.

Lun. 20 mai (release candidate)

Versions mises à jour des packages de base disponibles.

Épouser. 29 mai

Geler rosdistro. Aucun PR pour Dashing sur le repo rosdistro ne sera fusionné (réouverture après l’annonce de la sortie).