ROS2-Kernkommunikation

06 Knoten

06 Knoten (Nodes)

6.1 Zusammenfassung der Knoten

6.1.1 Was ist ein Knoten

Ein Knoten ist die grundlegendste Berechnungseinheit in ROS 2. Ein Knoten ist ein Prozess, der die ROS 2 API verwendet, um mit anderen Knoten zu kommunizieren. Jeder Knoten ist normalerweise für bestimmte Funktionen verantwortlich, wie z. B. das Lesen von Sensordaten, die Datenverarbeitung, die Steuerung von Implementierern usw.

6.1.2 Eigenschaften der Knoten

EigenschaftenAnmerkungen
LeichtgewichtigEine ausführbare Datei kann mehrere Knoten enthalten
VerteilungDer Knoten kann auf verschiedenen Maschinen ausgeführt werden.
EntkoppeltKommunikation zwischen Knoten über Schnittstelle, nicht direkt abhängig
GruppierbarMehrere Knoten zur Ausführung komplexer Funktionen
Unabhängiger LebenszyklusJeder Knoten unabhängig starten und schließen

6.1.3 Regeln für die Knotenbenennung

Der Knotenname muss eindeutig sein (im selben Namensraum)

Es können nur Buchstaben, Zahlen und Unterstriche enthalten sein

Groß-/Kleinschreibung beachten

Empfohlene Verwendung eines beschreibenden Namens

Namensbeispiel:

KnotennameBewertung
Camera_driverHervorragend.
path_plannerHervorragend.
Node1Nicht empfohlen (nicht beschreibend)
Oh, my-node.Ungültig (mit Bindestrich)

6.2 Hello World-Knoten-Fall

6.2.1 Python-Kit erstellen

workspace ersetzt den tatsächlichen Workspace-Pfad

bash
cd workspace/src
ros2 pkg create pkg_helloworld_py --build-type ament_python --dependencies rclpy --node-name helloworld

6.2.2 Vorbereitung der Codes

bash
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()
bash
colcon build --packages-select pkg_helloworld_py
source install/setup.bash
ros2 run pkg_helloworld_py helloworld

6.3 Nächste Schritte

1.07 Topic-Kommunikation

2.08 Service-Kommunikation

07 Topic-Kommunikation

07 Aktuelle Mitteilungen (Topics)

7.1 Zusammenfassung der aktuellen Kommunikation

7.1.1 Was ist eine Topic-Kommunikation?

Topic ist der Mechanismus für asynchrone Kommunikation zwischen ROS 2-Knoten unter Verwendung des Veröffentlichungs-/Abonnement-Modus (Pub/Sub). Der Herausgeberknoten gibt Nachrichten an das Topic aus, und der Abonnentenknoten erhält Informationen vom Topic, und keiner muss den anderen kennen.

7.1.2 Eigenschaften der Topic-Kommunikation

EigenschaftenBeschreibungAnwendungsszene
Asynchrone KommunikationSender wartet nicht auf die Antwort des AbonnentenSensordatenstrom
Mehrere zu mehrerenMehrere Herausgeber und AbonnentenDatenübertragung
Lose gekoppeltEntkopplungModulare Konstruktion
Stream-ÜbertragungLaufende DatenströmeKontinuierliche Überwachung

7.1.3 Regeln für die Topic-Benennung

RegelAnmerkungen
Muss mit (globaler Namensraum) oder relativem Namen beginnen
Verwenden Sie Kleinbuchstaben, Zahlen und Unterstriche
Verwenden Sie /, um Namensraum-Ebenen zu trennen
Vermeiden Sie reservierte Namen

Namensbeispiel:

Topic-NameBewertung
/cmd_velStandards, empfohlen
/camera/image_rawEbene klar. Empfohlen.
/sensor/front_camera/imageNamensraum, empfohlen.
/MyTopicNicht empfohlen (großgeschrieben)
add_velRelativer Name (Knoten-Namensraum hinzugefügt)

7.2 Kommunikationsfälle

7.2.1 Neues Funktionspaket

bash
cd ~/workspaces/src
ros2 pkg create pkg_topic --build-type ament_python --dependencies rclpy --node-name publisher_demo

7.2.2 Der Autor erreicht

bash
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 Konfigurationsdateien bearbeiten

7.2.4 Funktionspaket kompilieren

bash
cd ~/workspace
colcon build --packages-select pkg_topic
source install/setup.bash

7.2.5 Veröffentlichungsknoten ausführen

bash
ros2 run pkg_topic publisher_demo
ros2 topic list
ros2 topic echo /topic_demo

7.2.6 Abonnenten erstellen

bash
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 Konfigurationsdateien bearbeiten

7.2.8 Funktionspaket kompilieren

bash
cd ~/workspace
colcon build --packages-select pkg_topic
source install/setup.bash

7.2.9 Knoten betreiben

