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:

VersionsnameUbuntuWartungsstatus
Kinetic16.04Eingestellt
Melodic18.04Eingestellt
Noetic20.04Letzte 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:

bash
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:noetic

Wenn 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:

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.1 Einführung in ROS 1 Abbildung 1

7.2.1.1 Einführung in ROS 1 Abbildung 2

7.2.1.1 Einführung in ROS 1 Abbildung 3

7.2.1.1 Einführung in ROS 1 Abbildung 4

7.2.1.1 Einführung in ROS 1 Abbildung 5

7.2.1.1 Einführung in ROS 1 Abbildung 6

7.2.1.1 Einführung in ROS 1 Abbildung 7

7.2.1.1 Einführung in ROS 1 Abbildung 8

7.2.1.1 Einführung in ROS 1 Abbildung 9

7.2.1.1 Einführung in ROS 1 Abbildung 10

7.2.1.1 Einführung in ROS 1 Abbildung 11

7.2.1.1 Einführung in ROS 1 Abbildung 12

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.

bash
mkdir -p ~/catkin_ws/src  # create
cd catkin_ws/             # enter the workspace
catkin_make               # build
source devel/setup.bash   # source the workspace environment

Pakete

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

bash
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

bash
|-- 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 actions

Einfü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
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:

bash
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.

bash
edd executeable

Dies 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.

cmake
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.

cmake
target_link_libraries(node_name ${catkin_LIBRARIES})

Beispiel:

bash
(foo src/foo.cpp)
Add library (moo src/moo.cpp)
This links fly against libmoo.so

Bitte 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:

xml
<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

- URL für Informationen über das Paket, normalerweise die Wiki-Seite auf ros.org.

- Autor des Pakets

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):

bash
git clone https://github.com/ros/ros_tutorials.git -b noetic-devel

Dies ist ein Fall von ROS 1 basierend auf C++:

bash
cd ros_tutorials/
mkdir  src
cp roscpp_tutorials/ src/ -r
catkin_make # start building

Die Kompilierung wurde wie folgt abgeschlossen:

Nach Abschluss der Kompilierung ist eine Initialisierung erforderlich, bevor der Workspace weiterverwendet werden kann:

bash
source devel/setup.bash

Abbildungen

7.2.1.2 Vorbereiten des Workspace Abbildung 1

7.2.1.2 Vorbereiten des Workspace Abbildung 2# 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:

  1. Start mit ROS-Paketpfad

Das Format ist wie folgt:

bash
roslaunch package_name launch_file_name
roslaunch pkg_name launchfile_name.launch
  1. Absoluter Pfad zur Launch-Datei

Das Format ist wie folgt:

bash
roslaunch path_to_launchfile

Unabhä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.:

bash
roslaunch pkg_name launchfile_name model:=urdf/myfile.urdf # the launch file has a `model` argument that must be set

oder

bash
roslaunch pkg_name launchfile_name model:='$(find urdf_pkg)/urdf/myfile.urdf' # use `find` to provide the path

Der 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:

bash
roscore

Node-Start, rosrun+Paketname+ Nodename; Die rosrun-Methode führt nur einen Node auf einmal aus.

bash
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

bash
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 terminal

Nachdem 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.

