ROS 1 Noetic Grundlagen
Dieses Kapitel führt in den ROS 1 Noetic Entwicklungsworkflow auf dem reComputer Jetson ein, einschließlich Workspaces, Pakete, gängige Werkzeuge, Topic/Service-Kommunikation, benutzerdefinierte Nachrichten und TF.
Lange ausführbare Beispiele sind unter
./code/gespeichert, und zugehörige Abbildungen sind unter./images/gespeichert.
Inhalt
7.2.1.1 Einführung in ROS 1
ROS 1 (Robot Operation System 1) ist ein quelloffenes Framework für Robotiksoftware, das von Open Robotics gepflegt wird. Es ist kein Betriebssystem im herkömmlichen Sinne, sondern bietet Roboteranwendungen Kommunikationsmechanismen, Werkzeugketten und eine Bibliothek mit allgemeinen Funktionen, was die Entwicklung von Robotiksoftware erheblich vereinfacht. Es stellt die von einem Betriebssystem benötigten Dienste bereit, darunter Hardwareabstraktion, Steuerung der unteren Geräteebene, Implementierung häufig verwendeter Funktionen, Nachrichtenaustausch zwischen Prozessen und Paketverwaltung. Es bietet auch Werkzeuge und Bibliotheksfunktionen, die zum Erfassen, Kompilieren, Vorbereiten und computerübergreifenden Ausführen von Code benötigt werden.
ROS 1 Versionen
Gängige ROS 1 Editionen wie folgt:
| Versionsname | Ubuntu | Wartungsstatus |
|---|---|---|
| Kinetic | 16.04 | Eingestellt |
| Melodic | 18.04 | Eingestellt |
| Noetic | 20.04 | Letzte ROS 1 Version (LTS) |
Nachfolgende Beispiele in diesem Kapitel basieren auf der Noetic-Version von ROS 1.
Das Hauptziel von ROS ist die Wiederverwendung von Code für die Robotikforschung und -entwicklung. ROS ist ein verteiltes Framework aus Prozessen (d.h. "Nodes"), die in Paketen gekapselt sind, und Paketen, die einfach geteilt und veröffentlicht werden können. ROS unterstützt auch ein gemeinsames System ähnlich einem Code-Repository, das auch die Zusammenarbeit und Verbreitung von Projekten ermöglicht. Dieses Design erlaubt die Entwicklung eines Projekts und das Erreichen vollständiger unabhängiger Entscheidungsfindung (ohne ROS-Einschränkungen) vom Dateisystem bis zur Benutzeroberfläche. Gleichzeitig können alle Arbeiten in die grundlegenden ROS-Werkzeuge integriert werden.
Hauptmerkmale von ROS 1
(1) Eine verteilte Struktur (jeder Arbeitsprozess wird als Node betrachtet und über einen Node-Manager verwaltet),
(2) Mehrsprachige Unterstützung (z.B. C++, Python, etc.),
(3) Gute Elastizität (es kann entweder ein einzelner Node geschrieben oder viele Nodes durch roslaunch zu einem größeren Projekt organisiert werden),
(4) Quelloffener Code (ROS folgt der BSD-Vereinbarung und ist für private und kommerzielle Anwendungen und Modifikationen vollständig kostenlos).
Gesamtarchitektur von ROS 1
Open-Source-Community-Ebene: Dazu gehören unter anderem Wissensaustausch zwischen Entwicklern, Codes, Algorithmen.
Dateisystemebene: Eine Beschreibung des Codes und der ausführbaren Dateien, die auf der Festplatte zu finden sind.
Berechnungsebene: Spiegelt die Kommunikation zwischen Prozess und Prozess, Prozess und System wider.
ROS 1 Entwicklungsumgebung starten
Das SeeedStudio Jetson Orin Nano Super DevKit mit einem lokalen Ubuntu 22.04 System unterstützt ROS 1 nicht direkt, aber ROS 1 ist in der Firmware vorinstalliert. Wenn Sie die von uns bereitgestellten BSP-Firmwares verwenden, können Sie den folgenden Befehl ausführen, um den Docker-Container mit ROS 1 im Terminalfenster des Jetson-Geräts zu starten, unter Verwendung von Ubuntu 22.04:
xhost +
sudo docker run -it \
--net=host \
--privileged \
-v /dev:/dev \
-v /tmp/.X11-unix:/tmp/.X11-unix \
-e DISPLAY=$DISPLAY \
-e QT_X11_NO_MITSHM=1 \
ros:noeticWenn Sie ein Jetson-Gerät ohne vorinstallierte ROS 1-Entwicklungsumgebung erwerben, lesen Sie hier für die Installation.
Berechnungsdiagramm-Profil
Nodes
Der Node ist das grundlegendste Berechnungsimplementierungsmodul in ROS 1 und entspricht normalerweise einem unabhängig laufenden Prozess. Ein ROS-System ist kein einzelnes Programm, sondern ein verteiltes System aus mehreren zusammenarbeitenden Nodes.
In ROS 1 hat jeder Node normalerweise eine relativ einzelne und klar abgegrenzte Funktion, wie zum Beispiel:
Sensordatenerfassung (Kamera, Radar, IMU)
Algorithmische Verarbeitung (Positionierung, Kartierung, Routenplanung)
Steuerungsausgabe (Geschwindigkeitssteuerung, Motorsteuerung)
Datenweiterleitung und Debugging (Protokolle, Visualisierung)
Eigenschaften von ROS 1 Nodes
Unabhängiger Prozess Jeder Node ist normalerweise ein unabhängiger Linux-Prozess, wobei die Interaktion zwischen Nodes über ROS-Kommunikationsmechanismen erfolgt.
Entkoppeltes Design Funktionen werden nicht direkt zwischen Nodes aufgerufen, sondern kommunizieren über Topic, Service, Action, Parameter usw., um Systemerweiterung und -wartung zu erleichtern.
Eindeutiger Name Jeder Node muss einen eindeutigen Namen im ROS-Berechnungsgraphen haben, z.B. /turtle_velocity_publisher
Verteilte Ausführung Nodes können auf verschiedenen Hosts ausgeführt werden, solange sie mit demselben ROS Master verbunden sind.
Lebenszyklus vom ROS Master verwaltet Node registriert seine eigenen Informationen (Name, Veröffentlichung/Abonnement usw.) beim ROS Master beim Start und wird von jedem Node ausgeführt.
Gängige Kommunikationsmittel in ROS 1
Topic Node wird für asynchrone Kommunikation durch das Publish/Subscribe-Modell für hochfrequente Datenströme verwendet.
Service Synchrone Kommunikation basierend auf Anfrage-Antwort.
Action Anwendbar auf zeitaufwändige Aufgaben, unterstützt Feedback und Abbruch.
Parameter Server (Parameterserver) Zur Speicherung von Systemlaufparametern.
Node ist der Hauptprozess der Berechnungsimplementierung. ROS besteht aus vielen Nodes.
Drücken Sie einfach [Tab], wenn Sie einen Teil eingeben.
Das Folgende ist ein Beispiel für ein Nodendiagramm:
Wenn wir [rosnode] in der Befehlszeile eingeben und doppelt Tab drücken, finden wir diese Schlüsselwörter unter der Befehlszeile.
ROS-Befehlszeilenwerkzeug rosnode:
Der aktuelle Node und die Node-Informationen werden oft für die Entwicklung und das Debugging benötigt, also merken Sie sich diese häufig verwendeten Befehle. Falls das nicht möglich ist, kann die Verwendung des rosnode-Befehls auch über rosnode help eingesehen werden.
Nachricht
Logische Verbindungen und Datenaustausch zwischen Nodes werden durch Nachrichten erreicht.
Wenn wir [rosmsg] in der Befehlszeile eingeben und doppelt die Tab-Taste drücken, finden wir diese Schlüsselwörter unter der Befehlszeile.
ROS-Befehlszeilenwerkzeug rosmsg:
Topic
Das Topic ist eine Art der Informationsübermittlung (Veröffentlichung/Abonnement). Jede Nachricht wird auf dem entsprechenden Thema veröffentlicht, und jedes Topic ist stark typisiert.
Die Topic-Nachrichten von ROS können mit TCP/IP oder UDP übertragen werden, und ROS verwendet standardmäßig TCP/IP. Basierend auf TCP-Übertragung als TCPROS handelt es sich um eine langfristige Verbindung; UDP-basiert als UDPROS ist ein Modus mit geringer Verzögerung und effizienter Übertragung, aber anfällig für Datenverlust und geeignet für Fernoperationen.
Wenn wir [rostopic] in der Befehlszeile eingeben und dann doppelt die Tab-Taste drücken, finden wir diese Schlüsselwörter unter der Befehlszeile.
ROS-Befehlszeilenwerkzeug rostopic:
Services
Der Service muss auch einen eindeutigen Namen für das Anfrage-Antwort-Modell haben. Wenn ein Service von einem Node bereitgestellt wird, können alle Nodes mit ihm kommunizieren, indem sie von der ROS-Clientbibliothek entwickelten Code verwenden.
Wenn wir [rosservice] in der Befehlszeile eingeben und dann doppelt die Tab-Taste drücken, finden wir diese Schlüsselwörter unter der Befehlszeile.
ROS-Befehlszeilenwerkzeug rosservice:
Nachrichtenaufzeichnungspaket
Das Nachrichtenaufzeichnungspaket ist ein Dateiformat zum Speichern und Wiedergeben von ROS-Nachrichtendaten und wird in der .bag-Datei gespeichert. Es ist ein wichtiger Mechanismus zur Datenspeicherung.
Wenn wir [rosbag] in der Befehlszeile eingeben und doppelt Tab drücken, finden wir diese Schlüsselwörter unter der Befehlszeile.
ROS-Befehlszeilenwerkzeug rosbag:
Parameterserver
Der Parameterserver ist ein gemeinsam genutztes multivariantes Wörterbuch, das online zugänglich ist und vom Node-Manager nach Schlüsselwort gespeichert wird.
Wenn wir [rosparam] in der Befehlszeile eingeben und doppelt die Tab-Taste drücken, finden wir diese Schlüsselwörter unter der Befehlszeile.
ROS-Befehlszeilenwerkzeug rosparam:
Node-Manager (Master)
Der Node-Manager wird für Themen, Registrierung von Servicenamen und Suche usw. verwendet. Ohne Node-Manager findet im gesamten ROS-System keine Kommunikation zwischen Nodes statt.
Dateisystemebene
Die Abhängigkeiten zwischen Paketen können konfiguriert werden. Wenn Paket A von Paket B abhängt, muss B im ROS-Build-System älter als A sein und A kann die Header- und Bibliotheksdateien in B verwenden.
Das Konzept der Dateisystemebene ist wie folgt:
Funktionspaketliste:
Diese Liste zeigt die Abhängigkeit des Pakets, die Dokumentation des Quelldokuments usw. an. Die package.xml-Datei des Pakets ist eine Liste von Paketen.
Funktionspaket:
Das Paket ist die grundlegende Form der Softwareorganisation im ROS-System und enthält laufende Nodes und Konfigurationsdateien usw.
ROS-Paket zugehöriger Befehl
Integriertes Funktionskit
Eine Kombination aus mehreren Paketen kann gebildet werden.
Nachrichtentyp
Eine vorherige Informationsnotiz ist erforderlich, um die Nachricht zwischen den Nodes von ROS zu senden. Standardtypnachrichten werden in ROS bereitgestellt und können auch definiert werden. Die Nachrichtentypbeschreibung wird in der msg-Datei unter dem Paket gespeichert.
Servicetyp
Die Datenstruktur für Serviceanfragen und -antworten, die von jedem Prozess in ROS bereitgestellt wird, ist definiert.
Open-Source-Community-Ebene
Distribution: Die ROS-Release ist eine Reihe von integrierten Paketen, die unabhängig mit einer Versionsnummer installiert werden können. Die ROS-Release spielt eine ähnliche Rolle wie die Linux-Distribution. Dies erleichtert die Installation der ROS-Software und ermöglicht die Aufrechterhaltung konsistenter Versionen durch einen Software-Pool.
Repository: ROS stützt sich auf gemeinsam genutzte Open-Source- und Software-Repository-Websites oder Host-Dienste, bei denen verschiedene Institutionen ihre eigene Robotiksoftware und -programme veröffentlichen und teilen können.
ROSWiki: ROSWiki ist das Hauptforum für die Aufzeichnung von Informationen über ROS-Systeme. Jeder kann Konten registrieren, eigene Dokumente beitragen, Korrekturen oder Aktualisierungen bereitstellen, Lehrpläne vorbereiten und andere Handlungen durchführen.
Bug-Ticket-System: Wenn Sie ein Problem finden oder eine neue Funktion vorschlagen möchten, bietet ROS die Ressourcen dafür.
Mailingliste: Die ROS-Benutzer-Mailingliste ist der Hauptkommunikationskanal für ROS und ermöglicht den Austausch von Fragen oder Informationen von ROS-Software-Updates bis zur ROS-Software-Nutzung, wie es auch beim Forum der Fall ist.
ROS Answer: Benutzer können diese Ressource nutzen, um Fragen zu stellen.
Überblick über Kommunikationsmechanismen
Topic
Das Publish-Subscribe-Kommunikationsmodell wird in ROS häufig verwendet. Topic wird im Allgemeinen für unidirektionale, streamingbasierte Kommunikation verwendet. Topic hat im Allgemeinen eine starke Typdefinition: Ein Topic-Typ kann nur Nachrichten für einen bestimmten Datentyp akzeptieren/senden. Der Publisher wird nicht auf Typkonsistenz geprüft, aber der Subscriber überprüft den Typ mittels MD5 zum Zeitpunkt der Annahme und gibt dann einen Fehler aus.
Service
Service wird verwendet, um synchrone Kommunikation in der ROS-Kommunikation zu verarbeiten, unter Verwendung der Semantik Server/Client. Jeder Servicetyp hat zwei Teile: Request und Response. Für Service-Server überprüft ROS nicht die Aliasnamen, nur der zuletzt registrierte Server ist gültig und mit dem Client verbunden.
Action
Action verwendet mehrere Topics, um Aufgaben zu definieren, die Goal (Ziel), Feedback (Rückmeldung) und Result (Ergebnis) umfassen. Die Kompilierung von Action erzeugt automatisch sieben Strukturen: Action, ActionGoal, ActionFeedback, ActionResult, Goal, Feedback und Result.
Eigenschaften von Action:
Ein Frage-Antwort-Kommunikationsmechanismus
Mit kontinuierlichem Feedback
Kann während der Mission beendet werden.
ROS-basierter Nachrichtenmechanismus implementiert
Schnittstelle für Action:
Goal: Veröffentlichung von Missionszielen
Cancel: Anfrage zur Stornierung
Status: Benachrichtigung des Clients über den aktuellen Status
Feedback: Kontrolldaten für periodisches Feedback zum Aufgabenverlauf
Result: Sendet die Ergebnisse der Aufgabe an den Client, nur einmal.
Vergleich der Kommunikationsmuster
Gängige Komponenten
Die Launch-Datei; TF-Koordinatentransformation; Rviz; Gazebo; QT-Toolbox; Navigation; Movelt!
Launch: Die Launch-Datei ist eine Möglichkeit, mehrere Nodes gleichzeitig in ROS zu aktivieren. Sie aktiviert auch automatisch den ROS Master Node-Manager und ermöglicht die Konfiguration jedes Nodes, was den Betrieb mehrerer Nodes erheblich erleichtert.
TF-Koordinatentransformation: In der Robotik gibt es oft eine große Anzahl von Komponenten in ihrer Arbeitsumgebung, und die Position und Orientierung verschiedener Komponenten sind bei Robotikdesign und -anwendungen beteiligt. TF ist ein Paket, das es Benutzern ermöglicht, mehrere Koordinatensysteme im Zeitverlauf zu verfolgen, unter Verwendung von baumförmigen Datenstrukturen, Zeitpufferung und Aufrechterhaltung von Koordinatenbeziehungen zwischen mehreren Koordinatensystemen, was Entwicklern bei der Änderung von Koordinaten zu jedem Zeitpunkt, bei Abschlusspunkten zwischen Koordinaten, Vektoren usw. helfen kann.
QT-Toolbox: Um visuelles Debugging und Anzeige zu erleichtern, bietet ROS ein Backend-Grafikwerkzeugpaket für die Qt-Architektur - rqt common plugins, das eine Reihe praktischer Werkzeuge enthält: Log-Ausgabe-Tool (rqt console), Berechnungsvisualisierungs-Tool (rqt graph), Datenvisualisierungs-Tool (rqt plot), Parameter-Dynamikkonfigurations-Tool (rqt reconfigure)
Rviz: rviz ist ein dreidimensionales Visualisierungswerkzeug, das gut mit verschiedenen Roboterplattformen kompatibel ist, die auf dem ROS-Software-Framework basieren. In rviz kann XML verwendet werden, um die Abmessungen, Masse, Position, Material, Gelenke usw. von Robotern, umgebenden Objekten usw. zu beschreiben und in Schnittstellen darzustellen. Gleichzeitig kann rviz in Echtzeit Informationen über Robotersensoren, den Bewegungszustand des Roboters, Änderungen in der Umgebung usw. grafisch anzeigen.
Gazebo: Gazebo ist eine leistungsstarke dreidimensionale physikalische Simulationsplattform mit leistungsstarken Physik-Engines, hochwertiger Grafikdarstellung, bequemen Programmier- und Grafikschnittstellen und, was am wichtigsten ist, quelloffen und kostenlos. Obwohl Robotermodelle in Gazebo die gleichen sind wie die in rviz, müssen physikalische Eigenschaften von Robotern und der Umgebung, wie Masse, Reibungsfaktoren, Elastizitätsfaktoren usw., zu den Modellen hinzugefügt werden. Die Sensorinformationen des Roboters können auch in visueller Form durch Hinzufügen von Simulationsumgebungen über Plugins dargestellt werden.
Navigation: Navigation ist das ROS 2D-Navigationskit, das vereinfacht gesagt einen sicheren und zuverlässigen Roboter-Geschwindigkeitssteuerungsbefehl basierend auf dem Informationsfluss und der Gesamtposition des Roboters berechnet, wie z.B. dem Eingabe-Kilometerzähler.
Movelt: Movelt! Das Funktionskit ist das am häufigsten verwendete Werkzeugkit und wird hauptsächlich für die Trajektorienplanung verwendet. Moveit! Es ist entscheidend, dass Assistenten für einige Dokumente konfiguriert werden, die bei der Planung verwendet werden müssen.
Alle ROS 1 Versionen
Referenzlink: http://wiki.ros.org/Distributions
Die ROS-Version (ROS-Release) bezieht sich auf das ROS-Softwarepaket, ähnlich der Linux-Distribution (z.B. Ubuntu). Die Veröffentlichung der ROS-Version soll es Entwicklern ermöglichen, ein relativ stabiles Code-Repository zu verwenden, bis sie bereit sind, alle Inhalte zu aktualisieren. Daher reparieren die ROS-Entwickler in der Regel nur Fehler dieser Version nach jeder Veröffentlichung, während sie eine kleine Anzahl von Kernpaketverbesserungen bereitstellen. Stand Oktober 2019 sind der Name der Hauptversionsdistribution von ROS, das Veröffentlichungsdatum und ihr Lebenszyklus in der folgenden Tabelle dargestellt:
Referenzlinks
ROS Offizielles Wiki:
ROS Offizielle Anleitung: http://wiki.ros.org/ROS/Tutorials
ROS Installation: https://wiki.ros.org/noetic/Installation/Ubuntu (überspringen Sie dies, wenn ROS bereits vorinstalliert ist)
Abbildungen












