- Principes des nœuds dans ROS 2
Dans ROS 2, un nœud constitue l'unité d'exécution fondamentale, responsable d'une fonction distincte au sein d'un système robotique. Cette conception modulaire améliore la flexibilité et facilite la maintenance, permetttant une composition similaire à des blocs assemblables.
La communication entre nœuds s'effectue via divers mécanismes : les topics pour le flux de données continu, les services pour les interactions ponctuelles de type requête-réponse, les actions pour les tâches longues avec suivi, et les paramètres pour la configuration dynamique. Cette polyvalence répond aux besoins complexes des applications robotiques.
- Configuration de l'environnement et de l'espace de travail
Commencez par installer ROS 2 sur un système compatible, tel qu'Ubuntu 22.04 LTS. Initialisez ensuite un espace de travail dédié avec les étapes suivantes :
mkdir -p ~/dev_ws/src
cd ~/dev_ws
colcon build --symlink-install
source install/local_setup.bash
L'option --symlink-install accélère le développement en évitant des recompilations après chaque modification. Pour un accès permanent, ajoutez les lignes suivantes à votre fichier .bashrc :
echo "source /opt/ros/humble/setup.bash" >> ~/.bashrc
echo "source ~/dev_ws/install/local_setup.bash" >> ~/.bashrc
- Implémentation d'un nœud avec cycle de vie
Créez un paquet pour héberger votre nœud, en spécifiant les dépendances requises :
cd ~/dev_ws/src
ros2 pkg create --build-type ament_cmake lifecycle_publisher --dependencies rclcpp_lifecycle
Dans le fichier source, dévelopez un nœud intégrant la gestion du cycle de vie. Voici un exemple fonctionnel :
#include "rclcpp_lifecycle/lifecycle_node.hpp"
#include "std_msgs/msg/string.hpp"
#include <chrono>
using namespace std::chrono_literals;
class CyclePublisherNode : public rclcpp_lifecycle::LifecycleNode
{
public:
CyclePublisherNode()
: rclcpp_lifecycle::LifecycleNode("cycle_publisher"), message_count_(0)
{
RCLCPP_INFO(get_logger(), "Nœud initialisé en état non configuré");
}
protected:
rclcpp_lifecycle::node_interfaces::LifecycleNodeInterface::CallbackReturn on_configure(const rclcpp_lifecycle::State &)
{
publisher_ = create_publisher<std_msgs::msg::String>("status_data", 10);
timer_ = create_wall_timer(500ms, std::bind(&CyclePublisherNode::send_message, this));
RCLCPP_INFO(get_logger(), "Configuration terminée, publication prête");
return rclcpp_lifecycle::node_interfaces::LifecycleNodeInterface::CallbackReturn::SUCCESS;
}
rclcpp_lifecycle::node_interfaces::LifecycleNodeInterface::CallbackReturn on_activate(const rclcpp_lifecycle::State &)
{
RCLCPP_INFO(get_logger(), "Activation du nœud, diffusion en cours");
return rclcpp_lifecycle::node_interfaces::LifecycleNodeInterface::CallbackReturn::SUCCESS;
}
rclcpp_lifecycle::node_interfaces::LifecycleNodeInterface::CallbackReturn on_deactivate(const rclcpp_lifecycle::State &)
{
RCLCPP_INFO(get_logger(), "Désactivation du nœud, diffusion interrompue");
return rclcpp_lifecycle::node_interfaces::LifecycleNodeInterface::CallbackReturn::SUCCESS;
}
rclcpp_lifecycle::node_interfaces::LifecycleNodeInterface::CallbackReturn on_cleanup(const rclcpp_lifecycle::State &)
{
publisher_.reset();
timer_.reset();
RCLCPP_INFO(get_logger(), "Ressources libérées lors du nettoyage");
return rclcpp_lifecycle::node_interfaces::LifecycleNodeInterface::CallbackReturn::SUCCESS;
}
rclcpp_lifecycle::node_interfaces::LifecycleNodeInterface::CallbackReturn on_shutdown(const rclcpp_lifecycle::State &)
{
RCLCPP_INFO(get_logger(), "Arrêt final du nœud");
return rclcpp_lifecycle::node_interfaces::LifecycleNodeInterface::CallbackReturn::SUCCESS;
}
private:
void send_message()
{
auto output_msg = std_msgs::msg::String();
output_msg.data = "Signal n°" + std::to_string(message_count_++);
publisher_->publish(output_msg);
RCLCPP_INFO(get_logger(), "Envoyé: '%s'", output_msg.data.c_str());
}
rclcpp_lifecycle::LifecyclePublisher<std_msgs::msg::String>::SharedPtr publisher_;
rclcpp::TimerBase::SharedPtr timer_;
size_t message_count_;
};
int main(int argc, char * argv[])
{
rclcpp::init(argc, argv);
auto node = std::make_shared<CyclePublisherNode>();
rclcpp::spin(node->get_node_base_interface());
rclcpp::shutdown();
return 0;
}
Ce code démontre un nœud avec des transitions de cycle de vie contrôlables, permettant une gestion fine des ressources et du comportement via les outils ROS 2 dédiés.