bash
[ 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:

bash
roslaunch turtle_tf turtle_tf_demo.launch

Halten 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

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 -->
  1. Label [node]

Das Tag [node] ist der Kernbestandteil der Launch-Datei.

Code-Datei: 7-2-1-3-common-commands-and-tools-example-02.xml

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

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:

  1. Basisname, z.B. topic

  2. Globaler Name, z.B.: /A/topic

  3. Relativer Name, z.B. A/topic

  4. Private Namen, z.B. ~topic

Es gibt diese Codezeile zum Zeitpunkt der Veröffentlichung oder Buchung.

bash
 ros::init(argc, argv, "publish_node");
 ros::NodeHandle nh;
 ros::Publisher pub = nh.advertise<std_msgs::string>("topic",1000);
  1. 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

xml
<node pkg="some" type="some" name="some">
    <remap from="origin" to="new" />
</node>
  1. 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:

  1. Label

Wiederholung von Parametern durch [arg] ist möglich und kann an mehreren Stellen leicht geändert werden. Drei gängige Methoden:

: eine Deklaration [arg] aber kein Wert. Zu einem späteren Zeitpunkt können Sie den Wert über die Befehlszeile oder über das [include] Label zuweisen.

: Standardwert. Ein fester Wert.

Wertzuweisung über die Befehlszeile

roslaunch pack_name file_name.launch arg1:=value1 arg2:=value2

  1. 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

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:

cpp
<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

bash
roslaunch package_name file_name.launch a:=1 b:=5
  1. 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

bash
<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:

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

xml
 <node name="node1" pkg="pkg1" type="exe1">
    <param name="param1" value="False"/>
 </node>

Wenn Sie [param] mit rosparam list auflisten, ja

bash
/publish_frequency
/node1/param1   # namespace prefix is added automatically

Hinweis: 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:

bash
<rosparam command="load" file="$(find rosparam)/example.yaml" />

Delete: Löschen Sie einige param

bash
<rosparam command="delete" param="my_param" />

[param]-ähnliche Zuweisungsoperation

bash
<rosparam param="my_param">[1,2,3,4]</rosparam>

Oder...

Code-Datei: 7-2-1-3-common-commands-and-tools-example-08.xml

bash
<rosparam>
a: 1
b: 2
</rosparam>

[Rosparam] kann auch in [node] platziert werden, an diesem Punkt Node-Namensraum.

  1. 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

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

  1. 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.

bash
rosrun tf view_frames
  1. 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

bash
rosrun rqt_tf_tree rqt_tf_tree
  1. tf_echo Werkzeug

Mit dem tf_echo Werkzeug können Sie die Beziehung zwischen den beiden Referenzsystemen sehen.

bash
rosrun tf tf_echo <source_frame> <target_frame>

Gibt die Rotationstransformation vom Quell-Frame zum Ziel-Frame aus; Zum Beispiel:

bash
rosrun tf tf_echo turtle1 turtle2
  1. Static transform publisher

Veröffentlicht statische Koordinaten zwischen den beiden Koordinaten, die ihre relativen Positionen nicht ändern. Befehlsformat:

bash
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_ms

Verwendung in launch:

Code-Datei: 7-2-1-3-common-commands-and-tools-example-10.xml

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>
  1. Roswtf Plugin

Ein Plugin, um Ihre aktuelle tf-Konfiguration zu analysieren und zu versuchen, häufige Probleme zu identifizieren.

bash
roswtf

Gä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:

  1. 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.

  1. 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.

  1. 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.

bash
rosrun rqt_publisher rqt_publisher

Klicken 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:

  1. rqt_plot Datenvisualisierung

Die Referenzanweisungen sind wie folgt:

bash
rosrun rqt_plot rqt_plot
  1. 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.

bash
rosrun rqt_console rqt_console

Das 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

  1. rqt_reconfigure Dynamische Parameterkonfiguration

Die Referenzanweisungen sind wie folgt:

bash
rosrun rqt_reconfigure rqt_reconfigure

Bildquelle 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.3 Gängige Befehle und Werkzeuge Abbildung 1

7.2.1.3 Gängige Befehle und Werkzeuge Abbildung 2

7.2.1.3 Gängige Befehle und Werkzeuge Abbildung 3

7.2.1.3 Gängige Befehle und Werkzeuge Abbildung 4

7.2.1.3 Gängige Befehle und Werkzeuge Abbildung 5

7.2.1.3 Gängige Befehle und Werkzeuge Abbildung 6

7.2.1.3 Gängige Befehle und Werkzeuge Abbildung 7

7.2.1.3 Gängige Befehle und Werkzeuge Abbildung 8

7.2.1.3 Gängige Befehle und Werkzeuge Abbildung 9

7.2.1.3 Gängige Befehle und Werkzeuge Abbildung 10

7.2.1.3 Gängige Befehle und Werkzeuge Abbildung 11

7.2.1.3 Gängige Befehle und Werkzeuge Abbildung 12

7.2.1.3 Gängige Befehle und Werkzeuge Abbildung 13# 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

bash
mkdir -p ~/catkin_ws/src
cd ~/catkin_ws/src
catkin_init_workspace

Kompilierung des Workspace

bash
cd ~/catkin_ws/
catkin_make

Umgebungsvariablen aktualisieren

bash
source devel/setup.bash

Überprüfung der Umgebungsvariablen

bash
echo $ROS_PACKAGE_PATH

Pakete erstellen

bash
cd ~/catkin_ws/src
catkin_create_pkg learning_topic std_msgs rospy roscpp geometry_msgs turtlesim

Erläuterung: learning_topic ist der Name des Funktionskits

Pakete bauen

bash
cd ~/catkin_ws
catkin_make
source ~/catkin_ws/devel/setup.bash

Einen Publisher erstellen

Erstellungsschritte

  1. Initialisierung der ROS-Nodes

  2. Handles erstellen

  3. Registrierung der Node-Informationen beim ROS Master, einschließlich Name und Typ der veröffentlichten Informationen sowie der Länge der Warteschlange

  4. Nachrichtendaten erstellen und initialisieren

  5. Nachricht in einer bestimmten Frequenz in einer Schleife veröffentlichen

C++ Implementierung

  1. 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)