7.2.1.2 Vorbereiten des Workspace
Workspace-Verzeichnis
Die Dokumentenstruktur von ROS, nicht jeder Ordner ist obligatorisch und wird nach Geschäftsanforderungen gestaltet.
Über den Workspace
Der Workspace ist der Ort, an dem die ROS-Projektdokumente verwaltet und organisiert werden. Die visuelle Beschreibung ist ein Lager, das verschiedene Projektarbeiten für ROS enthält, was die Verwaltung des Systems erleichtert. Es ist ein Ordner in einer visuellen grafischen Oberfläche. Unsere eigenen ROS-Codes befinden sich normalerweise im Workspace. Es gibt vier Hauptverzeichnisse der ersten Ebene:
src: Quellspace; ROS Catkin-Paket (Quellpaket)
build: Kompilierter Space; Catkin (CMake) Cache-Informationen und Zwischendateien
devel: Entwicklungs-Space; Ausgabe von Zieldateien (einschließlich Headern, dynamischen Link-Bibliotheken, statischen Link-Bibliotheken, ausführbaren Dateien usw.), Umgebungsvariablen
install: Installationsspace
Der oberste Workspace (der beliebig benannt werden kann) und src (muss src sein) Ordner müssen selbst erstellt werden;
build und devel Ordner werden automatisch durch den catkin_make Befehl erstellt;
Install Ordner werden automatisch durch einen catkin_make install Befehl erstellt, der kaum verwendet wird und normalerweise nicht erstellt wird.
Hinweis: Der Workspace muss vor der Verwendung von catkin_make auf die oberste Ebene zurückgekehrt werden. (a) Die Existenz von Paketen unter demselben Workspace ist nicht zulässig; Das Paket mit demselben Namen ist in verschiedenen Workspaces erlaubt.
mkdir -p ~/catkin_ws/src # create
cd catkin_ws/ # enter the workspace
catkin_make # build
source devel/setup.bash # source the workspace environmentPakete
Package ist eine spezifische Dateistruktur und Ordnerkombination. Der Programmcode, der dieselbe Funktion erreicht, wird normalerweise in einem Paket platziert. Nur CMakeLists.txt und package.xml sind [erforderlich], und der Rest des Pfades hängt davon ab, ob das Paket benötigt wird.
Funktionspaket erstellen
cd ~/catkin_ws/src
catkin_create_pkg my_pkg rospy rosmsg roscpp[Rospy], [rosmsg], [roscpp] ist eine Abhängigkeitsbibliothek, die je nach Geschäftsanforderungen hinzugefügt werden kann, oder fügen Sie andere hinzu, ohne bei der Erstellung neu zu konfigurieren, wobei zu beachten ist, dass Ergänzungen konfiguriert werden müssen.
Dateistruktur
|-- CMakeLists.txt # (required) build rules for the current package.
|—— package.xml # (required) package metadata and ROS dependencies.
|—— include directory # stores C++ header files
|—— config directory # stores parameter files
|—— launch directory # stores launch files (.launch or .xml)
|—— meshes directory # stores robot or simulation 3D models (.sda, .stl, .dae, etc.)
|—— urdf directory # stores robot model descriptions (.urdf or .xacro)
|—— rviz directory # rviz files
|—— src directory # C++ source code
|—— scripts directory # executable scripts, such as shell scripts (.sh) and Python scripts (.py)
|—— srv directory # custom services
|—— msg directory # custom topics
|—— action directory # custom actionsEinführung in CMakeLists.txt
Allgemein
Die CMakeLists.txt war ursprünglich ein regelbasiertes Dokument für das CMake Build-System, während Catkin Builds weitgehend dem CMake-Stil der Builds folgten, aber einige Makrodefinitionen für das ROS-Projekt hinzufügten. Beim Schreiben ist Catkins CMakeLists.txt also grundsätzlich mit CMake identisch.
Dieses Dokument definiert direkt den Prozess, von dem das Paket abhängt, welche Ziele es kompiliert, wie es kompiliert wird usw. Daher ist CMakeLists.txt sehr wichtig, weil es die Regeln vom Quellcode zur Zieldatei festlegt, und die Catkin-Builds finden zuerst die CMakeLists.txt unter jedem Paket und kompilieren und bauen dann gemäß den Regeln.
Format
Die grundlegende Syntax von CMakeLists.txt ist dieselbe wie die von CMake, wobei Catkin eine kleine Anzahl von Makros hinzugefügt hat, wobei die Gesamtstruktur wie folgt ist:
Eine typische catkin CMakeLists.txt enthält diese Teile:
cmake_minimum_required(VERSION 3.0.2)
project(package_name)
find_package(catkin REQUIRED COMPONENTS roscpp rospy std_msgs)
catkin_package()
include_directories(${catkin_INCLUDE_DIRS})
add_executable(node_name src/node_name.cpp)
target_link_libraries(node_name ${catkin_LIBRARIES})Pakete, die benutzerdefinierte Nachrichten, Services oder Actions definieren, verwenden auch add_message_files(), add_service_files(), add_action_files() und generate_messages().
Boost aktiviert
Wenn Sie C++ und Boost verwenden, müssen Sie Find package() für Boost aufrufen und angeben, welche Aspekte von Boost als Komponenten verwendet werden. Wenn Sie beispielsweise den Boost-Thread verwenden möchten, würden Sie sagen:
Find package
catkin package()
Catkin package() ist ein CMake-Makro, das von catkin bereitgestellt wird. Dies ist notwendig, um catkin-spezifische Informationen für die Konstruktion des Systems zuzuweisen, die zur Generierung von pkg-config- und CMake-Dateien verwendet werden.
Diese Funktion muss aufgerufen werden, bevor ein Objekt mit add library() oder add executable() deklariert wird. Diese Funktion hat fünf optionale Parameter:
INCLUDE DIRS - Include-Pfade exportieren
LIBRARIES - Aus dem Projekt exportierte Bibliothek
CATKIN DEPENDS - Andere catkin-Projekte, auf denen das Projekt basiert
DEPENDS - Nicht-catkin CMake-Projekt, auf das sich das Projekt stützt. Zum besseren Verständnis sehen Sie sich diese Erklärung an.
CFG EXTRAS - Andere Konfigurationsoptionen
Die vollständige Makrodokumentation finden Sie hier.
Zum Beispiel:
catkin_package(
INCLUDE_DIRS include
LIBRARIES ${PROJECT_NAME}
CATKIN_DEPENDS roscpp nodelet
DEPENDS eigen opencv)Dies zeigt an, dass der Ordner "include" im Paketordner der Punkt ist, an dem die Header-Datei exportiert wird. Die CMake-Umgebungsvariable ${PROJECT_NAME} bewertet alles, was zuvor an die Funktion project() übergeben wurde, in diesem Fall wird es "robot brain" sein. "roscpp" + "nodelet" ist ein Softwarepaket, das vorhanden sein muss, um dieses Paket zu bauen/auszuführen, und "eigen" + "opencv" ist ein Systemabhängigkeitseintrag, der vorhanden sein muss, um dieses Paket zu bauen/auszuführen.
Include-Pfade und Bibliotheken
Bevor Sie ein Ziel angeben, müssen Sie den Speicherort angeben, an dem Ressourcen für das angegebene Ziel gefunden werden können, insbesondere Header-Dateien und Bibliotheken:
Includes-Pfad - wo die Header-Datei (am häufigsten C/C++) gefunden werden kann
Bibliothekspfad - Welche Bibliotheken befinden sich beim aktiven Ziel?
Include directories
link directories
Include directories()
Die Parameter für include directories sollten der find_package-Aufruf und jedes andere Verzeichnis sein, das eingeschlossen werden muss. Wenn Sie catkin und Boost verwenden, sollte Ihr include directories() wie folgt sein:
Include directories
Der erste Parameter "include" bedeutet, dass das include/-Verzeichnis im Paket auch Teil des Pfades ist.
link directories()
Beispiel:
link directories (~)
Die CMake-Funktion link directories() kann verwendet werden, um zusätzliche Bibliothekspfade hinzuzufügen, aber dies wird nicht empfohlen. Alle catkin- und CMake-Pakete fügen automatisch Link-Informationen zur Bibliothek in target_link_libraries() hinzu, wenn Sie find_package verwenden.
Siehe die Aufstellung bei cmake für ein detailliertes Beispiel zur Verwendung von target_link_libraries() in link directories().
Ausführbare Ziele
Um die ausführbare Datei anzugeben, die gebaut werden muss, müssen wir die CMake-Funktion add executable() verwenden.
edd executeableDies wird eine ausführbare Zieldatei namens MyProgram bauen, die aus drei Quelldateien gebaut wird: src/main.cpp, src/some_file.cpp und src/other_file.cpp.
Bibliotheksziele
Verwenden Sie add_library(), wenn das Paket ein wiederverwendbares Bibliotheksziel bauen muss. Viele einfache Tutorial-Pakete benötigen nur ausführbare Dateien.
add_library(${PROJECT_NAME} src/library_file.cpp)target_link_libraries
Verwenden Sie target_link_libraries() nach add_executable() oder add_library(), um das Ziel gegen catkin und andere erforderliche Bibliotheken zu linken.
target_link_libraries(node_name ${catkin_LIBRARIES})Beispiel:
(foo src/foo.cpp)
Add library (moo src/moo.cpp)
This links fly against libmoo.soBitte beachten Sie, dass in den meisten Fällen die Verwendung von link directories() nicht erforderlich ist, da Informationen automatisch durch find package() eingeführt werden.
Nachrichten, Services und Actions
Nachrichten- (.msg), Service- (.srv) und Action-Dateien (.action) erfordern einen speziellen Präprozessor-Builder, bevor ROS-Pakete konstruiert und verwendet werden. Die Schlüsselelemente dieser Makros sind die Generierung von programmiersprachenspezifischen Dokumenten, so dass sie Nachrichten, Services und Actions in der Programmiersprache ihrer Wahl verwenden können. Das Konstruktionssystem wird mit allen verfügbaren Generatoren (z.B. gencpp, genpy, genlisp, etc.) gebunden.
Drei Makros wurden bereitgestellt, um Nachrichten, Services und Actions separat zu behandeln:
add_message_files()
add_service_files()
add_action_files()
Diese Makros müssen vom resultierenden Makro gefolgt werden:
generate_messages()
Lesen Sie CMake Practice: https://github.com/Akagi201/learning-cmake/blob/master/docs/cmake-practice.pdf, wenn Sie noch nie Kontakt mit der Syntax von CMake hatten. Die Beherrschung von CMake ist sehr hilfreich für das Verständnis des ROS-Projekts.
Einführung in package.xml
Überblick
Die Paketliste ist eine XML-Datei im Stammordner namens package.xml, die jedes Kompatibilitätspaket enthalten muss. Package.xml ist auch ein erforderliches Paket für catkins Paket, eine Beschreibung des Pakets, die in einer früheren ROS-Version (Rosbuild-Build-System) "manifest.xml" genannt wird, um grundlegende Informationen über das Paket zu beschreiben. Wenn Sie einige ROS-Projekte im Internet sehen, die manifest.xml enthalten, ist es wahrscheinlich vor der Hydro-Version. Die package.xml enthält Informationen über den Namen, die Versionsnummer, die Beschreibung des Inhalts, das Wartungspersonal, Softwarelizenzen, Kompilierungskonstruktionswerkzeuge, Build-Abhängigkeit und Betriebsabhängigkeit des Pakets.
Package.xml-Dateien müssen message_generation enthalten, run_depend muss message_runtime enthalten.
Format
Eine typische package.xml enthält die Paket-Metadaten und Abhängigkeitsdeklarationen:
<package format="2">
<name>package_name</name>
<version>0.0.0</version>
<description>Package description</description>
<maintainer email="user@example.com">Maintainer Name</maintainer>
<license>BSD</license>
<buildtool_depend>catkin</buildtool_depend>
<depend>roscpp</depend>
<depend>rospy</depend>
<depend>std_msgs</depend>
</package>Abhängigkeitsbeziehungen
Die Liste der Pakete mit minimalen Labels gibt keine Abhängigkeit von anderen Paketen an. Das Paket hat sechs Abhängigkeiten:
Build-Abhängigkeit <build_depend> gibt das Paket an, das zum Bauen dieses Pakets benötigt wird. Dies ist der Fall, wenn Dateien in diesen Paketen für die Konstruktion erforderlich sind. Dies könnte die Header-Datei zum Zeitpunkt der Kompilierung, einen Link zur Bibliotheksdatei dieser Pakete oder andere für die Konstruktion benötigte Ressourcen umfassen (insbesondere wenn die Pakete in CMake mit find_package() gefunden werden). Im Cross-Kompilierungsszenario ist eine Abhängigkeitsbeziehung zur Zielsystemarchitektur strukturiert.
Build-Export-Abhängigkeit <build_export_depend> gibt das Paket an, das zum Bauen der Bibliothek für dieses Paket benötigt wird. Dies ist der Fall, wenn Sie diesen Header in die öffentliche Header-Datei in diesem Paket einbinden (insbesondere wenn das catkin-Paket in CMake deklariert ist (CATKIN_DEPENDS)).
Ausführungsabhängigkeit <exec_depend> gibt das Softwarepaket an, das zum Ausführen des Codes in diesem Paket erforderlich ist. Dies ist der Fall, wenn Sie auf die gemeinsam genutzte Bibliothek in diesem Paket angewiesen sind (insbesondere wenn Catkin_package() in CMake deklariert ist).
Testabhängigkeit <test_depend> gibt nur zusätzliche Abhängigkeiten für Unit-Tests an. Sie sollten keine bereits als Build- oder Ausführungsabhängigkeit erwähnten Abhängigkeiten duplizieren.
Build-Tool-Abhängigkeiten <buildtool_depend> geben an, dass dieses Paket sein eigenes Build-System-Tool bauen muss. Normalerweise ist der einzige Builder catkin. Im Cross-Kompilierungsszenario verlassen sich Konstruktionswerkzeuge auf Beziehungen zur Implementierung der Kompilierungsarchitektur.
Dokumenten-Tool-Abhängigkeit <doc_depend> gibt das Dokumenten-Tool an, mit dem das Paket das Dokument generiert.
Zusätzliche Tags
Zum Beispiel:
"Website"
Seed.
Workspace zur Vorbereitung offizieller Beispiele
Beachten Sie, dass ROS 1-Operationen in vorhandenen Docker-Containern durchgeführt werden müssen.
Nach dem Betreten des Docker-Containers laden Sie das offizielle ROS-Beispiel herunter (falls verfügbar):
git clone https://github.com/ros/ros_tutorials.git -b noetic-develDies ist ein Fall von ROS 1 basierend auf C++:
cd ros_tutorials/
mkdir src
cp roscpp_tutorials/ src/ -r
catkin_make # start buildingDie Kompilierung wurde wie folgt abgeschlossen:
Nach Abschluss der Kompilierung ist eine Initialisierung erforderlich, bevor der Workspace weiterverwendet werden kann:
source devel/setup.bashAbbildungen