bash
ros2 run pkg_topic publisher_demo
ros2 run pkg_topic subscriber_demo

7.3 Nächste Schritte

1.08 Service-Kommunikation

2.09 Action-Kommunikation

08 Service-Kommunikation

08 Service-Kommunikation (Services)

8.1 Übersicht über die Service-Kommunikation

8.1.1 Was ist Service-Kommunikation

Service ist der Mechanismus für synchronisierte Kommunikation zwischen Knoten in ROS 2, unter Verwendung des Client/Server-Modells. Der Client sendet die Anfrage, der Service bearbeitet sie und gibt die Antwort zurück.

8.1.2 Services vs. Topics

MerkmalServicesTopics
KommunikationsmodusSynchron (Anfrage-Antwort)Asynchron (Veröffentlichungs-Abonnement)
VerbindungEins zu eins.Mehrere zu mehreren.
AnwendungsszeneKurze OperationsabfrageLaufende Datenströme
BlockClient blockiert wartend.Keine Blockierung.
RückgabewertWir müssen die Antwort zurückgeben.Keine Antwort

8.1.3 Definition des Servicetyps

bash
# File: example interfaces/srv/AddTwoInts.srv
int64 a
int64 b
---
int64 sum

8.2 Beispiele für Service-Kommunikation

8.2.1 Neues Funktionspaket

bash
ros2 pkg create pkg_service --build-type ament_python --dependencies rclpy --node-name server_demo

8.2.2 Service-Endpunkt erstellen

bash
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()
bash
ros2 interface show example_interfaces/srv/AddTwoInts

8.2.3 Konfigurationsdateien bearbeiten

bash
'server_demo = pkg_service.server_demo:main',

8.2.4 Funktionspaket kompilieren

bash
colcon build --packages-select pkg_service
source install/setup.bash
ros2 run pkg_service server_demo
bash
ros2 service list
ros2 service call /add_two_ints example_interfaces/srv/AddTwoInts "{a: 1,b: 4}"

8.2.5 Client erstellen

bash
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 Konfigurationsdateien bearbeiten

bash
'client_demo = pkg_service.client_demo:main'

8.2.7 Funktionspaket kompilieren

bash
cd ~/workspace
colcon build --packages-select pkg_service
source install/setup.bash
ros2 run pkg_service server_demo
bash
source install/setup.bash
ros2 run pkg_service client_demo

8.3 Nächste Schritte

1.09 Action-Kommunikation - Action-Kommunikation lernen (lange Mission)

  1. 10 TF2-Koordinatentransformation - benutzerdefinierten Servicetyp erstellen

09 Action-Kommunikation

09 Action-Kommunikation (Actions)

9.1 Zusammenfassung der Action-Kommunikation

9.1.1 Was ist Bewegungskommunikation?

Action ist der Kommunikationsmechanismus, der in ROS 2 verwendet wird, um lange Aufgaben zu bearbeiten. Ähnlich wie Services sind Actions ein Client-Server-Modus, aber unterstützen:

  • Echtzeit-Feedback während der Mandatsumsetzung

  • Client kann eine aktive Aufgabe abbrechen.

  • Geeignet für die Bearbeitung von Operationen, die Sekunden bis Minuten dauern können.

9.1.2 Action vs. Services

MerkmalServiceAction
AnwendungsdauerKurze Operation (ms-s)Lange Aufgaben (Sekunden-Minuten)
FeedbackKein Echtzeit-FeedbackSendet kontinuierlich Feedback
AbbrechenNicht unterstütztAber abbrechen.
BlockClient-BlockDeaktivieren
AnwendungsszeneAbfrage, einfache OperationenNavigation, Erfassung

9.2 Action-Kommunikationsfälle

9.2.1 Neues Funktionskit

bash
ros2 pkg create --build-type ament_cmake pkg_interfaces
bash
int64 num
---
int64 sum
---
float64 progress
bash
<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>
bash
find_package(rosidl_default_generators REQUIRED)

rosidl_generate_interfaces(${PROJECT_NAME}
  "action/Progress.action")
bash
cd ~/workspace
colcon build --packages-select pkg_interfaces
bash
ros2 interface show pkg_interfaces/action/Progress
bash
ros2 pkg create pkg_action --build-type ament_python --dependencies rclpy pkg_interfaces --node-name action_server_demo

4. Service-End-Realisierung

4.1 Service-Anbieter erstellen

bash
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 Konfigurationsdateien bearbeiten

bash
'action_server_demo = pkg_action.action_server_demo:main',

4.3 Funktionspaket kompilieren

bash
cd ~/workspace
colcon build --packages-select pkg_action
source install/setup.bash
ros2 run pkg_action action_server_demo
bash
ros2 action list
ros2 action send_goal /get_sum pkg_interfaces/action/Progress "{num: 10}"

5. Client erreicht

5.1 Client erstellen