bash
touch turtle_velocity_publisher.cpp # create the file
vim turtle_velocity_publisher.cpp # edit the file
  1. Kopieren Sie den folgenden Programmcode in die Datei turtle_velocity_publisher.cpp

Code-Datei: 7-2-1-4-publisher-turtle_velocity_publisher.cpp

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:

bash
catkin_ws/
├── CMakeLists.txt
└── src/
    ├── CMakeLists.txt
    └── learning_topic/
        ├── CMakeLists.txt
        ├── package.xml
        └── src/
            └── turtle_velocity_publisher.cpp
  1. Flussdiagramm des Programms, das dem Inhalt von 1.3.1 entspricht

  2. 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

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

  1. Kompilieren Sie den Code im Workspace-Verzeichnis neu
bash
cd ~/catkin_ws
catkin_make
source devel/setup.bash     # source the workspace so ROS can find the program

Programm ausführen

Öffnen Sie das erste Terminal und führen Sie roscore aus:

bash
roscore

Führen Sie den Little-Turtle-Node aus

bash
rosrun turtlesim turtlesim_node

Führen Sie den Publisher aus, der kontinuierlich Geschwindigkeit an die Schildkröte sendet.

bash
rosrun learning_topic turtle_velocity_publisher
  1. Erwartetes Ergebnis

  2. 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

  1. 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

  2. Kopieren Sie den folgenden Programmcode in die Datei turtle_velocity_publisher.py

Code-Datei: 7-2-1-4-publisher-suffix.py

python
#!/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
  1. PROJEKT-Flussdiagramm

  2. Programm ausführen

Öffnen Sie das erste Terminal und führen Sie roscore aus

bash
roscore

Führen Sie den Little-Turtle-Node aus

bash
rosrun turtlesim turtlesim_node

Führen Sie den Publisher aus, der kontinuierlich Geschwindigkeit an die Schildkröte sendet.

bash
rosrun learning_topic turtle_velocity_publisher.py

Hinweis: 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.

bash
sudo chmod a+x turtle_velocity_publisher.py

Alle Python-Dateien benötigen Ausführungsberechtigungen, sonst gibt es Fehler!

Abbildungen

7.2.1.4 Publisher Abbildung 1

7.2.1.4 Publisher Abbildung 2

7.2.1.4 Publisher Abbildung 3

7.2.1.4 Publisher Abbildung 4

7.2.1.4 Publisher Abbildung 5

7.2.1.4 Publisher Abbildung 6

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

  1. Initialisierung der ROS-Nodes

  2. Handles erstellen

  3. Topics zum Abonnieren

  4. Topic-Nachricht in einer Schleife empfangen und an die Callback-Funktion zurückgeben

  5. Nachrichtenverarbeitung in einer Callback-Funktion abschließen

Der Workspace dieses Kapitels folgt dem in Abschnitt IV erstellten Workspace.

C++ Implementierung

  1. Erstellen Sie eine neue C++-Datei im src-Ordner des erstellten Pakets unter dem Tutorial-Verzeichnis 'publishing' namens turtle_pose_subscriber.cpp

  2. Kopieren Sie den folgenden Programmcode in die Datei turtle_pose_subscriber.cpp