# 7.2.1.3 Gängige Befehle und Werkzeuge
Methode zum Starten von Nodes
Launch-Dateien
Es gibt mindestens zwei Möglichkeiten, eine Launch-Datei mit dem roslaunch-Befehl zu starten:
- Start mit ROS-Paketpfad
Das Format ist wie folgt:
roslaunch package_name launch_file_name
roslaunch pkg_name launchfile_name.launch- Absoluter Pfad zur Launch-Datei
Das Format ist wie folgt:
roslaunch path_to_launchfileUnabhängig davon, wie Sie die Launch-Datei starten, können Sie Parameter hinten hinzufügen, die häufiger sind.
--screen: erleichtert das Debuggen der Informationen des ROS-Node (falls vorhanden), um sie auf dem Bildschirm auszugeben, anstatt sie in einer Protokolldatei zu speichern
arg:=value: Wenn die in der Launch-Datei anzugebende Variable angegeben wird, kann der Wert auf diese Weise angegeben werden, z.B.:
roslaunch pkg_name launchfile_name model:=urdf/myfile.urdf # the launch file has a `model` argument that must be setoder
roslaunch pkg_name launchfile_name model:='$(find urdf_pkg)/urdf/myfile.urdf' # use `find` to provide the pathDer roslaunch-Befehl wird ausgeführt, um zuerst zu erkennen, ob der rosmaster des Systems läuft oder, falls gestartet, den vorhandenen rosmaster zu verwenden; Wenn Sie nicht starten, können Sie zuerst den rosmaster starten, dann können Sie die Einstellungen in der Launch-Datei ausführen, und Sie können mehrere Nodes gemäß unserer Vorkonfiguration starten.
Es ist zu beachten, dass die Launch-Datei nicht kompiliert werden muss und wie oben beschrieben direkt ausgeführt werden kann.
rosrun
Der Node-Manager (Master) muss aktiviert sein, und Master wird für viele Prozesse im Verwaltungssystem verwendet, und jeder Node startet mit der Registrierung und Verwaltung der Kommunikation zwischen Node und Node. Nachdem der Master gestartet ist, geht er durch den Master, um jeden Node zu registrieren. Geben Sie den Befehl im Ubuntu-Terminal ein:
roscoreNode-Start, rosrun+Paketname+ Nodename; Die rosrun-Methode führt nur einen Node auf einmal aus.
rosrun [--prefix cmd] [--debug] pkg_name node_name [ARGS]Rosrun sucht nach einem ausführbaren Programm namens Package, das optionale ARGS einbringt.
Python
Wenn Python der Code ist, können Sie direkt unter dem Verzeichnis starten, in dem sich die py-Datei befindet, wobei Sie auf den Unterschied zwischen Python2 und Python3 achten müssen.
Eine kleine Schildkröte starten
roscore # start roscore in the first terminal
rosrun turtlesim turtlesim_node # start the turtlesim node in the second terminal
rosrun turtlesim turtle_teleop_key # start keyboard teleoperation in the third terminalNachdem der Start abgeschlossen ist, können Sie die Bewegung der kleinen Schildkröten über die Tastatureingabe manipulieren, und der Cursor muss die Bewegung der kleinen Schildkröten steuern, indem Sie auf die Tastatur [oben], [unten], [links], [rechts] unter dem Befehl von [rosrun turtlesim turtle_teleop_key] klicken.
Und das rosrun turtlesim turtlesim_node Terminal wird einige Protokolle der kleinen Schildkröte ausgeben.
[ INFO] [1607648666.226328691]: Starting turtlesim with node name /turtlesim
[ INFO] [1607648666.229275030]: Spawning turtle [turtle1] at x=[5.544445], y=[5.544445], theta=[0.000000]Start der zweiten Schildkröte
Im ersten Terminal starten Sie den Node über die Launch-Datei:
roslaunch turtle_tf turtle_tf_demo.launchHalten Sie den vorherigen Tastatursteuerungs-Node aktiv
An diesem Punkt treiben Sie die kleine Schildkrötenbewegung mit der Tastatur [oben], [unten], [links], [rechts] an; Eine kleine Schildkröte kann beobachtet werden, wie sie einer anderen Bewegung folgt.
Launch-Dateien
Allgemein
Ein Node-Programm in ROS führt normalerweise nur eine einzelne Funktion aus, aber ein vollständiger ROS-Roboter arbeitet typischerweise gleichzeitig mit vielen Node-Programmen und arbeitet miteinander zusammen, um komplexe Aufgaben auszuführen, und dies erfordert, dass viele Node-Programme beim Aktivieren eines Roboters gestartet werden, was mühsamer ist, wenn ein Node einzeln gestartet wird. Die Launch-Datei und der roslaunch-Befehl ermöglichen es, mehrere Nodes auf einmal zu aktivieren, erleichtern "One-Key" und setzen umfangreiche Parameter.
Format der Dokumentation
Die Launch-Datei ist im Wesentlichen eine XML-Datei, die in einigen Editoren hervorgehoben werden kann, lesbar, mit oder ohne Kopfzeile
Ähnlich wie andere Dateien im XML-Format werden Launch-Dateien durch Tags (tag) geschrieben, die Haupt-Tags sind wie folgt:
Code-Datei: 7-2-1-3-common-commands-and-tools-example-01.xml
<launch> <!-- root tag -->
<node> <!-- node and parameters to start -->
<include> <!-- include another launch file -->
<machine> <!-- target machine -->
<env-loader> <!-- set environment variables -->
<param> <!-- define a parameter on the parameter server -->
<rosparam> <!-- load YAML parameters into the parameter server -->
<arg> <!-- define an argument -->
<remap> <!-- set topic remapping -->
<group> <!-- set a group -->
</launch> <!-- root tag -->- Label [node]
Das Tag [node] ist der Kernbestandteil der Launch-Datei.
Code-Datei: 7-2-1-3-common-commands-and-tools-example-02.xml
<launch>
<node pkg="package_name" type="executable_file" name="node_name"/>
<node pkg="another_package" type="another_executable" name="another_node"></node>...
</launch>davon
pkg ist der Paketname des Nodes
type ist das ausführbare Dokument im Paket, das, wenn es mit Python vorbereitet wird, .py sein kann oder, wenn es mit C++ vorbereitet wird, der Name der ausführbaren Datei nach der Kompilierung der Quelldatei.
name ist der Name nach dem Start des Nodes, und jeder Node hat seinen eigenen eindeutigen Namen.
Hinweis: roslaunch kann die Startreihenfolge des Nodes nicht garantieren, daher sollten alle Nodes in der Launch-Datei möglichst unabhängig von der Startreihenfolge sein.
Weitere Parameter können wie folgt gesetzt werden:
Code-Datei: 7-2-1-3-common-commands-and-tools-example-03.xml
<launch>
<node
pkg=""
type=""
name=""
respawn="true"
required="true"
launch-prefix="xterm -e"
output="screen"
ns="namespace"
/>
</launch>In der obigen Reihenfolge,
respawn: Wenn dieser Node geschlossen wird, wird er automatisch neu gestartet?
required: Wenn dieser Node geschlossen wird, ob alle anderen Nodes geschlossen werden
launch-prefix: Ob ein neues Fenster zur Ausführung geöffnet werden soll. Zum Beispiel sollte ein neues Fenster für die Steuerung des Nodes geöffnet werden, wenn Roboterbewegungssteuerungen über Fenster erforderlich sind; Oder wenn ein Node einige Informationsausgaben hat, die nicht mit anderen Node-Informationen gemischt werden sollen.
output: Standardmäßig startet launch Node-Informationen in der folgenden Protokolldatei, die durch Setzen von Parametern hier auf dem Bildschirm angezeigt werden können
ns: Integrieren Sie den Node in einen anderen Namensraum, d.h. fügen Sie ein ns-Präfix vor dem Node-Namen hinzu. Um diese Art von Operation zu erreichen, werden Node-Name und Topic-Name in der Node-Quelldatei mit relativem Namen definiert, d.h. ohne Symbol /.
Der Name der Berechnungsquelle ist unterteilt in:
-
Basisname, z.B. topic
-
Globaler Name, z.B.: /A/topic
-
Relativer Name, z.B. A/topic
-
Private Namen, z.B. ~topic
Es gibt diese Codezeile zum Zeitpunkt der Veröffentlichung oder Buchung.
ros::init(argc, argv, "publish_node");
ros::NodeHandle nh;
ros::Publisher pub = nh.advertise<std_msgs::string>("topic",1000);- Label [remap]
Erscheint oft als Sub-Label für ein Node-Label, um Topic zu ändern. In vielen rosnode-Dateien wurde das empfangende oder sendende Topic möglicherweise nicht angegeben, sondern nur durch input topic und output topic ersetzt, so dass abstrakte Topic-Namen anstelle von Topic-Namen in bestimmten Szenen verwendet werden.
Kurz gesagt, die Funktion von remap besteht darin, die Anwendung derselben Node-Datei in einer anderen Umgebung zu erleichtern, indem remap topic von außen verwendet wird, ohne die Quelldatei zu ändern.
Gängige Verwendungsformate für remap sind wie folgt:
Code-Datei: 7-2-1-3-common-commands-and-tools-example-04.xml
<node pkg="some" type="some" name="some">
<remap from="origin" to="new" />
</node>- Include
Dieses Label wird verwendet, um eine weitere Launch-Datei zu dieser Launch-Datei hinzuzufügen, ähnlich der Launch-Datei-Verschachtelung. Grundformat:
Der oberste Dateipfad kann als spezifischer Pfad angegeben werden, aber im Allgemeinen ist es für die Programmportabilität am besten, den Dateipfad mit einem find-Befehl anzugeben:
Für den obigen Befehl ist der Wert von $(find package-name) gleich dem Pfad des entsprechenden Pakets in diesem Computer. Dies ermöglicht es, den entsprechenden Pfad auch dann zu finden, wenn der andere Master durch dasselbe Paket ersetzt wird.
Manchmal benötigt ein anderer durch launch eingeführter Node möglicherweise einen einheitlichen Namen oder einen Node-Namen mit ähnlichen Eigenschaften, wie /my/gps, /my/lidar, /my/imu, oder Node hat ein einheitliches Präfix, das leicht zu suchen ist. Dies kann durch Setzen der ns (Namensraum) Eigenschaften erreicht werden, mit den folgenden Befehlen:
- Label
Wiederholung von Parametern durch [arg] ist möglich und kann an mehreren Stellen leicht geändert werden. Drei gängige Methoden:
Wertzuweisung über die Befehlszeile
roslaunch pack_name file_name.launch arg1:=value1 arg2:=value2
- Ersetzung von Variablen
Es gibt zwei häufig verwendete Variablenersetzungen in Launch-Dateien
$(find pkg): zum Beispiel $(find rospy)/manifest.xml. Paketbasierte Pfade werden nach Möglichkeit dringend empfohlen.
$(arg arg_name): setzt einen Standardwert; verwenden Sie ihn, wenn keine Überschreibung bereitgestellt wird
Zum Beispiel:
Code-Datei: 7-2-1-3-common-commands-and-tools-manifest.xml
<arg name="gui" default="true" />
<!-- set a default value; use it when no override is provided -->
<param name="use_gui" value="$(arg gui)"/>Ein weiteres Beispiel:
<node pkg="package_name" type="executable_file" name="node_name" args="$(arg a) $(arg b)" />Nach dem Setzen kann dieser Wert den args-Parametern beim Start von roslaunch übergeben werden
roslaunch package_name file_name.launch a:=1 b:=5- Label
Im Gegensatz zu [arg] ist [param] gemeinsam genutzt, und sein Wert ist nicht auf value beschränkt, es kann eine Datei sein, sogar eine Befehlszeile.
Format
Code-Datei: 7-2-1-3-common-commands-and-tools-example-06.xml
<param name="param_name" type="type1" value="val"/> # type can be omitted; ROS infers it
<param name="param_name" textfile="$(find pkg)/path/file"/> # read file content as a string
<param name="param_name" command="$(find pkg)/exe '$(find pkg)/arg.txt'"/>
Example:
<param name="param" type="yaml" command="cat '$(find pkg)/*.yaml'"/> # store command output in the parameter[Param] kann im globalen Kontext sein, sein Name ist der ursprüngliche Name, oder in einem kleineren Bereich, wie Node, und sein Gesamtname ist node/param.
Zum Beispiel, im globalen Kontext, definieren Sie wie folgt:
<param name="publish_frequency" type="double" value="10.0" />Definieren Sie Folgendes im Node-Bereich
Code-Datei: 7-2-1-3-common-commands-and-tools-example-07.xml
<node name="node1" pkg="pkg1" type="exe1">
<param name="param1" value="False"/>
</node>Wenn Sie [param] mit rosparam list auflisten, ja
/publish_frequency
/node1/param1 # namespace prefix is added automaticallyHinweis: Obwohl der Namensraum zum Namen [param] hinzugefügt wurde, ist er immer noch global.
[Rosparam]
[Param] kann nur auf ein einzelnes [Param] operieren und nur in drei Formen: value, textfile, command, gibt einzelnen [Param] Inhalt zurück. [Rosparam] ermöglicht Batch-Operationen und enthält Befehle für Parametereinstellungen, z.B. dump, delete, etc.
load: Laden Sie eine Reihe von params aus der YAML-Datei im folgenden Format:
<rosparam command="load" file="$(find rosparam)/example.yaml" />Delete: Löschen Sie einige param
<rosparam command="delete" param="my_param" />[param]-ähnliche Zuweisungsoperation
<rosparam param="my_param">[1,2,3,4]</rosparam>Oder...
Code-Datei: 7-2-1-3-common-commands-and-tools-example-08.xml
<rosparam>
a: 1
b: 2
</rosparam>[Rosparam] kann auch in [node] platziert werden, an diesem Punkt Node-Namensraum.
- Group
Wenn Sie dieselbe Einrichtung für mehrere Nodes wünschen, zum Beispiel im selben Namensraum, dasselbe Topic remappen, können Sie [group] verwenden. Alle gängigen Labels können in [group] verwendet werden, zum Beispiel
Code-Datei: 7-2-1-3-common-commands-and-tools-example-09.xml
<group ns="rosbot">
<remap from="chatter" to="talker"/> # applies to following nodes in this group
<node... />
<node... >
<remap from="chatter" to="talker1"/> # each node can override the remap
</node>
</group>TF-Koordinatentransformation
tf ist ein Paket, das es Benutzern ermöglicht, mehrere Koordinatensysteme jederzeit zu verfolgen. tf verwaltet die Beziehung zwischen den Koordinaten in der Struktur eines Echtzeitpuffers und ermöglicht es Benutzern, Punkte, Vektoren usw. zu jedem Zeitpunkt zwischen zwei beliebigen Frames zu konvertieren.
Das Tf-Paket ist dasjenige, das die Koordinaten eines Punktes in einem Koordinatensystem in die Koordinaten eines anderen umwandelt. Der Sensor kann ein Koordinatensystem sehen, die Maschine kann ein Koordinatensystem sehen und das Hindernis kann einen Punkt sehen.
Nach der Aktivierung von zwei kleinen Schildkröten führen Sie die folgenden Operationen aus.
tf gängige Werkzeuge
- View frames Werkzeug
Es ist in der Lage, alle tf-Koordinaten zu erfassen, die derzeit über ROS gesendet werden, und Baumdiagramme zu zeichnen, um die Verbindung zwischen den Koordinaten anzuzeigen, wobei eine Datei namens frame.pdf generiert und an ihrer aktuellen lokalen Position gespeichert wird.
rosrun tf view_frames- rqt_tf_tree Werkzeug
Obwohl view_frames die aktuelle Koordinatenbeziehung in einer Offline-Datei speichern kann, kann es die Koordinatenbeziehung nicht in Echtzeit widerspiegeln, daher ist es möglich, die Koordinatenbeziehung in Echtzeit mit rqt_tf_tree zu aktualisieren
rosrun rqt_tf_tree rqt_tf_tree- tf_echo Werkzeug
Mit dem tf_echo Werkzeug können Sie die Beziehung zwischen den beiden Referenzsystemen sehen.
rosrun tf tf_echo <source_frame> <target_frame>Gibt die Rotationstransformation vom Quell-Frame zum Ziel-Frame aus; Zum Beispiel:
rosrun tf tf_echo turtle1 turtle2- Static transform publisher
Veröffentlicht statische Koordinaten zwischen den beiden Koordinaten, die ihre relativen Positionen nicht ändern. Befehlsformat:
static_transform_publisher x y z yaw pitch roll frame_id child_frame_id period_in_ms
static_transform_publisher x y z qx qy qz qw frame_id child_frame_id period_in_msVerwendung in launch:
Code-Datei: 7-2-1-3-common-commands-and-tools-example-10.xml
<launch>
<node pkg="tf" type="static_transform_publisher" name="link1_broadcaster" args="1 0 0 0 0 0 1 link1_parent link1 100" />
</launch>- Roswtf Plugin
Ein Plugin, um Ihre aktuelle tf-Konfiguration zu analysieren und zu versuchen, häufige Probleme zu identifizieren.
roswtfGängige Koordinatensysteme
Die üblichen Koordinaten sind die frame_id, mit map, odom, base_link, base_footprint, base_laser, etc.
Weltkoordinate (map)
Die Map-Koordinaten sind ein festes Koordinatensystem der Welt mit einer Z-Achse, die nach oben zeigt. Die Haltung der mobilen Plattform gegenüber dem Map-System sollte sich im Laufe der Zeit nicht wesentlich bewegen. Map-Koordinaten sind nicht kontinuierlich, was bedeutet, dass die Haltung der sich bewegenden Plattform im Map-System jederzeit getrennt werden kann. Typische Einstellungen: Positionierungsmodule basieren auf Sensorüberwachung und berechnen ständig die Position von Robotern in Weltkoordinaten neu, wodurch Abweichungen beseitigt werden, aber sie können springen, wenn neue Sensorinformationen eintreffen. Map-Koordinaten sind als langfristige globale Referenz nützlich, aber Sprünge machen sie zu einer schlechten Referenz für lokale Sensoren und Wahrnehmung.
odom
Odom ist ein globales Koordinatensystem, das die aktuelle Bewegungshaltung des Roboters durch einen Kilometerzähler aufzeichnet. Die Position der sich bewegenden Plattform in den odom-Koordinaten kann sich frei ohne Grenzen bewegen, was verhindert, dass die odom-Koordinaten als langfristige globale Referenz dienen. Dies dient zur Unterscheidung zwischen den Konzepten von Koordinaten und Kilometerstand, die auf der Grundlage von Encoder (oder visuell etc.) berechnet werden. Aber es gibt auch eine Beziehung, und die odom-Topic-Transformationsmatrix ist die tf-Beziehung von odom->base_link. Die odom- und map-Koordinaten fallen zu Beginn der Roboterbewegung zusammen. Im Laufe der Zeit gibt es jedoch keine Überlappung, und die Abweichung ist der kumulative Fehler des Kilometerzählers. Eine Positionsschätzung (Lokalisierung) wird in einigen Korrekturpaketen wie amcl angegeben, die durch die tf von Map->base_link erhalten werden kann, so dass der Unterschied zwischen der Position und der Kilometerstandposition der Unterschied zwischen den Koordinaten von odom und Map ist. Wenn Ihre odom-Berechnung nicht falsch ist, ist die map->odom tf null. Das odom-Koordinatensystem ist als kurzfristige lokale Referenz nützlich, aber die Abweichung verhindert, dass es eine langfristige Referenz ist.
Basiskoordinaten (base_link)
Das Roboter-Heimsystem (Matrix) Koordinaten überlappen mit dem Roboterzentrum, das typischerweise das Zentrum der Roboterrotation ist.
Base_footprint: Ursprung ist die Projektion des base_link-Ursprungs auf den Boden, mit einem gewissen Unterschied (z-Werte).
Beziehung zwischen Koordinaten
In Robotersystemen verwenden wir einen Baum, um alle Koordinaten zu verbinden, so dass jede eine väterliche und zufällige Unterkoordinate hat, wie folgt: Map-> odom-> base_link-Weltkoordinate ist der Vater der odom-Koordinate und odom-Koordinate ist der Vater von base_link. Obwohl, intuitiv, Map und odom mit base_link verbunden sein sollten, ist dies nicht zulässig, da nur ein Elternteil in jedem System gefunden werden kann.
Koordinatensystem-Berechtigungen
Die Konvertierung von odom zu base_link wird von der Kilometerzählerquelle berechnet und veröffentlicht. Das Lokalisierungsmodul veröffentlicht jedoch nicht die Transformation von Map zu base_link. Stattdessen empfängt das Lokalisierungsmodul die Transformation von odom zu base_link und verwendet diese Informationen, um die Transformation von map zu odom zu veröffentlichen.
rqt (QT-Tool)
Öffnen Sie das Befehlszeilenfenster und geben Sie rosrun rqt ein und doppelklicken Sie auf die Tab-Taste, um anzuzeigen, was im QT-Tool in ROS enthalten ist, wie in der folgenden Abbildung dargestellt:
Nehmen wir also das Beispiel der kleinen Schildkröten und geben eine kurze Einführung in einige der verwendeten QT-Tools:
- rqt_graph Rechnervisualisierung
Öffnen Sie das Befehlszeilenfenster und geben Sie den folgenden Befehl ein, woraufhin ein Dialogfenster erscheint.
rosrun rqt_graph rqt_graph
Aus den Bildern ist klar ersichtlich, dass der /teleop_turtle Node über das /turtle1/cmd_vel Topic an den /turtlesim Node übertragen wird.
/teleop_turtle ist der Node mit Publisher-Funktion.
/turtlesim ist der Node mit Subscriber-Funktion.
Dieser Beitrag ist Teil unserer Sonderberichterstattung Sambia.
- rqt_topic Topics anzeigen
rosrun rqt_topic rqt_topic
Durch dieses Tool können wir einige Echtzeitinformationen über Änderungen der kleinen Schildkröten klar erkennen.
- rqt_publisher
rqt_publisher bietet ein GUI-Plugin, um jede Nachricht mit festen oder berechneten Feldwerten zu veröffentlichen. Öffnen Sie das Befehlszeilenfenster und geben Sie den folgenden Befehl ein, woraufhin ein Dialogfenster erscheint.
rosrun rqt_publisher rqt_publisherKlicken Sie auf das Auswahlfeld rechts von Topic, um das benötigte /turtle1/cmd_vel Topic zu finden und klicken Sie rechts, um die Nummer wie folgt hinzuzufügen:
- rqt_plot Datenvisualisierung
Die Referenzanweisungen sind wie folgt:
rosrun rqt_plot rqt_plot- rqt_console Protokollausgabe
Das RS Log (log) System funktioniert, um Protokollnachrichten zu generieren, die auf dem Bildschirm angezeigt, an ein bestimmtes Topic gesendet oder in einer bestimmten Protokolldatei gespeichert werden, um Debugging, Aufzeichnung, Alarmierung usw. zu erleichtern.
Die Protokollnachricht in ROS kann je nach Schweregrad in 5 Stufen unterteilt werden: DEBUG, INFO, WARN, ERROR, FATAL. Solange das Programm ausgeführt werden kann, muss keine Aufmerksamkeit geschenkt werden, aber das Vorhandensein von ERROR und FATAL zeigt an, dass es ernsthafte Probleme mit dem Programm gibt, die es unmöglich machen, es auszuführen.
rosrun rqt_console rqt_consoleDas Protokollausgabe-Tool ist Teil des ROS-Logging-Frameworks, das Ausgabeinformationen für Nodes anzeigt, und wir können auf der Karte sehen, dass die Schildkröte gegen die Wand gestoßen ist.
Gängige API
- rqt_reconfigure Dynamische Parameterkonfiguration
Die Referenzanweisungen sind wie folgt:
rosrun rqt_reconfigure rqt_reconfigureBildquelle ROS Wiki:
Rviz
rviz ist ein grafisches Tool, das das ROS-Programm einfach grafisch ausführen kann. Es ist auch einfacher zu bedienen.
[Set initial pose], [Set target pose]
Die rviz-Oberfläche besteht hauptsächlich aus:
1: 3D-Ansichtsbereich zur visuellen Anzeige von Daten, der derzeit nicht verfügbar und daher schwarz ist.
2: Werkzeugleiste, die Werkzeuge wie Perspektivensteuerung, Zielsetzung, Verteilungsposition usw. bereitstellt.
3: Zeigt eine Liste von Elementen an, um das aktuell ausgewählte Anzeige-Plugin anzuzeigen, das die Eigenschaften jedes Plugins konfigurieren kann.
4: Perspektiveinstellung, mit mehreren verfügbaren Beobachtungsoptionen.
5: Zeitanzeigebereich, der die aktuelle Systemzeit und ROS-Zeit anzeigt.
Display hinzufügen
Schritt 1: Klicken Sie auf die Schaltfläche [Add]. Ein Feld wird angezeigt.
Schritt 2: Fügen Sie nach Anzeigetyp [By display type] hinzu, obwohl die Koordinaten nur angezeigt werden können, wenn sie das entsprechende Topic ändern; Sie können auch direkt hinzufügen, indem Sie das Topic [By topic] auswählen, damit Sie es ordnungsgemäß anzeigen können.
Schritt 3: Klicken Sie auf [OK].
Gängige ROS-Befehle
Abbildungen












