En bref
- Installez ROS 2 Jazzy sur Ubuntu 24.04 avec
sudo apt install ros-jazzy-desktop - Concepts clés : nœuds (processus), topics (pub/sub), services (RPC), actions (tâches longues)
- Écrivez un éditeur/abonné Python/C++ en 5 minutes
- Utilisez
ros2 launchpour l'orchestration multi-nœuds - Déboguez avec
rqt,ros2 bagetrviz2
1. Installation de ROS 2 (Jazzy) sur Ubuntu
Prérequis
- Ubuntu 24.04 (Noble Numbat) Exigences de ROS 2 Jazzy
- Système 64 bits
- 20 Go+ d'espace disque (pour une installation complète du bureau)
Étape 1 : Configuration de la locale et des dépôts
sudo apt update && sudo apt install locales
sudo locale-gen en_US en_US.UTF-8
sudo update-locale LC_ALL=en_US.UTF-8 LANG=en_US.UTF-8
export LANG=en_US.UTF-8
sudo apt install software-properties-common
sudo add-apt-repository universe
Étape 2 : Ajout du dépôt ROS 2
sudo apt update && sudo apt install curl -y
curl -sSL https://raw.githubusercontent.com/ros/rosdistro/master/ros.key -o /usr/share/keyrings/ros-archive-keyring.gpg
echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/ros-archive-keyring.gpg] http://packages.ros.org/ros2/ubuntu $(. /etc/os-release && echo $UBUNTU_CODENAME) main" | sudo tee /etc/apt/sources.list.d/ros2.list > /dev/null
sudo apt update
Étape 3 : Installation de ROS 2 Jazzy
# Installation bureau (recommandée) : ROS, RViz, démos, tutoriels
sudo apt install ros-jazzy-desktop
# Installation de base (minimale) : uniquement ROS et outils en ligne de commande
# sudo apt install ros-jazzy-ros-base
# Outils de développement (optionnels)
sudo apt install ros-dev-tools
Étape 4 : Configuration de l'environnement
# Source du fichier de configuration ROS 2 (ajoutez à ~/.bashrc pour la persistance)
source /opt/ros/jazzy/setup.bash
# Vérification de l'installation
ros2 --version
# Sortie attendue : ros2 version 26.0.0 (ou supérieure)
Points d'attention :
- Si
ros2 --versionéchoue, assurez-vous que/opt/ros/jazzy/setup.bashest sourcé. - Pour les paquets Python, installez
python3-colcon-common-extensionss'il est manquant.
2. Nœuds, Topics, Services et Actions
Concepts clés
| Concept | Description | Correspondance dans la pile IA physique |
|---|---|---|
| Nœud | Un processus effectuant des calculs (ex. : pilote de capteur, planificateur). | CALCUL |
| Topic | Communication asynchrone pub/sub (ex. : /scan pour les données LiDAR). | CONNEXION |
| Service | Requête/réponse synchrone (ex. : /reset_pose pour la localisation). | RAISONNEMENT |
| Action | Tâche longue avec retour d'information (ex. : /navigate_to_pose pour la navigation). | ACTION |
Commandes CLI
# Lister les nœuds
ros2 node list
# Lister les topics
ros2 topic list
# Écouter un topic
ros2 topic echo /scan
# Appeler un service
ros2 service call /reset_pose std_srvs/srv/Empty
# Lister les actions
ros2 action list
3. Écrire votre premier éditeur/abonné
Exemple en Python
Éditeur (publisher.py)
#!/usr/bin/env python3
import rclpy
from rclpy.node import Node
from std_msgs.msg import String
class MinimalPublisher(Node):
def __init__(self):
super().__init__('minimal_publisher')
self.publisher_ = self.create_publisher(String, 'topic', 10)
timer_period = 0.5 # secondes
self.timer = self.create_timer(timer_period, self.timer_callback)
self.i = 0
def timer_callback(self):
msg = String()
msg.data = f'Hello ROS 2: {self.i}'
self.publisher_.publish(msg)
self.get_logger().info(f'Publication : "{msg.data}"')
self.i += 1
def main(args=None):
rclpy.init(args=args)
minimal_publisher = MinimalPublisher()
rclpy.spin(minimal_publisher)
minimal_publisher.destroy_node()
rclpy.shutdown()
if __name__ == '__main__':
main()
Abonné (subscriber.py)
#!/usr/bin/env python3
import rclpy
from rclpy.node import Node
from std_msgs.msg import String
class MinimalSubscriber(Node):
def __init__(self):
super().__init__('minimal_subscriber')
self.subscription = self.create_subscription(
String,
'topic',
self.listener_callback,
10)
self.subscription # éviter l'avertissement de variable inutilisée
def listener_callback(self, msg):
self.get_logger().info(f'J’ai entendu : "{msg.data}"')
def main(args=None):
rclpy.init(args=args)
minimal_subscriber = MinimalSubscriber()
rclpy.spin(minimal_subscriber)
minimal_subscriber.destroy_node()
rclpy.shutdown()
if __name__ == '__main__':
main()
Exécution de l'exemple
# Terminal 1 : Exécuter l'éditeur
python3 publisher.py
# Terminal 2 : Exécuter l'abonné
python3 subscriber.py
# Sortie attendue (Terminal 2) :
# [INFO] [minimal_subscriber]: J’ai entendu : "Hello ROS 2: 0"
# [INFO] [minimal_subscriber]: J’ai entendu : "Hello ROS 2: 1"
Exemple en C++
Éditeur (publisher.cpp)
#include <chrono>
#include <memory>
#include "rclcpp/rclcpp.hpp"
#include "std_msgs/msg/string.hpp"
using namespace std::chrono_literals;
class MinimalPublisher : public rclcpp::Node {
public:
MinimalPublisher() : Node("minimal_publisher"), count_(0) {
publisher_ = this->create_publisher<std_msgs::msg::String>("topic", 10);
timer_ = this->create_wall_timer(
500ms, std::bind(&MinimalPublisher::timer_callback, this));
}
private:
void timer_callback() {
auto message = std_msgs::msg::String();
message.data = "Hello ROS 2: " + std::to_string(count_++);
RCLCPP_INFO(this->get_logger(), "Publication : '%s'", message.data.c_str());
publisher_->publish(message);
}
rclcpp::TimerBase::SharedPtr timer_;
rclcpp::Publisher<std_msgs::msg::String>::SharedPtr publisher_;
size_t count_;
};
int main(int argc, char * argv[]) {
rclcpp::init(argc, argv);
rclcpp::spin(std::make_shared<MinimalPublisher>());
rclcpp::shutdown();
return 0;
}
Compilation et exécution
# Créer un espace de travail
mkdir -p ~/ros2_ws/src
cd ~/ros2_ws/src
ros2 pkg create --build-type ament_cmake cpp_pubsub
# Remplacer le fichier généré src/cpp_pubsub/src/publisher_member_function.cpp par le code ci-dessus
# Compiler
cd ~/ros2_ws
colcon build --packages-select cpp_pubsub
# Sourcer l'espace de travail
source install/setup.bash
# Exécuter l'éditeur
ros2 run cpp_pubsub talker
4. Fichiers de lancement et paramètres
Exemple de fichier de lancement (launch_example.py)
from launch import LaunchDescription
from launch_ros.actions import Node
def generate_launch_description():
return LaunchDescription([
Node(
package='cpp_pubsub',
executable='talker',
name='talker_node',
parameters=[{'use_sim_time': True}]
),
Node(
package='demo_nodes_py',
executable='listener',
name='listener_node'
)
])
Exécution du fichier de lancement
ros2 launch launch_example.py
Paramètres
# Lister les paramètres
ros2 param list
# Obtenir un paramètre
ros2 param get /talker_node use_sim_time
# Définir un paramètre
ros2 param set /talker_node use_sim_time false
5. DDS, QoS et considérations temps réel
Profils QoS
ROS 2 utilise des politiques de Quality of Service (QoS) pour configurer la fiabilité, la durabilité et la latence des communications.
| Politique | Options | Cas d'usage |
|---|---|---|
| Fiabilité | RELIABLE, BEST_EFFORT | Données de capteur (BEST_EFFORT), commandes (RELIABLE) |
| Durabilité | VOLATILE, TRANSIENT_LOCAL | Données de carte (TRANSIENT_LOCAL), télémétrie (VOLATILE) |
| Historique | KEEP_LAST(n), KEEP_ALL | Tampon limité (KEEP_LAST), rejeu complet (KEEP_ALL) |
Exemple : Configuration de QoS en Python
from rclpy.qos import QoSProfile, ReliabilityPolicy, HistoryPolicy
qos_profile = QoSProfile(
reliability=ReliabilityPolicy.RELIABLE,
history=HistoryPolicy.KEEP_LAST,
depth=10
)
self.publisher = self.create_publisher(
String,
'topic',
qos_profile
)
Configuration temps réel
- Utiliser un noyau temps réel :
sudo apt install linux-image-rt-amd64 - Configurer DDS pour le temps réel :
- Utilisez
rmw_connextddsourmw_cycloneddsavec des paramètres temps réel. - Exemple
cyclonedds.xml:<CycloneDDS> <Domain> <General> <NetworkInterfaceAddress>lo</NetworkInterfaceAddress> <AllowMulticast>false</AllowMulticast> </General> <Tracing> <Verbosity>warning</Verbosity> </Tracing> </Domain> </CycloneDDS>
- Utilisez
- Définir les priorités des threads :
rclcpp::ExecutorOptions options; options.context = rclcpp::Context::make_shared(); options.context->init(0, nullptr, rclcpp::InitOptions().use_real_time()); rclcpp::executors::SingleThreadedExecutor executor(options);
6. ros2_control et interfaces matérielles
Vue d'ensemble
ros2_control est un framework pour le contrôle temps réel du matériel robotique. Il sépare les interfaces matérielles des algorithmes de contrôle.
Exemple : URDF avec ros2_control
<robot name="my_robot">
<ros2_control name="MyRobotSystem" type="system">
<hardware>
<plugin>my_robot_hardware/MyRobotSystemHardware</plugin>
</hardware>
<joint name="joint1">
<command_interface name="position"/>
<state_interface name="position"/>
<state_interface name="velocity"/>
</joint>
</ros2_control>
</robot>
Fichier de lancement pour ros2_control
from launch import LaunchDescription
from launch_ros.actions import Node
from launch_ros.substitutions import FindPackageShare
from launch.substitutions import PathJoinSubstitution
def generate_launch_description():
return LaunchDescription([
Node(
package='controller_manager',
executable='ros2_control_node',
parameters=[PathJoinSubstitution([
FindPackageShare('my_robot_description'),
'config',
'my_robot_controllers.yaml'
])]
),
Node(
package='controller_manager',
executable='spawner',
arguments=['joint_state_broadcaster']
),
Node(
package='controller_manager',
executable='spawner',
arguments=['joint_trajectory_controller']
)
])
7. Débogage avec rqt, ros2 bag et rviz2
rqt (Outils graphiques)
# Lancer rqt
rqt
# Plugins courants :
# - Moniteur de topics (/rqt_topic)
# - Appel de service (/rqt_service_caller)
# - Graphe des nœuds (/rqt_graph)
ros2 bag (Enregistrement/Rejeu)
# Enregistrer des topics
ros2 bag record /scan /odom
# Rejouer
ros2 bag play rosbag2_2026_06_02-12_00_00
# Informations
ros2 bag info rosbag2_2026_06_02-12_00_00
rviz2 (Visualisation)
# Lancer RViz2
rviz2