Code-Datei: 7-2-1-5-subscriber-subscriber.cpp

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;
}
bash
catkin_ws/
├── CMakeLists.txt
└── src/
    ├── CMakeLists.txt
    └── learning_topic/
        ├── CMakeLists.txt
        ├── package.xml
        └── src/
            └── turtle_velocity_publisher.cpp
            └── turtle_pose_subscriber.cpp
  1. Flussdiagramm des Programms, das dem Inhalt von 5.2.1 entspricht

  2. Fügen Sie in catkin_ws/src/learning_topic/CMakeLists.txt unter dem Build-Bereich Folgendes hinzu:

(vim Grundlagen: 14 mit Vim-Editor)

bash
Add executeable (turtle pose subscriber src/turtle_pose_subscriber.cpp)
{\cHFFFFFF}{\cH00FFFF}
  1. Code im Workspace-Verzeichnis kompilieren
bash
cd ~/catkin_ws
catkin_make
source devel/setup.bash     # source the workspace so ROS can find the program

Programm ausführen

Öffnen Sie das erste Terminal und führen Sie roscore aus

bash
roscore

Das zweite Terminal führt den Schildkröten-Node aus.

bash
rosrun turtlesim turtlesim_node

Das dritte Terminal führt den Abonnement-Node aus und empfängt kontinuierlich Daten über die Zustellposition der Schildkröten

bash
rosrun learning_topic turtle_pose_subscriber
  1. 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

  1. 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

  2. Kopieren Sie den folgenden Programmcode in die Datei turtle_pose_subscriber.py

Code-Datei: 7-2-1-5-subscriber-suffix.py

python
#!/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()
  1. PROJEKT-Flussdiagramm

  2. Programm ausführen

Führen Sie roscore aus

bash
roscore

Führen Sie den Little-Turtle-Node aus

bash
rosrun turtlesim turtlesim_node

Führen Sie den Subscriber aus und empfangen Sie kontinuierlich Daten über die Zustellposition der Schildkröte

bash
rosrun learning_topic turtle_pose_subscriber.py

Abbildungen

7.2.1.5 Subscriber Abbildung 1

7.2.1.5 Subscriber Abbildung 2

7.2.1.5 Subscriber Abbildung 3

7.2.1.5 Subscriber Abbildung 4

7.2.1.5 Subscriber Abbildung 5# 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:

bash
cd ~/catkin_ws/src/learning_topic
mkdir -p msg
vim msg/Information.msg

Code-Datei: 7-2-1-6-custom-topic-messages-and-usage-Information.msg

msg
string company
string city

package.xml aktualisieren

Fügen Sie Nachrichtengenerierungs-/Laufzeitabhängigkeiten zu package.xml hinzu:

xml
<build_depend>message_generation</build_depend>
<exec_depend>message_runtime</exec_depend>

CMakeLists.txt aktualisieren

Fügen Sie die Nachrichtengenerierung zu CMakeLists.txt hinzu:

cmake
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:

bash
cd ~/catkin_ws
catkin_make
source devel/setup.bash

C++ 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

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

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:

cmake
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:

bash
cd ~/catkin_ws
catkin_make
source devel/setup.bash
roscore
rosrun learning_topic Information_publisher
rosrun learning_topic Information_subscriber

Python 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

python
#!/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

python
#!/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()
bash
chmod +x scripts/Information_publisher.py scripts/Information_subscriber.py
roscore
rosrun learning_topic Information_publisher.py
rosrun learning_topic Information_subscriber.py

Abbildungen

7.2.1.6 Benutzerdefinierte Topic-Nachrichten und Verwendung Abbildung 1

7.2.1.6 Benutzerdefinierte Topic-Nachrichten und Verwendung Abbildung 2

7.2.1.6 Benutzerdefinierte Topic-Nachrichten und Verwendung Abbildung 3

7.2.1.6 Benutzerdefinierte Topic-Nachrichten und Verwendung Abbildung 4

7.2.1.6 Benutzerdefinierte Topic-Nachrichten und Verwendung Abbildung 5

7.2.1.6 Benutzerdefinierte Topic-Nachrichten und Verwendung Abbildung 6

7.2.1.6 Benutzerdefinierte Topic-Nachrichten und Verwendung Abbildung 7