# 7.2.1.4 Publisher
Publisher
Der Publisher fungiert per Definition als Herausgeber. Diese Nachricht, die von der unteren Maschine mit den Sensorinformationen auf der Maschine gesendet werden könnte, wurde dann verpackt und an den Subscriber des Topics gesendet; Es könnte auch möglich sein, die Daten auf dem Gerät zu berechnen und sie zu verpacken und an den Subscriber zu senden, der das Topic abonniert hat.
Erstellung von Workspace und Topic-Paket
Erstellung von Workspaces
mkdir -p ~/catkin_ws/src
cd ~/catkin_ws/src
catkin_init_workspaceKompilierung des Workspace
cd ~/catkin_ws/
catkin_makeUmgebungsvariablen aktualisieren
source devel/setup.bashÜberprüfung der Umgebungsvariablen
echo $ROS_PACKAGE_PATHPakete erstellen
cd ~/catkin_ws/src
catkin_create_pkg learning_topic std_msgs rospy roscpp geometry_msgs turtlesimErläuterung: learning_topic ist der Name des Funktionskits
Pakete bauen
cd ~/catkin_ws
catkin_make
source ~/catkin_ws/devel/setup.bashEinen Publisher erstellen
Erstellungsschritte
-
Initialisierung der ROS-Nodes
-
Handles erstellen
-
Registrierung der Node-Informationen beim ROS Master, einschließlich Name und Typ der veröffentlichten Informationen sowie der Länge der Warteschlange
-
Nachrichtendaten erstellen und initialisieren
-
Nachricht in einer bestimmten Frequenz in einer Schleife veröffentlichen
C++ Implementierung
- Erstellen Sie eine C++-Datei (Datei mit der Endung .cpp) im src-Ordner des Pakets namens turtle_velocity_publisher.cpp (vim Grundlagen: 14 mit Vim-Editor)
touch turtle_velocity_publisher.cpp # create the file
vim turtle_velocity_publisher.cpp # edit the file- Kopieren Sie den folgenden Programmcode in die Datei turtle_velocity_publisher.cpp
Code-Datei: 7-2-1-4-publisher-turtle_velocity_publisher.cpp
/*Create a turtlesim velocity publisher.*/
#include <ros/ros.h>
#include <geometry_msgs/Twist.h>
int main(int argc, char **argv){
ros::init(argc, argv, "turtle_velocity_publisher");//Initialize the ROS node.
ros::NodeHandle n;//Create a node handle.
//Create a publisher for /turtle1/cmd_vel with geometry_msgs::Twist messages and queue size 10.
ros::Publisher turtle_vel_pub = n.advertise<geometry_msgs::Twist>("/turtle1/cmd_vel", 10);
ros::Rate loop_rate(10);//Set the loop rate.
while (ros::ok()){
//Initialize a message with the same type as the publisher.
geometry_msgs::Twist turtle_vel_msg;
turtle_vel_msg.linear.x = 0.8;
turtle_vel_msg.angular.z = 0.6;
turtle_vel_pub.publish(turtle_vel_msg);// Publish the velocity message.
//Print the published velocity.
ROS_INFO("Publsh turtle velocity command[%0.2f m/s, %0.2f rad/s]", turtle_vel_msg.linear.x, turtle_vel_msg.angular.z);
loop_rate.sleep();//Sleep according to the loop rate.
}
return 0;
}Die bearbeitete Projektverzeichnisstruktur ist wie folgt:
catkin_ws/
├── CMakeLists.txt
└── src/
├── CMakeLists.txt
└── learning_topic/
├── CMakeLists.txt
├── package.xml
└── src/
└── turtle_velocity_publisher.cpp-
Flussdiagramm des Programms, das dem Inhalt von 1.3.1 entspricht
-
Fügen Sie in catkin_ws/src/learning_topic/CMakeLists.txt unter dem Build-Bereich Folgendes hinzu:
(vim Grundlagen: 14 mit Vim-Editor)
Code-Datei: 7-2-1-4-publisher-example-02.cmake
add_executable(turtle_velocity_publisher src/turtle_velocity_publisher.cpp)
target_link_libraries(turtle_velocity_publisher ${catkin_LIBRARIES})Achten Sie darauf, die CMakeLists.txt im richtigen Pfad zu ändern
- Kompilieren Sie den Code im Workspace-Verzeichnis neu
cd ~/catkin_ws
catkin_make
source devel/setup.bash # source the workspace so ROS can find the programProgramm ausführen
Öffnen Sie das erste Terminal und führen Sie roscore aus:
roscoreFühren Sie den Little-Turtle-Node aus
rosrun turtlesim turtlesim_nodeFühren Sie den Publisher aus, der kontinuierlich Geschwindigkeit an die Schildkröte sendet.
rosrun learning_topic turtle_velocity_publisher-
Erwartetes Ergebnis
-
Beschreibung des Programmablaufs
Wenn Sie die Liste der Topics im Terminal eingeben, finden Sie das Topic /turtle1/cmd_vel.
Wir werden es mit rostopic info /turtle1/cmd_vel herausfinden
Dies bedeutet, dass die Schildkröte ein Subscriber des Geschwindigkeits-Topics /turtle1/cmd_vel ist, so dass der Publisher kontinuierlich Geschwindigkeitsdaten sendet und wenn die Schildkröten sie empfangen, beginnen sie sich mit dieser Geschwindigkeit zu bewegen.
Python Implementierung
-
Erstellen Sie unter dem Paketverzeichnis einen neuen Ordner scripts und dann eine neue Python-Datei (Datei mit der Endung .py) im scripts-Ordner namens turtle_velocity_publisher.py
-
Kopieren Sie den folgenden Programmcode in die Datei turtle_velocity_publisher.py
Code-Datei: 7-2-1-4-publisher-suffix.py
#!/usr/bin/env python3
import rospy
from geometry_msgs.msg import Twist
def turtle_velocity_publisher():
rospy.init_node('turtle_velocity_publisher', anonymous=True) # Initialize the ROS node.
# Create a turtlesim velocity publisher on /turtle1/cmd_vel. The message type is geometry_msgs/Twist and the queue size is 8.
turtle_vel_pub = rospy.Publisher('/turtle1/cmd_vel', Twist, queue_size=8)
rate = rospy.Rate(10) # Set the loop rate.
while not rospy.is_shutdown():
# Initialize a geometry_msgs::Twist message.
turtle_vel_msg = Twist()
turtle_vel_msg.linear.x = 0.8
turtle_vel_msg.angular.z = 0.6
# Publish the message.
turtle_vel_pub.publish(turtle_vel_msg)
rospy.loginfo("linear is:%0.2f m/s, angular is:%0.2f rad/s",
turtle_vel_msg.linear.x, turtle_vel_msg.angular.z)
rate.sleep()# Sleep according to the loop rate.
if __name__ == '__main__':
try:
turtle_velocity_publisher()
except rospy.ROSInterruptException:
pass-
PROJEKT-Flussdiagramm
-
Programm ausführen
Öffnen Sie das erste Terminal und führen Sie roscore aus
roscoreFühren Sie den Little-Turtle-Node aus
rosrun turtlesim turtlesim_nodeFühren Sie den Publisher aus, der kontinuierlich Geschwindigkeit an die Schildkröte sendet.
rosrun learning_topic turtle_velocity_publisher.pyHinweis: Vor der Ausführung muss der Datei turtle_velocity_publisher.py eine Ausführungsberechtigung hinzugefügt werden. Öffnen Sie das Terminal im Ordner turtle_velocity_publisher.py.
sudo chmod a+x turtle_velocity_publisher.pyAlle Python-Dateien benötigen Ausführungsberechtigungen, sonst gibt es Fehler!
Abbildungen






