ROS2-kerncommunicatie
06 Knooppunt
06 Knooppunten (Nodes)
6.1 Samenvatting van knooppunten
6.1.1 Wat is een knooppunt
Een knooppunt is de meest basale rekeneenheid in ROS 2. Een knooppunt is een proces dat de ROS 2 API gebruikt om met andere knooppunten te communiceren. Elk knooppunt is normaal gesproken verantwoordelijk voor specifieke functies, zoals het lezen van sensorgegevens, het verwerken van gegevens, het besturen van implementeerders, enz.
6.1.2 Kenmerken van knooppunten
| Kenmerken | Annotaties |
|---|---|
| Lichtgewicht | Een uitvoerbaar bestand kan meerdere knooppunten bevatten |
| Distributie | Knooppunt kan op verschillende machines draaien. |
| Ontkoppeld | Communicatie tussen knooppunten via interface, niet rechtstreeks afhankelijk |
| Groepeerbaar | Meerdere knooppunten om complexe functies uit te voeren |
| Onafhankelijke levenscyclus | Elk knooppunt onafhankelijk starten en sluiten |
6.1.3 Knooppuntnaamgevingsregels
Knooppuntnaam moet uniek zijn (in dezelfde naamruimte)
Alleen letters, cijfers en onderstrepingstekens kunnen worden opgenomen
Hoofdlettergevoelig
Aanbevolen gebruik van beschrijvende naam
Voorbeeld van naam:
| Knooppuntnaam | Evaluatie |
|---|---|
| Camera_driver | Uitstekend. |
| path_planner | Uitstekend. |
| Node1 | Niet aanbevolen (geen beschrijving) |
| Oh, my-node. | Ongeldig (met afbreekstreepje) |
6.2 Hello World Node-case
6.2.1 Python-kit maken
workspace vervangt het werkelijke werkruimtepad
cd workspace/src
ros2 pkg create pkg_helloworld_py --build-type ament_python --dependencies rclpy --node-name helloworld6.2.2 Voorbereiding van 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 Volgende stappen
1.07 Topic-communicatie
2.08 Service-communicatie
07 Topic-communicatie
07 Topic-nieuwsbrief (Topics)
7.1 Samenvatting van topic-communicatie
7.1.1 Wat is topic-communicatie?
Topic is het mechanisme voor asynchrone communicatie tussen ROS 2-knooppunten, met behulp van de publicatie-/abonnementsmodus (Pub/Sub). Het uitgeversknooppunt geeft nieuws uit aan het topic, en het abonneeknooppunt ontvangt informatie van het topic, en geen van beide hoeft de ander te kennen.
7.1.2 Kenmerken van topic-communicatie
| Kenmerken | Beschrijving | Toepassingsscène |
|---|---|---|
| Asynchrone communicatie | Verzender wacht niet op de reactie van de abonnee | Sensorgegevensstroom |
| Veel-op-veel | Meerdere uitgevers en abonnees | Datatransmissie |
| Zwak gekoppeld | Ontkoppeling | Modulair ontwerp |
| Streamoverdracht | Lopende datastromen | Continue monitoring |
7.1.3 Topic-naamgevingsregels
| Regel | Annotaties |
|---|---|
| Moet beginnen (globale naamruimte) of relatieve naam | |
| Gebruik kleine letters, cijfers en onderstrepingstekens | |
| Gebruik / om naamruimteniveaus te scheiden | |
| Vermijd het behouden van namen |
Voorbeeld van naam:
| Topicnaam | Evaluatie |
|---|---|
| /cmd_vel | Standaarden, aanbevolen |
| /camera/image_raw | Niveau duidelijk. Aanbevolen. |
| /sensor/front_camera/image | Naamruimte, aanbevolen. |
| /MyTopic | Niet aanbevolen (in hoofdletters) |
| add_vel | Relatieve naam (knooppuntnaamruimte toegevoegd) |
7.2 Communicatiecases
7.2.1 Nieuw functioneel pakket
cd ~/workspaces/src
ros2 pkg create pkg_topic --build-type ament_python --dependencies rclpy --node-name publisher_demo7.2.2 De auteur bereikt
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 Configuratiebestanden bewerken
7.2.4 Functioneel pakket compileren
cd ~/workspace
colcon build --packages-select pkg_topic
source install/setup.bash7.2.5 Vrijgaveknooppunten uitvoeren
ros2 run pkg_topic publisher_demo
ros2 topic list
ros2 topic echo /topic_demo7.2.6 Een abonnee aanmaken
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 Configuratiebestanden bewerken
7.2.8 Functioneel pakket compileren
cd ~/workspace
colcon build --packages-select pkg_topic
source install/setup.bash7.2.9 Operationele knooppunten
ros2 run pkg_topic publisher_demo
ros2 run pkg_topic subscriber_demo7.3 Volgende stappen
1.08 Service-communicatie
2.09 Action-communicatie
08 Service-communicatie
08 Service-communicatie (Services)
8.1 Overzicht van service-communicatie
8.1.1 Wat is service-communicatie
Service is het mechanisme voor gesynchroniseerde communicatie tussen knooppunten in ROS 2, met behulp van het client/server-model. De client verzendt het verzoek, de service verwerkt het en stuurt de respons terug.
8.1.2 Services vs topics
| Kenmerk | Services | Topics |
|---|---|---|
| Communicatiemodus | Sync (verzoek-respons) | Async (publicatie-abonnement) |
| Verbinding | Eén op één. | Veel-op-veel. |
| Toepassingsscène | Korte operatiequery | Lopende datastromen |
| Blok | Client blokkeert tijdens wachten. | Geen blokkering. |
| Retourwaarde | We moeten de respons retourneren. | Geen respons |
8.1.3 Definitie van servicetype
# File: example interfaces/srv/AddTwoInts.srv
int64 a
int64 b
---
int64 sum8.2 Voorbeelden van service-communicatie
8.2.1 Nieuw functioneel pakket
ros2 pkg create pkg_service --build-type ament_python --dependencies rclpy --node-name server_demo8.2.2 Een service-eindpunt aanmaken
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 Configuratiebestanden bewerken
'server_demo = pkg_service.server_demo:main',8.2.4 Functioneel pakket compileren
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 Client maken
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 Configuratiebestanden bewerken
'client_demo = pkg_service.client_demo:main'8.2.7 Functioneel pakket compileren
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 Volgende stappen
1.09 Action-communicatie - Action-communicatie leren (lange missie)
- 10 TF2 coördinatentransformatie - aangepast servicetype maken
09 Action-communicatie
09 Action-communicatie (Actions)
9.1 Samenvatting van action-communicatie
9.1.1 Wat is bewegingscommunicatie?
Action is het communicatiemechanisme dat in ROS 2 wordt gebruikt om lange opdrachten te verwerken. Vergelijkbaar met services zijn acties een client-server-modus, maar ondersteunen:
-
Realtime feedback tijdens de uitvoering van het mandaat
-
Client kan een actieve opdracht annuleren.
-
Geschikt voor het afhandelen van bewerkingen die seconden tot minuten kunnen duren.
9.1.2 Action vs services
| Kenmerk | Service | Action |
|---|---|---|
| Lengte van de toepassing | Korte bewerking (ms-s) | Lange missies (seconden-minuten) |
| Feedback | Geen realtime feedback | Verzend continu feedback |
| Annuleren | Niet ondersteund | Maar annuleren. |
| Blok | Clientblok | Uitschakelen |
| Toepassingsscène | Query, eenvoudige bewerkingen | Navigatie, vastleggen |
9.2 Action-communicatiecases
9.2.1 Nieuw functionele kit
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. Service-eind-realisatie
4.1 Een serviceprovider maken
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 Configuratiebestanden bewerken
'action_server_demo = pkg_action.action_server_demo:main',4.3 Functioneel pakket compileren
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}"