7.2.1.6 Benutzerdefinierte Topic-Nachrichten und Verwendung Abbildung 8

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

  1. Wechseln Sie zu ~/catkin_ws/src, Terminalausführung:
bash
catkin_create_pkg learning_server std_msgs rospy roscpp geometry_msgs turtlesim

Wechseln Sie zum ~ Verzeichnis, um die Kompilierung auszuführen:

bash
catkin_make

C++ Implementierung

Schritte zur Realisierung

  1. Initialisierung der ROS-Nodes

  2. Handles erstellen

  3. Erstellen Sie eine Instanz des Clients

  4. Initialisieren und veröffentlichen Sie Service-Anfragedaten

  5. 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

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;
};
  1. Flussdiagramm des Verfahrens
  1. 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

cmake
add_executable(a_new_turtle src/a_new_turtle.cpp)
target_link_libraries(a_new_turtle ${catkin_LIBRARIES})
  1. Kompilieren Sie den Code im Workspace-Verzeichnis neu
bash
cd ~/catkin_ws
catkin_make
source devel/setup.bash     # source the workspace so ROS can find the program
  1. Öffnen Sie drei Terminal-Programme
bash
roscore
rosrun turtlesim turtlesim_node
rosrun learning_server a_new_turtle
  1. Erwartetes Ergebnis

  2. 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

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

python
#!/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)
  1. Flussdiagramm des Verfahrens

  2. Öffnen von drei Terminal-Programmen

bash
roscore
rosrun turtlesim turtlesim_node
rosrun learning_server a_new_turtle.py
  1. 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.7 Client Abbildung 1

7.2.1.7 Client Abbildung 2

7.2.1.7 Client Abbildung 3

7.2.1.7 Client Abbildung 4

7.2.1.7 Client Abbildung 5

7.2.1.7 Client Abbildung 6

7.2.1.7 Client Abbildung 7

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

  1. Initialisierung der ROS-Nodes

  2. Beispiele für die Erstellung von Server

  3. Schleife, die auf Service-Anfragen wartet und in eine Callback-Funktion eintritt

  4. 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

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;
}
  1. Flussdiagramm des Verfahrens
  1. 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

cmake
add_executable(turtle_vel_command_server src/turtle_vel_command_server.cpp)
target_link_libraries(turtle_vel_command_server ${catkin_LIBRARIES})
  1. Code im Workspace-Verzeichnis kompilieren
bash
cd ~/catkin_ws
catkin_make
source devel/setup.bash     # source the workspace so ROS can find the program
  1. Starten von vier Terminal-Programmen
bash
roscore
rosrun turtlesim turtlesim_node
rosrun learning_server turtle_vel_command_server
rosservice call /turtle_vel_command
  1. Erwartetes Ergebnis

  2. 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

python
#!/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()
  1. Flussdiagramm des Verfahrens
  1. Öffnen Sie drei Terminal-Programme:
bash
roscore
rosrun turtlesim turtlesim_node
rosrun learning_server turtle_vel_command_server.py
  1. Die Auswirkungen des Betriebs des Verfahrens und die Beschreibung des Verfahrens stimmen mit den durch C++ erzielten überein.

Abbildungen

7.2.1.8 Server Abbildung 1

7.2.1.8 Server Abbildung 2

7.2.1.8 Server Abbildung 3

7.2.1.8 Server Abbildung 4

7.2.1.8 Server Abbildung 5

7.2.1.8 Server Abbildung 6

7.2.1.8 Server Abbildung 7# 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

bash
cd ~/catkin_ws/src/learning_server
mkdir -p srv
vim srv/IntPlus.srv

Code-Datei: 7-2-1-9-custom-service-messages-and-usage-IntPlus.srv

srv
int64 a
int64 b
---
int64 result

package.xml und CMakeLists.txt aktualisieren

Fügen Sie diese Abhängigkeiten zu package.xml hinzu:

xml
<build_depend>message_generation</build_depend>
<exec_depend>message_runtime</exec_depend>

Fügen Sie die Service-Generierung zu CMakeLists.txt hinzu:

cmake
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:

bash
cd ~/catkin_ws
catkin_make
source devel/setup.bash

C++ Server und Client

Code-Datei: 7-2-1-9-custom-service-messages-and-usage-IntPlus_server.cpp

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

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:

cmake
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:

bash
roscore
rosrun learning_server IntPlus_server
rosrun learning_server IntPlus_client

Sie können den Service auch direkt aufrufen:

bash
rosservice call /Two_Int_Plus 5 6

Python Server und Client

Code-Datei: 7-2-1-9-custom-service-messages-and-usage-IntPlus_server.py

python
#!/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

python
#!/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)
bash
chmod +x scripts/IntPlus_server.py scripts/IntPlus_client.py
roscore
rosrun learning_server IntPlus_server.py
rosrun learning_server IntPlus_client.py

Abbildungen

7.2.1.9 Benutzerdefinierte Service-Nachrichten und Verwendung Abbildung 1

7.2.1.9 Benutzerdefinierte Service-Nachrichten und Verwendung Abbildung 2

7.2.1.9 Benutzerdefinierte Service-Nachrichten und Verwendung Abbildung 3

7.2.1.9 Benutzerdefinierte Service-Nachrichten und Verwendung Abbildung 4

7.2.1.9 Benutzerdefinierte Service-Nachrichten und Verwendung Abbildung 5

7.2.1.9 Benutzerdefinierte Service-Nachrichten und Verwendung Abbildung 6

7.2.1.9 Benutzerdefinierte Service-Nachrichten und Verwendung Abbildung 7

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

  1. Abfangen der tf-Transformation

Empfängt alle im Cachesystem veröffentlichten Koordinaten, transformiert die Daten und sucht daraus die benötigten Koordinaten.

  1. 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

bash
cd ~/catkin_ws/src
catkin_create_pkg learning_tf rospy roscpp turtlesim tf
cd..
catkin_make

Wie man einen tf-Sender erreicht

  1. Definition des TF-Senders (Transform Broadcaster);

  2. Initialisierung der tf-Daten und Erstellung von Koordinaten;

  3. Veröffentlichung der Koordinatenkonvertierung (sendTransform);

Wie man ein tf-Abhörgerät erreicht

  1. Definition des TF-Abhörgeräts (TransformListener);

  2. Koordinaten finden (waitForTransform, lookupTransform)

C++ Sprachrealisierung des tf-Senders

  1. Erstellen Sie eine C++-Datei (Datei mit der Endung .cpp) im src-Ordner des Pakets

  2. 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

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;
};
  1. PROJEKT-Flussdiagramm

  2. 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

  1. Erstellen Sie eine C++-Datei (Datei mit der Endung .cpp) im src-Ordner des Pakets

  2. 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

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;
};
  1. PROJEKT-Flussdiagramm

  2. 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

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

  1. Ä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

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})
  1. Implementierungsdokumente kompilieren
bash
cd ~/catkin_ws
catkin_make
source devel/setup.bash     # source the workspace so ROS can find the program

Demonstration von Start und Betriebseffekten

  1. Öffnen Sie sechs Terminals und führen Sie die folgenden Befehle aus:
bash
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
  1. 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

  1. 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

  2. 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

python
#!/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()
  1. PROJEKT-Flussdiagramm

Python-Sprache erreicht tf-Abhörgeräte

  1. Erstellen Sie eine Python-Datei (Datei mit der Endung .py) im scripts-Ordner des Pakets learning_tf namens turtle_tf_listener.py

  2. 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

python
#!/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()
  1. PROJEKT-Flussdiagramm

Demonstration von Start und Betriebseffektivität

  1. 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

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>
  1. Start
bash
roslaunch learning_tf start_tf_demo_py.launch

Wenn 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.

  1. Die Betriebseffekte sind weitgehend konsistent mit C++

Abbildungen

7.2.1.10 Veröffentlichen und Abhören mit TF Abbildung 1

7.2.1.10 Veröffentlichen und Abhören mit TF Abbildung 2

7.2.1.10 Veröffentlichen und Abhören mit TF Abbildung 3

7.2.1.10 Veröffentlichen und Abhören mit TF Abbildung 4

7.2.1.10 Veröffentlichen und Abhören mit TF Abbildung 5

7.2.1.10 Veröffentlichen und Abhören mit TF Abbildung 6

7.2.1.10 Veröffentlichen und Abhören mit TF Abbildung 7