7.2.1.5 Subscriber
Subscriber
Subscriber empfangen die vom Publisher veröffentlichten Daten und treten dann in ihre Callback-Funktion ein, wo die empfangenen Daten verarbeitet werden. Der Kerninhalt ist eine Callback-Funktion, und jeder Subscriber abonniert das Topic.
Einen Subscriber erstellen
Erstellungsschritte
-
Initialisierung der ROS-Nodes
-
Handles erstellen
-
Topics zum Abonnieren
-
Topic-Nachricht in einer Schleife empfangen und an die Callback-Funktion zurückgeben
-
Nachrichtenverarbeitung in einer Callback-Funktion abschließen
Der Workspace dieses Kapitels folgt dem in Abschnitt IV erstellten Workspace.
C++ Implementierung
-
Erstellen Sie eine neue C++-Datei im src-Ordner des erstellten Pakets unter dem Tutorial-Verzeichnis 'publishing' namens turtle_pose_subscriber.cpp
-
Kopieren Sie den folgenden Programmcode in die Datei turtle_pose_subscriber.cpp
Code-Datei: 7-2-1-5-subscriber-subscriber.cpp
/*Create a subscriber for the current turtlesim pose.*/
#include <ros/ros.h>
#include "turtlesim/Pose.h"
// The callback runs when a subscribed message is received.
void turtle_poseCallback(const turtlesim::Pose::ConstPtr& msg){
// Print the received message.
ROS_INFO("Turtle pose: x:%0.3f, y:%0.3f", msg->x, msg->y);
}
int main(int argc, char **argv){
ros::init(argc, argv, "turtle_pose_subscriber");// Initialize the ROS node.
ros::NodeHandle n;//Create a node handle.
// Create a subscriber for /turtle1/pose and register poseCallback.
ros::Subscriber pose_sub = n.subscribe("/turtle1/pose", 10, turtle_poseCallback);
ros::spin(); // Wait for callbacks.
return 0;
}catkin_ws/
├── CMakeLists.txt
└── src/
├── CMakeLists.txt
└── learning_topic/
├── CMakeLists.txt
├── package.xml
└── src/
└── turtle_velocity_publisher.cpp
└── turtle_pose_subscriber.cpp-
Flussdiagramm des Programms, das dem Inhalt von 5.2.1 entspricht
-
Fügen Sie in catkin_ws/src/learning_topic/CMakeLists.txt unter dem Build-Bereich Folgendes hinzu:
(vim Grundlagen: 14 mit Vim-Editor)
Add executeable (turtle pose subscriber src/turtle_pose_subscriber.cpp)
{\cHFFFFFF}{\cH00FFFF}- Code im Workspace-Verzeichnis kompilieren
cd ~/catkin_ws
catkin_make
source devel/setup.bash # source the workspace so ROS can find the programProgramm ausführen
Öffnen Sie das erste Terminal und führen Sie roscore aus
roscoreDas zweite Terminal führt den Schildkröten-Node aus.
rosrun turtlesim turtlesim_nodeDas dritte Terminal führt den Abonnement-Node aus und empfängt kontinuierlich Daten über die Zustellposition der Schildkröten
rosrun learning_topic turtle_pose_subscriber- Beschreibung des Programmablaufs
Nach dem Ausführen des Nodes der kleinen Schildkröte senden die Schildkröten kontinuierlich ihre Positionsnachrichten, und das Topic ist
/turtle1/pose
Und wenn es ausgeführt wird, empfängt es Datennachrichten, die von Schildkröten gesendet werden, und gibt sie dann in der Echo-Funktion aus.
Python Implementierung
-
Erstellen Sie unter dem Paketverzeichnis einen neuen Ordner scripts und dann eine neue Python-Datei (Datei mit der Endung .py) im scripts-Ordner namens turtle_pose_subscriber.py
-
Kopieren Sie den folgenden Programmcode in die Datei turtle_pose_subscriber.py
Code-Datei: 7-2-1-5-subscriber-suffix.py
#!/usr/bin/env python3
import rospy
from turtlesim.msg import Pose
def poseCallback(msg):
rospy.loginfo("Turtle pose: x:%0.3f, y:%0.3f", msg.x, msg.y)
def turtle_pose_subscriber():
rospy.init_node('turtle_pose_subscriber', anonymous=True)# Initialize the ROS node.
# Create a subscriber for /turtle1/pose and register poseCallback.
rospy.Subscriber("/turtle1/pose", Pose, poseCallback)
rospy.spin()# Wait for callbacks.
if __name__ == '__main__':
turtle_pose_subscriber()-
PROJEKT-Flussdiagramm
-
Programm ausführen
Führen Sie roscore aus
roscoreFühren Sie den Little-Turtle-Node aus
rosrun turtlesim turtlesim_nodeFühren Sie den Subscriber aus und empfangen Sie kontinuierlich Daten über die Zustellposition der Schildkröte
rosrun learning_topic turtle_pose_subscriber.pyAbbildungen




