Communication principale de ROS2
06 Nœud
06 Nœuds
6.1 Résumé des nœuds
6.1.1 Qu'est-ce qu'un nœud
Un nœud est l'unité de calcul la plus basique dans ROS 2. Un nœud est un processus utilisant l'API ROS 2 pour communiquer avec d'autres nœuds. Chaque nœud est normalement responsable de fonctions spécifiques, telles que la lecture de données de capteurs, le traitement de données, le contrôle des implémentateurs, etc.
6.1.2 Caractéristiques des nœuds
| Caractéristiques | Annotations |
|---|---|
| Léger | Un exécutable peut contenir plusieurs nœuds |
| Distribution | Le nœud peut s'exécuter sur différentes machines. |
| Découplé | Communications entre les nœuds via interface, ne dépendent pas directement |
| Groupable | Plusieurs nœuds pour effectuer des fonctions complexes |
| Cycle de vie indépendant | Démarrer et fermer chaque nœud indépendamment |
6.1.3 Règles de nommage des nœuds
Le nom du nœud doit être unique (dans le même espace de noms)
Seules les lettres, les chiffres et les soulignements peuvent être inclus
Sensible à la casse
Utilisation recommandée d'un nom descriptif
Exemple de nom :
| Nom du nœud | Évaluation |
|---|---|
| Camera_driver | Excellent. |
| path_planner | Excellent. |
| Node1 | Non recommandé (non descriptif) |
| Oh, my-node. | Invalide (avec trait d'union) |
6.2 Cas du nœud Hello World
6.2.1 Créer un kit python
workspace remplace le chemin réel de l'espace de travail
cd workspace/src
ros2 pkg create pkg_helloworld_py --build-type ament_python --dependencies rclpy --node-name helloworld6.2.2 Préparation des codes
import rclpy
from rclpy.node import Node
import time
class HelloWorldNode(Node):
def __init__(self, name):
super().__init__(name)
while rclpy.ok():
self.get_logger().info("Hello World")
time.sleep(0.5)
def main(args=None):
rclpy.init(args=args)
node = HelloWorldNode("helloworld")
rclpy.spin(node)
node.destroy_node()
rclpy.shutdown()colcon build --packages-select pkg_helloworld_py
source install/setup.bash
ros2 run pkg_helloworld_py helloworld6.3 Étapes suivantes
1.07 Communications de topics
2.08 Communications de service
07 Communication de topic
07 Bulletin d'information sur les topics (Topics)
7.1 Résumé des communications topiques
7.1.1 Qu'est-ce qu'une communication de topic ?
Le topic est le mécanisme de communication asynchrone entre les nœuds ROS 2, utilisant le mode de publication/abonnement (Pub/Sub). Le nœud émetteur émet des nouvelles au topic, et le nœud abonné reçoit les informations du topic, et aucun ne doit connaître l'autre.
7.1.2 Caractéristiques des communications topiques
| Caractéristiques | Description | Appliquer la scène |
|---|---|---|
| Communications asynchrones | L'expéditeur n'attend pas la réponse de l'abonné | Flux de données du capteur |
| Multiple à multiple | Plusieurs éditeurs et abonnés | Diffusion de données |
| Couplage faible | Découplage | Conception modulaire |
| Transfert en flux | Flux de données en cours | Surveillance continue |
7.1.3 Règles de nommage des topics
| Règle | Annotations |
|---|---|
| Doit commencer (espace de noms global) ou nom relatif | |
| Utilisez des lettres minuscules, des chiffres et des soulignements | |
| Utilisez / pour séparer les niveaux d'espace de noms | |
| Évitez de conserver les noms |
Exemple de nom :
| Nom du sujet | Évaluation |
|---|---|
| /cmd_vel | Standards, recommandé |
| /camera/image_raw | Niveau clair. Recommandé. |
| /sensor/front_camera/image | Espace de noms, recommandé. |
| /MyTopic | Non recommandé (capitalisé) |
| add_vel | Nom relatif (espace de nommage du nœud ajouté) |
7.2 Cas de communication
7.2.1 Nouveau paquet de fonctionnalités
cd ~/workspaces/src
ros2 pkg create pkg_topic --build-type ament_python --dependencies rclpy --node-name publisher_demo7.2.2 Réalisation de l'auteur
import rclpy
from rclpy.node import Node
from std_msgs.msg import String
class Topic_Pub(Node):
def __init__(self,name):
super().__init__(name)
self.pub = self.create_publisher(String,"/topic_demo",1)
self.timer = self.create_timer(1,self.pub_msg)
def pub_msg(self):
msg = String()
msg.data = "Hi,I send a message."
self.pub.publish(msg)
def main():
rclpy.init()
pub_demo = Topic_Pub("publisher_node")
rclpy.spin(pub_demo)
pub_demo.destroy_node()
rclpy.shutdown()7.2.3 Modifier les fichiers de configuration
7.2.4 Compilateur du paquet fonctionnel
cd ~/workspace
colcon build --packages-select pkg_topic
source install/setup.bash7.2.5 Exécuter les nœuds de publication
ros2 run pkg_topic publisher_demo
ros2 topic list
ros2 topic echo /topic_demo7.2.6 Créer un abonné
import rclpy
from rclpy.node import Node
from std_msgs.msg import String
class Topic_Sub(Node):
def __init__(self,name):
super().__init__(name)
self.sub = self.create_subscription(String,"/topic_demo",self.sub_callback,1)
def sub_callback(self,msg):
self.get_logger().info(msg.data)
def main():
rclpy.init()
sub_demo = Topic_Sub("subscriber_node")
rclpy.spin(sub_demo)
sub_demo.destroy_node()
rclpy.shutdown()7.2.7 Modifier les fichiers de configuration
7.2.8 Compilateur du paquet fonctionnel
cd ~/workspace
colcon build --packages-select pkg_topic
source install/setup.bash7.2.9 Nœuds opérationnels
ros2 run pkg_topic publisher_demo
ros2 run pkg_topic subscriber_demo7.3 Étapes suivantes
1.08 Communications de service
2.09 Communications d'action
08 Communications de service
08 Communications de service (Services)
8.1 Vue d'ensemble des communications de service
8.1.1 Qu'est-ce que la communication de service
Le service est le mécanisme de communication synchronisée entre les nœuds dans ROS 2, en utilisant le modèle client/serveur. Le client envoie la demande, le service la traite et retourne la réponse.
8.1.2 Services vs topics
| Caractéristique | Services | Topics |
|---|---|---|
| Mode de communication | Synchrone (requête-réponse) | Asynchrone (publication-abonnement) |
| Connexion | Un à un. | Multiple à multiple. |
| Appliquer la scène | Requête d'opération courte | Flux de données en cours |
| Bloc | Client en attente de blocage. | Pas de blocage. |
| Valeur de retour | Nous devons retourner la réponse. | Pas de réponse |
8.1.3 Définition du type de service
# File: example interfaces/srv/AddTwoInts.srv
int64 a
int64 b
---
int64 sum8.2 Exemples de communications de service
8.2.1 Nouveau paquet de fonctionnalités
ros2 pkg create pkg_service --build-type ament_python --dependencies rclpy --node-name server_demo8.2.2 Créer une extrémité de service
import rclpy
from rclpy.node import Node
from example_interfaces.srv import AddTwoInts
class Service_Server(Node):
def __init__(self,name):
super().__init__(name)
self.srv = self.create_service(AddTwoInts, '/add_two_ints', self.Add2Ints_callback)
def Add2Ints_callback(self,request,response):
response.sum = request.a + request.b
print("response.sum = ",response.sum)
return response
def main():
rclpy.init()
server_demo = Service_Server("publisher_node")
rclpy.spin(server_demo)
server_demo.destroy_node()
rclpy.shutdown()ros2 interface show example_interfaces/srv/AddTwoInts8.2.3 Modifier les fichiers de configuration
'server_demo = pkg_service.server_demo:main',8.2.4 Compilateur du paquet fonctionnel
colcon build --packages-select pkg_service
source install/setup.bash
ros2 run pkg_service server_demoros2 service list
ros2 service call /add_two_ints example_interfaces/srv/AddTwoInts "{a: 1,b: 4}"8.2.5 Créer un client
import rclpy
from rclpy.node import Node
from example_interfaces.srv import AddTwoInts
class Service_Client(Node):
def __init__(self,name):
super().__init__(name)
self.client = self.create_client(AddTwoInts,'/add_two_ints')
while not self.client.wait_for_service(timeout_sec=1.0):
print("service not available, waiting again...")
self.request = AddTwoInts.Request()
def send_request(self):
self.request.a = 10
self.request.b = 90
self.future = self.client.call_async(self.request)
def main():
rclpy.init()
service_client = Service_Client("client_node")
service_client.send_request()
while rclpy.ok():
rclpy.spin_once(service_client)
if service_client.future.done():
try:
response = service_client.future.result()
print("Result = ",response.sum)
except Exception as e:
service_client.get_logger().info('Service call failed %r' % (e,))
break
service_client.destroy_node()
rclpy.shutdown()8.2.6 Modifier les fichiers de configuration
'client_demo = pkg_service.client_demo:main'8.2.7 Compilateur du paquet fonctionnel
cd ~/workspace
colcon build --packages-select pkg_service
source install/setup.bash
ros2 run pkg_service server_demosource install/setup.bash
ros2 run pkg_service client_demo8.3 Étapes suivantes
1.09 Communications d'action - Apprendre les communications d'action (longue mission)
- 10 Transformation de coordonnées TF2 - Créer un type de service personnalisé
09 Communications d'action
09 Communications d'action (Actions)
9.1 Résumé des communications d'action
9.1.1 Qu'est-ce que la communication de mouvement ?
L'action est le mécanisme de communication utilisé dans ROS 2 pour gérer les longues affectations. Semblable aux services, les actions sont un mode client-serveur, mais prennent en charge :
-
Retour en temps réel pendant la mise en œuvre du mandat
-
Le client peut annuler une affectation active.
-
Convient au traitement des opérations qui peuvent prendre des secondes à des minutes.
9.1.2 Action vs services
| Caractéristique | Service | Action |
|---|---|---|
| Durée de l'application | Courte opération (ms-s) | Longues missions (secondes-minutes) |
| Retour | Aucun retour en temps réel | Envoyer des retours sur une base continue |
| Annuler | Non pris en charge | Mais annuler. |
| Bloc | Bloc client | Désactiver |
| Appliquer la scène | Requête, opérations simples | Navigation, capture |
9.2 Cas de communications d'action
9.2.1 Nouveau kit fonctionnel
ros2 pkg create --build-type ament_cmake pkg_interfacesint64 num
---
int64 sum
---
float64 progress<buildtool_depend>rosidl_default_generators</buildtool_depend>
<exec_depend>rosidl_default_runtime</exec_depend>
<depend>action_msgs</depend>
<member_of_group>rosidl_interface_packages</member_of_group>find_package(rosidl_default_generators REQUIRED)
rosidl_generate_interfaces(${PROJECT_NAME}
"action/Progress.action")cd ~/workspace
colcon build --packages-select pkg_interfacesros2 interface show pkg_interfaces/action/Progressros2 pkg create pkg_action --build-type ament_python --dependencies rclpy pkg_interfaces --node-name action_server_demo4. Réalisation côté service
4.1 Créer un fournisseur de services
import time
import rclpy
from rclpy.action import ActionServer
from rclpy.node import Node
from pkg_interfaces.action import Progress
class Action_Server(Node):
def __init__(self):
super().__init__('progress_action_server')
self._action_server = ActionServer(
self,
Progress,
'get_sum',
self.execute_callback)
self.get_logger().info('The action server has started!')
def execute_callback(self, goal_handle):
self.get_logger().info('Starting task execution...')
feedback_msg = Progress.Feedback()
total = 0
for i in range(1, goal_handle.request.num + 1):
total += i
feedback_msg.progress = i / goal_handle.request.num
self.get_logger().info('Continuous feedback: %.2f' % feedback_msg.progress)
goal_handle.publish_feedback(feedback_msg)
time.sleep(1)
goal_handle.succeed()
result = Progress.Result()
result.sum = total
self.get_logger().info('Task completed!')
return result
def main(args=None):
rclpy.init(args=args)
Progress_action_server = Action_Server()
rclpy.spin(Progress_action_server)
Progress_action_server.destroy_node()
rclpy.shutdown()4.2 Modifier les fichiers de configuration
'action_server_demo = pkg_action.action_server_demo:main',4.3 Compilateur du paquet fonctionnel
cd ~/workspace
colcon build --packages-select pkg_action
source install/setup.bash
ros2 run pkg_action action_server_demoros2 action list
ros2 action send_goal /get_sum pkg_interfaces/action/Progress "{num: 10}"