# 7.2.1.6 Benutzerdefinierte Topic-Nachrichten und Verwendung
Führen Sie die Befehle im ROS 1 Noetic Docker-Container aus, der in 7.2.1.1 Einführung in ROS 1 beschrieben ist.
Dieser Abschnitt erstellt und verwendet eine benutzerdefinierte Topic-Nachricht namens Information.msg. Das Beispiel setzt das zuvor erstellte learning_topic-Paket fort.
Die Nachrichtendatei erstellen
Erstellen Sie das msg-Verzeichnis und definieren Sie die benutzerdefinierte Nachricht:
cd ~/catkin_ws/src/learning_topic
mkdir -p msg
vim msg/Information.msgCode-Datei: 7-2-1-6-custom-topic-messages-and-usage-Information.msg
string company
string citypackage.xml aktualisieren
Fügen Sie Nachrichtengenerierungs-/Laufzeitabhängigkeiten zu package.xml hinzu:
<build_depend>message_generation</build_depend>
<exec_depend>message_runtime</exec_depend>CMakeLists.txt aktualisieren
Fügen Sie die Nachrichtengenerierung zu CMakeLists.txt hinzu:
find_package(catkin REQUIRED COMPONENTS
roscpp
rospy
std_msgs
message_generation
)
add_message_files(
FILES
Information.msg
)
generate_messages(
DEPENDENCIES
std_msgs
)
catkin_package(
CATKIN_DEPENDS message_runtime
)Bauen Sie den Workspace:
cd ~/catkin_ws
catkin_make
source devel/setup.bashC++ Publisher und Subscriber
Erstellen Sie die folgenden Dateien unter ~/catkin_ws/src/learning_topic/src.
Code-Datei: 7-2-1-6-custom-topic-messages-and-usage-Information_publisher.cpp
/**
* Publish /company_info with the custom learning_topic::Information message type.
*/
#include <ros/ros.h>
#include "learning_topic/Information.h"
int main(int argc, char **argv)
{
ros::init(argc, argv, "company_information_publisher");
ros::NodeHandle nh;
ros::Publisher info_pub = nh.advertise<learning_topic::Information>("/company_info", 10);
ros::Rate loop_rate(1);
while (ros::ok())
{
learning_topic::Information info_msg;
info_msg.company = "Seeed";
info_msg.city = "Shenzhen";
info_pub.publish(info_msg);
ROS_INFO("Information: company:%s city:%s", info_msg.company.c_str(), info_msg.city.c_str());
loop_rate.sleep();
}
return 0;
}Code-Datei: 7-2-1-6-custom-topic-messages-and-usage-Information_subscriber.cpp
/**
* Subscribe to /company_info with the custom learning_topic::Information message type.
*/
#include <ros/ros.h>
#include "learning_topic/Information.h"
void companyInfoCallback(const learning_topic::Information::ConstPtr& msg)
{
ROS_INFO("Company: %s, city: %s", msg->company.c_str(), msg->city.c_str());
}
int main(int argc, char **argv)
{
ros::init(argc, argv, "company_information_subscriber");
ros::NodeHandle nh;
ros::Subscriber sub = nh.subscribe("/company_info", 10, companyInfoCallback);
ros::spin();
return 0;
}Fügen Sie die ausführbaren Dateien zu CMakeLists.txt hinzu:
add_executable(Information_publisher src/Information_publisher.cpp)
target_link_libraries(Information_publisher ${catkin_LIBRARIES})
add_dependencies(Information_publisher ${PROJECT_NAME}_generate_messages_cpp)
add_executable(Information_subscriber src/Information_subscriber.cpp)
target_link_libraries(Information_subscriber ${catkin_LIBRARIES})
add_dependencies(Information_subscriber ${PROJECT_NAME}_generate_messages_cpp)Bauen und ausführen:
cd ~/catkin_ws
catkin_make
source devel/setup.bash
roscore
rosrun learning_topic Information_publisher
rosrun learning_topic Information_subscriberPython Publisher und Subscriber
Erstellen Sie die folgenden Dateien unter ~/catkin_ws/src/learning_topic/scripts und machen Sie sie dann ausführbar.
Code-Datei: 7-2-1-6-custom-topic-messages-and-usage-Information_publisher.py
#!/usr/bin/env python3
import rospy
from learning_topic.msg import Information
def information_publisher():
rospy.init_node('information_publisher', anonymous=True)
info_pub = rospy.Publisher('/company_info', Information, queue_size=10)
rate = rospy.Rate(1)
while not rospy.is_shutdown():
info_msg = Information()
info_msg.company = 'Seeed'
info_msg.city = 'Shenzhen'
info_pub.publish(info_msg)
rospy.loginfo('Information: company:%s city:%s', info_msg.company, info_msg.city)
rate.sleep()
if __name__ == '__main__':
information_publisher()Code-Datei: 7-2-1-6-custom-topic-messages-and-usage-Information_subscriber.py
#!/usr/bin/env python3
import rospy
from learning_topic.msg import Information
def company_info_callback(msg):
rospy.loginfo('Company: %s, city: %s', msg.company, msg.city)
def information_subscriber():
rospy.init_node('information_subscriber', anonymous=True)
rospy.Subscriber('/company_info', Information, company_info_callback)
rospy.spin()
if __name__ == '__main__':
information_subscriber()chmod +x scripts/Information_publisher.py scripts/Information_subscriber.py
roscore
rosrun learning_topic Information_publisher.py
rosrun learning_topic Information_subscriber.pyAbbildungen








7.2.1.7 Client
Führen Sie die Befehle im ROS 1 Noetic Docker-Container aus, der in 7.2.1.1 Einführung in ROS 1 beschrieben ist.
Zusätzlich zur Topic-Kommunikation gibt es eine Service-Kommunikation. Ein Client sendet eine Anfrage, und ein Server gibt eine Antwort zurück. Dieser Abschnitt konzentriert sich auf den Client und zeigt, wie ein Client in C++ und Python implementiert wird.
Vorbereitende Arbeiten
Verwenden Sie weiterhin das in diesem Abschnitt erstellte
learning_server-Paket.
Erstellung von Paketen
- Wechseln Sie zu ~/catkin_ws/src, Terminalausführung:
catkin_create_pkg learning_server std_msgs rospy roscpp geometry_msgs turtlesimWechseln Sie zum ~ Verzeichnis, um die Kompilierung auszuführen:
catkin_makeC++ Implementierung
Schritte zur Realisierung
-
Initialisierung der ROS-Nodes
-
Handles erstellen
-
Erstellen Sie eine Instanz des Clients
-
Initialisieren und veröffentlichen Sie Service-Anfragedaten
-
VOM SERVER EMPFANGENE ANTWORT
Erstellen Sie a_new_turtle.cpp unter ~/catkin_ws/src/learning_server/src und fügen Sie den folgenden Code ein.
a_new_turtle.cpp
Code-Datei: 7-2-1-7-client-new.cpp
/**
This example calls the turtlesim /spawn service to create a new turtle at the specified position.
*/
#include <ros/ros.h>
#include <turtlesim/Spawn.h>
int main(int argc, char** argv)
{
ros::init(argc, argv, "a_new_turtle");// Initialize the ROS node.
ros::NodeHandle node;
ros::service::waitForService("/spawn"); // Wait for the /spawn service.
ros::ServiceClient new_turtle = node.serviceClient<turtlesim::Spawn>("/spawn");//Create a service client for /spawn.
// Initialize the turtlesim::Spawn request.
turtlesim::Spawn new_turtle_srv;
new_turtle_srv.request.x = 6.0;
new_turtle_srv.request.y = 8.0;
new_turtle_srv.request.name = "turtle2";
// Call the service with x/y position and name parameters.
ROS_INFO("Call service to create a new turtle name is %s,at the x:%.1f,y:%.1f", new_turtle_srv.request.name.c_str(),
new_turtle_srv.request.x,
new_turtle_srv.request.y);
new_turtle.call(new_turtle_srv);
ROS_INFO("Spawn turtle successfully [name:%s]", new_turtle_srv.response.name.c_str());// Display the service call result.
return 0;
};- Flussdiagramm des Verfahrens
- Fügen Sie in der CMakeLists.txt-Konfiguration unter dem Build-Bereich Folgendes hinzu:
(vim Grundlagen: 14 mit Vim-Editor)
Code-Datei: 7-2-1-7-client-example-02.cmake
add_executable(a_new_turtle src/a_new_turtle.cpp)
target_link_libraries(a_new_turtle ${catkin_LIBRARIES})- Kompilieren Sie den Code im Workspace-Verzeichnis neu
cd ~/catkin_ws
catkin_make
source devel/setup.bash # source the workspace so ROS can find the program- Öffnen Sie drei Terminal-Programme
roscore
rosrun turtlesim turtlesim_node
rosrun learning_server a_new_turtle-
Erwartetes Ergebnis
-
Prozess
Sobald der kleine Schildkröten-Node aktiviert ist, zeigt die erneute Ausführung von a_new_turtle eine weitere Schildkröte im Bild, da der kleine Schildkröten-Node den Service /spawn bereitstellt, der eine weitere Schildkröte turtle2 erzeugt, die über den Befehl rosservice list angezeigt werden kann, wie unten gezeigt.
Die für diesen Service erforderlichen Parameter können über rosservice info /spawn angezeigt werden, wie in der folgenden Abbildung dargestellt.
Es ist zu sehen, dass vier Parameter benötigt werden: x, y, theta, name, die in a_new_turtle.cpp initialisiert werden
Code-Datei: 7-2-1-7-client-turtle.cpp
srv.request.x = 6.0;
srv.request.y = 8.0;
srv.request.name = "turtle2";Hinweis: Theta ist nicht zugewiesen, Standard ist 0
Python Implementierung
Erstellen Sie scripts/a_new_turtle.py unter ~/catkin_ws/src/learning_server und fügen Sie den folgenden Code ein.
a_new_turtle.py
Code-Datei: 7-2-1-7-client-a_new_turtle.py
#!/usr/bin/env python3
import rospy
from turtlesim.srv import Spawn
def turtle_spawn():
rospy.init_node('new_turtle')
rospy.wait_for_service('/spawn')
try:
spawn_client = rospy.ServiceProxy('/spawn', Spawn)
response = spawn_client(2.0, 2.0, 0.0, 'turtle2')
return response.name
except rospy.ServiceException as exc:
rospy.logerr('Failed to call /spawn: %s', exc)
return None
if __name__ == '__main__':
name = turtle_spawn()
if name:
rospy.loginfo('Created a new turtle named %s.', name)-
Flussdiagramm des Verfahrens
-
Öffnen von drei Terminal-Programmen
roscore
rosrun turtlesim turtlesim_node
rosrun learning_server a_new_turtle.py- Die Auswirkungen des Betriebs und die Beschreibung des Verfahrens stimmen mit den durch C++ erzielten Ergebnissen überein, und hier sind die Parameter, wie Python den Service bereitstellt,
response = spawn_client(2.0, 2.0, 0.0, "turtle2")
Die entsprechenden Parameter sind x, y, theta, name.
Abbildungen







7.2.1.8 Server
Führen Sie die Befehle im ROS 1 Noetic Docker-Container aus, der in 7.2.1.1 Einführung in ROS 1 beschrieben ist.
Wenn wir über Client-Anfragen und dann Service sprechen, sprechen wir über die Servicebereitstellung.
Verwenden Sie weiterhin das in diesem Abschnitt erstellte
learning_server-Paket.
C++ Implementierung
Schritte zur Realisierung
-
Initialisierung der ROS-Nodes
-
Beispiele für die Erstellung von Server
-
Schleife, die auf Service-Anfragen wartet und in eine Callback-Funktion eintritt
-
Vervollständigen Sie die funktionale Verarbeitung des Service in der Callback-Funktion und geben Sie Feedback zu den Antwortdaten
Erstellen Sie turtle_vel_command_server.cpp unter ~/catkin_ws/src/learning_server/src und fügen Sie den folgenden Code ein.
Code-Datei: 7-2-1-8-server-new.cpp
/**
This example provides /turtle_vel_command with the std_srvs/Trigger service type.
*/
#include <ros/ros.h>
#include <geometry_msgs/Twist.h>
#include <std_srvs/Trigger.h>
ros::Publisher turtle_vel_pub;
bool pubvel = false;
// Service callback: req is the request and res is the response.
bool pubvelCallback(std_srvs::Trigger::Request &req,
std_srvs::Trigger::Response &res)
{
pubvel = !pubvel;
ROS_INFO("Do you want to publish the vel?: [%s]", pubvel==true?"Yes":"No");// Print the client request.
// Set response data.
res.success = true;
res.message = "The status is changed!";
return true;
}
int main(int argc, char **argv)
{
ros::init(argc, argv, "turtle_vel_command_server");
ros::NodeHandle n;
// Create the /turtle_vel_command server and register pubvelCallback.
ros::ServiceServer command_service = n.advertiseService("/turtle_vel_command", pubvelCallback);
// Create a publisher for /turtle1/cmd_vel. The message type is geometry_msgs::Twist and the queue size is 8.
turtle_vel_pub = n.advertise<geometry_msgs::Twist>("/turtle1/cmd_vel", 8);
ros::Rate loop_rate(10);// Set the loop rate.
while(ros::ok())
{
ros::spinOnce();// Process callbacks once.
// Publish turtle velocity commands when pubvel is true.
if(pubvel)
{
geometry_msgs::Twist vel_msg;
vel_msg.linear.x = 0.6;
vel_msg.angular.z = 0.8;
turtle_vel_pub.publish(vel_msg);
}
loop_rate.sleep();//Sleep according to the loop rate.
}
return 0;
}- Flussdiagramm des Verfahrens
- Konfigurieren Sie in CMakeLists.txt unter dem Build-Bereich und fügen Sie Folgendes hinzu:
Code-Datei: 7-2-1-8-server-example-02.cmake
add_executable(turtle_vel_command_server src/turtle_vel_command_server.cpp)
target_link_libraries(turtle_vel_command_server ${catkin_LIBRARIES})- Code im Workspace-Verzeichnis kompilieren
cd ~/catkin_ws
catkin_make
source devel/setup.bash # source the workspace so ROS can find the program- Starten von vier Terminal-Programmen
roscore
rosrun turtlesim turtlesim_node
rosrun learning_server turtle_vel_command_server
rosservice call /turtle_vel_command-
Erwartetes Ergebnis
-
Prozess
Zuerst, wenn Sie den kleinen Schildkröten-Node ausführen, können Sie rosservice list im Terminal eingeben, um zu sehen, was der aktuelle Service ist, wie folgt:
Und dann führen wir das turtle_vel_command_server Programm aus und geben rosservice list ein, und wir finden einen zusätzlichen /turtle_vel_command Service, wie in der folgenden Abbildung dargestellt.
Und dann rufen wir diesen Service auf, indem wir ihn im Terminal eingeben, und wir stellen fest, dass kleine Schildkröten eine kreisförmige Bewegung machen, und wenn sie erneut aufgerufen werden, stoppen sie. Dies liegt daran, dass wir im Callback-Service den Wert von pubvel umkehren und dann Feedback zurückgeben, die Hauptfunktion beurteilt den Wert von pubvel, und wenn es True ist, gibt sie Geschwindigkeitsanweisungen, und nicht für False.
Python Implementierung
Erstellen Sie scripts/turtle_vel_command_server.py unter ~/catkin_ws/src/learning_server und fügen Sie den folgenden Code ein.
turtle_vel_command_server.py
Code-Datei: 7-2-1-8-server-turtle_vel_command_server.py
#!/usr/bin/env python3
import threading
import rospy
from geometry_msgs.msg import Twist
from std_srvs.srv import Trigger, TriggerResponse
pubvel = False
turtle_vel_pub = None
def publish_velocity_loop():
rate = rospy.Rate(10)
while not rospy.is_shutdown():
if pubvel:
vel_msg = Twist()
vel_msg.linear.x = 0.6
vel_msg.angular.z = 0.8
turtle_vel_pub.publish(vel_msg)
rate.sleep()
def pubvel_callback(req):
global pubvel
pubvel = not pubvel
rospy.loginfo('Publish turtle velocity: %s', pubvel)
return TriggerResponse(success=True, message='Velocity publishing toggled.')
def turtle_pubvel_command_server():
global turtle_vel_pub
rospy.init_node('turtle_vel_command_server')
turtle_vel_pub = rospy.Publisher('/turtle1/cmd_vel', Twist, queue_size=8)
rospy.Service('/turtle_vel_command', Trigger, pubvel_callback)
threading.Thread(target=publish_velocity_loop, daemon=True).start()
rospy.loginfo('Ready to receive /turtle_vel_command requests.')
rospy.spin()
if __name__ == '__main__':
turtle_pubvel_command_server()- Flussdiagramm des Verfahrens
- Öffnen Sie drei Terminal-Programme:
roscore
rosrun turtlesim turtlesim_node
rosrun learning_server turtle_vel_command_server.py- Die Auswirkungen des Betriebs des Verfahrens und die Beschreibung des Verfahrens stimmen mit den durch C++ erzielten überein.
Abbildungen






# 7.2.1.9 Benutzerdefinierte Service-Nachrichten und Verwendung
Führen Sie die Befehle im ROS 1 Noetic Docker-Container aus, der in 7.2.1.1 Einführung in ROS 1 beschrieben ist.
Dieser Abschnitt definiert einen benutzerdefinierten Service namens IntPlus.srv und implementiert ein Server/Client-Paar in C++ und Python.
Die Service-Datei erstellen
cd ~/catkin_ws/src/learning_server
mkdir -p srv
vim srv/IntPlus.srvCode-Datei: 7-2-1-9-custom-service-messages-and-usage-IntPlus.srv
int64 a
int64 b
---
int64 resultpackage.xml und CMakeLists.txt aktualisieren
Fügen Sie diese Abhängigkeiten zu package.xml hinzu:
<build_depend>message_generation</build_depend>
<exec_depend>message_runtime</exec_depend>Fügen Sie die Service-Generierung zu CMakeLists.txt hinzu:
find_package(catkin REQUIRED COMPONENTS
roscpp
rospy
std_msgs
message_generation
)
add_service_files(
FILES
IntPlus.srv
)
generate_messages(
DEPENDENCIES
std_msgs
)
catkin_package(
CATKIN_DEPENDS message_runtime
)Bauen Sie den Workspace:
cd ~/catkin_ws
catkin_make
source devel/setup.bashC++ Server und Client
Code-Datei: 7-2-1-9-custom-service-messages-and-usage-IntPlus_server.cpp
#include <ros/ros.h>
#include "learning_server/IntPlus.h"
bool intPlusCallback(learning_server::IntPlus::Request &req,
learning_server::IntPlus::Response &res)
{
ROS_INFO("number 1 is:%ld, number 2 is:%ld", req.a, req.b);
res.result = req.a + req.b;
return true;
}
int main(int argc, char **argv)
{
ros::init(argc, argv, "IntPlus_server");
ros::NodeHandle nh;
ros::ServiceServer service = nh.advertiseService("/Two_Int_Plus", intPlusCallback);
ROS_INFO("Ready to calculate two integers.");
ros::spin();
return 0;
}Code-Datei: 7-2-1-9-custom-service-messages-and-usage-IntPlus_client.cpp
#include <ros/ros.h>
#include "learning_server/IntPlus.h"
int main(int argc, char **argv)
{
ros::init(argc, argv, "IntPlus_client");
ros::NodeHandle nh;
ros::service::waitForService("/Two_Int_Plus");
ros::ServiceClient client = nh.serviceClient<learning_server::IntPlus>("/Two_Int_Plus");
learning_server::IntPlus srv;
srv.request.a = 8;
srv.request.b = 6;
if (client.call(srv)) {
ROS_INFO("Result: %ld", srv.response.result);
} else {
ROS_ERROR("Failed to call /Two_Int_Plus");
}
return 0;
}Fügen Sie die ausführbaren Dateien zu CMakeLists.txt hinzu:
add_executable(IntPlus_server src/IntPlus_server.cpp)
target_link_libraries(IntPlus_server ${catkin_LIBRARIES})
add_dependencies(IntPlus_server ${PROJECT_NAME}_generate_messages_cpp)
add_executable(IntPlus_client src/IntPlus_client.cpp)
target_link_libraries(IntPlus_client ${catkin_LIBRARIES})
add_dependencies(IntPlus_client ${PROJECT_NAME}_generate_messages_cpp)Führen Sie das Beispiel aus:
roscore
rosrun learning_server IntPlus_server
rosrun learning_server IntPlus_clientSie können den Service auch direkt aufrufen:
rosservice call /Two_Int_Plus 5 6Python Server und Client
Code-Datei: 7-2-1-9-custom-service-messages-and-usage-IntPlus_server.py
#!/usr/bin/env python3
import rospy
from learning_server.srv import IntPlus, IntPlusResponse
def int_plus_callback(req):
rospy.loginfo('Ints: a:%d b:%d', req.a, req.b)
return IntPlusResponse(req.a + req.b)
if __name__ == '__main__':
rospy.init_node('IntPlus_server')
rospy.Service('/Two_Int_Plus', IntPlus, int_plus_callback)
rospy.loginfo('Ready to calculate two integers.')
rospy.spin()Code-Datei: 7-2-1-9-custom-service-messages-and-usage-IntPlus_client.py
#!/usr/bin/env python3
import rospy
from learning_server.srv import IntPlus
if __name__ == '__main__':
rospy.init_node('IntPlus_client')
rospy.wait_for_service('/Two_Int_Plus')
plus_client = rospy.ServiceProxy('/Two_Int_Plus', IntPlus)
response = plus_client(22, 20)
rospy.loginfo('Result: %d', response.result)chmod +x scripts/IntPlus_server.py scripts/IntPlus_client.py
roscore
rosrun learning_server IntPlus_server.py
rosrun learning_server IntPlus_client.pyAbbildungen







7.2.1.10 Veröffentlichen und Abhören mit TF
Führen Sie die Befehle im ROS 1 Noetic Docker-Container aus, der in 7.2.1.1 Einführung in ROS 1 beschrieben ist.
tf-Pakete
tf ist ein Paket, das es Benutzern ermöglicht, mehrere Koordinatensysteme im Zeitverlauf zu verfolgen, unter Verwendung von baumförmigen Datenstrukturen, die Entwicklern helfen, Koordinaten jederzeit zu ändern, Abschlusspunkte zwischen Koordinaten, Vektoren usw., unter Verwendung von Zeitpuffern und Aufrechterhaltung von Koordinatenwechseln zwischen mehreren Koordinaten.
Verwendungsschritte
- Abfangen der tf-Transformation
Empfängt alle im Cachesystem veröffentlichten Koordinaten, transformiert die Daten und sucht daraus die benötigten Koordinaten.
- Ausstrahlen der tf-Transformation
(b) Sendet den Koordinatenwechsel zwischen den Koordinaten im System. Es kann tf-Änderungssendungen in mehreren Teilen des Systems geben. Jede Sendung kann direkt in den tf-Baum eingefügt werden, ohne dass eine weitere Synchronisierung erforderlich ist.
tf-Koordinatensendung und -abhörung programmtechnisch erreicht
Pakete erstellen und kompilieren
cd ~/catkin_ws/src
catkin_create_pkg learning_tf rospy roscpp turtlesim tf
cd..
catkin_makeWie man einen tf-Sender erreicht
-
Definition des TF-Senders (Transform Broadcaster);
-
Initialisierung der tf-Daten und Erstellung von Koordinaten;
-
Veröffentlichung der Koordinatenkonvertierung (sendTransform);
Wie man ein tf-Abhörgerät erreicht
-
Definition des TF-Abhörgeräts (TransformListener);
-
Koordinaten finden (waitForTransform, lookupTransform)
C++ Sprachrealisierung des tf-Senders
-
Erstellen Sie eine C++-Datei (Datei mit der Endung .cpp) im src-Ordner des Pakets
-
Kopieren Sie den folgenden Programmcode in die Datei turtle_tf_broadcaster.cpp
Code-Datei: 7-2-1-10-publishing-and-listening-with-tf-with.cpp
#include <ros/ros.h>
#include <tf/transform_broadcaster.h>
#include <turtlesim/Pose.h>
std::string turtle_name;
void poseCallback(const turtlesim::PoseConstPtr& msg)
{
static tf::TransformBroadcaster br;// Create a TF broadcaster.
// Initialize TF data.
tf::Transform transform;
transform.setOrigin( tf::Vector3(msg->x, msg->y, 0.0) );//Set xyz coordinates.
tf::Quaternion q;
q.setRPY(0, 0, msg->theta);//Set Euler angles for x, y, and z rotation.
transform.setRotation(q);
br.sendTransform(tf::StampedTransform(transform, ros::Time::now(), "world", turtle_name));// Broadcast TF data between world and the turtle frame.
}
int main(int argc, char** argv)
{
ros::init(argc, argv, "turtle_world_tf_broadcaster");// Initialize the ROS node.
if (argc != 2)
{
ROS_ERROR("Missing a parameter as the name of the turtle!");
return -1;
}
turtle_name = argv[1];// Use the input argument as the turtle name.
// Subscribe to the turtle pose topic.
ros::NodeHandle node;
ros::Subscriber sub = node.subscribe(turtle_name+"/pose", 10, &poseCallback);
// Wait for callbacks.
ros::spin();
return 0;
};-
PROJEKT-Flussdiagramm
-
Code-Auflösung
Zunächst abonnieren Sie die /pose-Position der Schildkröte, und wenn das Topic veröffentlicht wird, tritt es in die Callback-Funktion ein. Und dann zurück zum tf-Sender, dann initialisieren Sie die tf-Daten, deren Wert das Abonnement des /pose-Topics ist. Schließlich wird die Transformation der Koordinaten der Welt durch kleine Schildkröten über br.sendTransform, eine Funktion von sendTransform, veröffentlicht. Es gibt vier Parameter, von denen der erste tf darstellt: (d.h. zuvor initialisierte tf-Daten) Koordinaten des Transform-Typs, der zweite Parameter ist ein Zeitstempel, und der dritte und vierte sind eine variable Quell- und Zielkoordinate.
C++ Sprachrealisierung des tf-Abhörgeräts
-
Erstellen Sie eine C++-Datei (Datei mit der Endung .cpp) im src-Ordner des Pakets
-
Kopieren Sie den folgenden Programmcode in die Datei turtle_tf_listener.cpp
Code-Datei: 7-2-1-10-publishing-and-listening-with-tf-with.cpp
/**
This example listens to TF data, computes velocity commands, and publishes them to turtle2.
turtle2->turtle1 = world->turtle*world->turtle2
*/
#include <ros/ros.h>
#include <tf/transform_listener.h>
#include <geometry_msgs/Twist.h>
#include <turtlesim/Spawn.h>
int main(int argc, char** argv)
{
ros::init(argc, argv, "turtle1_turtle2_listener");// Initialize the ROS node.
ros::NodeHandle node; // Create a node handle.
// Call the service to spawn turtle2.
ros::service::waitForService("/spawn");
ros::ServiceClient add_turtle = node.serviceClient<turtlesim::Spawn>("/spawn");
turtlesim::Spawn srv;
add_turtle.call(srv);
// Create a publisher for turtle2 velocity commands.
ros::Publisher vel = node.advertise<geometry_msgs::Twist>("/turtle2/cmd_vel", 10);
tf::TransformListener listener;// Create a TF listener.
ros::Rate rate(10.0);
while (node.ok())
{
// Get TF data between turtle1 and turtle2.
tf::StampedTransform transform;
try
{
listener.waitForTransform("/turtle2", "/turtle1", ros::Time(0), ros::Duration(3.0));
listener.lookupTransform("/turtle2", "/turtle1", ros::Time(0), transform);
}
catch (tf::TransformException &ex)
{
ROS_ERROR("%s",ex.what());
ros::Duration(1.0).sleep();
continue;
}
// Compute angular and linear velocity from the relative pose between turtle1 and turtle2, then publish commands for turtle2.
geometry_msgs::Twist turtle2_vel_msg;
turtle2_vel_msg.angular.z = 6.0 * atan2(transform.getOrigin().y(),
transform.getOrigin().x());
turtle2_vel_msg.linear.x = 0.8 * sqrt(pow(transform.getOrigin().x(), 2) +
pow(transform.getOrigin().y(), 2));
vel.publish(turtle2_vel_msg);
rate.sleep();
}
return 0;
};-
PROJEKT-Flussdiagramm
-
Code-Auflösung
Zuerst ruft der Service die Erstellung einer weiteren kleinen Schildkröte turtle2 auf, und dann wird ein turtle2-Geschwindigkeitsregler erstellt; Dann erstellen Sie ein Abhörgerät, das die Beziehung zwischen turtle1 und turtle2 abhört und sucht, was zwei Funktionen umfasst:
Code-Datei: 7-2-1-10-publishing-and-listening-with-tf-example-03.cpp
waitForTransform and lookupTransform
waitForTransform(target_frame,source_frame,time,timeout)Die beiden Frames repräsentieren die Zielkoordinaten bzw. die Quellkoordinaten, und die Zeiten geben die Zeit an, die auf eine Änderung zwischen den beiden Koordinaten gewartet werden soll, da die Änderung der Koordinaten ein blockierender Prozess ist und daher eingerichtet werden muss, um das Zeitlimit anzugeben.
LookupTransform (target_frame, source_frame, transform): gegeben Quell-Frame und Zielkoordinaten (target_frame), gegeben die Zeit zwischen den beiden Koordinaten (transform).
Wir haben das Ergebnis der Koordinatentransformation durch lookupTransform erhalten und dann x, y verwendet, um die lineare und Winkelgeschwindigkeit zu berechnen.
Änderungen an CMakeLists.txt und Kompilierungen
- Ändern von CMakeLists.txt
Ändern Sie die src/learning_tf/CMakeLists.txt unter dem Paket, indem Sie Folgendes hinzufügen:
(vim Grundlagen: 14 mit Vim-Editor)
Code-Datei: 7-2-1-10-publishing-and-listening-with-tf-example-04.cpp
add_executable(turtle_tf_listener src/turtle_tf_listener.cpp)
target_link_libraries(turtle_tf_listener ${catkin_LIBRARIES})
add_executable(turtle_tf_broadcaster src/turtle_tf_broadcaster.cpp)
target_link_libraries(turtle_tf_broadcaster ${catkin_LIBRARIES})- Implementierungsdokumente kompilieren
cd ~/catkin_ws
catkin_make
source devel/setup.bash # source the workspace so ROS can find the programDemonstration von Start und Betriebseffekten
- Öffnen Sie sechs Terminals und führen Sie die folgenden Befehle aus:
roscore
rosrun turtlesim turtlesim_node
rosrun learning_tf turtle_tf_broadcaster __name:=turtle1_tf_broadcaster /turtle1
rosrun learning_tf turtle_tf_broadcaster __name:=turtle2_tf_broadcaster /turtle2
rosrun learning_tf turtle_tf_listener
rosrun turtlesim turtle_teleop_key # start keyboard teleoperation for the turtle- Demonstrierte Auswirkung
III. VERFAHRENSERKLÄRUNGEN
Wenn roscore aktiviert ist, wird der kleine Schildkröten-Node aktiviert, und eine kleine Schildkröte erscheint am Ende; Dann veröffentlichen wir zwei tf-Transformationen, turtle1->world, turtle2->world, denn wenn wir die Änderung zwischen turtle2 und turtle1 wissen wollen, müssen wir die Änderung zwischen ihnen und world kennen; Das tf-Abhörprogramm wird dann geöffnet, woraufhin das Terminal eine weitere Schildkröte erzeugt, und turtle2 wird sich in Richtung turtle1 bewegen; Dann schalten wir die Tastatursteuerung ein und klicken dann auf den Pfeil, um die turtle1-Bewegung zu steuern, und turtle2 folgt der turtle1-Bewegung.
tf-Sender in Python-Sprache
-
Erstellen Sie einen Ordner scripts im Paket learning_tf, wechseln Sie in dieses Verzeichnis, erstellen Sie eine neue .py-Datei namens turtle_tf_broadcaster.py
-
Kopieren Sie den folgenden Programmcode in die Datei turtle_tf_broadcaster.py
Code-Datei: 7-2-1-10-publishing-and-listening-with-tf-new.py
#!/usr/bin/env python3
import roslib
roslib.load_manifest('learning_tf')
import rospy
import tf
import turtlesim.msg
def handle_turtle_pose(msg, turtlename):
br = tf.TransformBroadcaster()# Create a TF broadcaster.
# Broadcast the TF transform between world and the named turtle.
br.sendTransform((msg.x, msg.y, 0),
tf.transformations.quaternion_from_euler(0, 0, msg.theta),
rospy.Time.now(),
turtlename,
"world")
if __name__ == '__main__':
rospy.init_node('turtle1_turtle2_tf_broadcaster')# Initialize the ROS node.
turtlename = rospy.get_param('~turtle') # Get the turtle name from the parameter server.
# Subscribe to the turtle pose topic.
rospy.Subscriber('/%s/pose' % turtlename,
turtlesim.msg.Pose,
handle_turtle_pose,
turtlename)
rospy.spin()- PROJEKT-Flussdiagramm
Python-Sprache erreicht tf-Abhörgeräte
-
Erstellen Sie eine Python-Datei (Datei mit der Endung .py) im scripts-Ordner des Pakets learning_tf namens turtle_tf_listener.py
-
Kopieren Sie den folgenden Programmcode in die Datei turtle_tf_listener.py
Code-Datei: 7-2-1-10-publishing-and-listening-with-tf-with.py
#!/usr/bin/env python3
import rospy
import math
import tf
import geometry_msgs.msg
import turtlesim.srv
if __name__ == '__main__':
rospy.init_node('turtle_tf_listener')# Initialize the ROS node.
listener = tf.TransformListener()# Initialize a TF listener.
rospy.wait_for_service('spawn')
# Call the service to create another turtle named turtle2.
spawner = rospy.ServiceProxy('spawn', turtlesim.srv.Spawn)
spawner(8, 6, 0, 'turtle2')
# Declare a publisher for turtle2 velocity.
turtle_vel = rospy.Publisher('turtle2/cmd_vel', geometry_msgs.msg.Twist,queue_size=1)
rate = rospy.Rate(10.0)
while not rospy.is_shutdown():
try:
# Look up the TF transform between turtle2 and turtle1.
(trans,rot) = listener.lookupTransform('/turtle2', '/turtle1', rospy.Time(0))
except (tf.LookupException, tf.ConnectivityException, tf.ExtrapolationException):
continue
# Compute linear and angular velocity, then publish them.
angular = 6.0 * math.atan2(trans[1], trans[0])
linear = 0.8 * math.sqrt(trans[0] ** 2 + trans[1] ** 2)
cmd = geometry_msgs.msg.Twist()
cmd.linear.x = linear
cmd.angular.z = angular
turtle_vel.publish(cmd)
rate.sleep()- PROJEKT-Flussdiagramm
Demonstration von Start und Betriebseffektivität
- Vorbereitung einer Launch-Datei
Erstellen Sie im Paketverzeichnis einen neuen Ordner launch, wechseln Sie zu launch, erstellen Sie eine neue Launch-Datei namens start_tf_demo_py.launch und kopieren Sie Folgendes hinein:
Code-Datei: 7-2-1-10-publishing-and-listening-with-tf-py.xml
<launch>
<!-- turtlesim node-->
<node pkg="turtlesim" type="turtlesim_node" name="sim"/>
<!-- broadcast turtle1 -> world -->
<node name="turtle1_tf_broadcaster" pkg="learning_tf" type="turtle_tf_broadcaster.py" respawn="false" output="screen" >
<param name="turtle" type="string" value="turtle1" />
</node>
<!-- broadcast turtle2 -> world -->
<node name="turtle2_tf_broadcaster" pkg="learning_tf" type="turtle_tf_broadcaster.py" respawn="false" output="screen" >
<param name="turtle" type="string" value="turtle2" />
</node>
<!--listener-->
<node pkg="learning_tf" type="turtle_tf_listener.py" name="listener" />
<!--turtle keyboard control node-->
<node pkg="turtlesim" type="turtle_teleop_key" name="teleop" output="screen"/>
</launch>- Start
roslaunch learning_tf start_tf_demo_py.launchWenn die Anwendung läuft, klickt die Maus auf das Fenster, das launch ausführt, drücken Sie die Pfeiltaste, und turtle2 bewegt sich mit turtle1.
- Die Betriebseffekte sind weitgehend konsistent mit C++
Abbildungen






