7.1.4-ROS-Kommunikationsmechanismus:
Tutorial zur Topic-Kommunikation
Einführung in die Topic-Kommunikation
In ROS ist die Topic-Kommunikation eine der grundlegenden Möglichkeiten für Knoten, Informationen auszutauschen. Dieses Tutorial führt Sie durch das Einrichten der grundlegenden Topic-Kommunikation mit C++ und Python. Wir implementieren ein einfaches Publisher-Subscriber-Modell, bei dem der Publisher Textnachrichten mit einer Frequenz von 10Hz sendet und der Subscriber diese Nachrichten empfängt und ausgibt.
1. Theoretisches Modell
Die Topic-Kommunikation umfasst drei Hauptkomponenten:
- ROS Master: Verwaltet die Registrierung und Verbindung der Knoten.
- Talker (Publisher): Sendet Nachrichten.
- Listener (Subscriber): Empfängt Nachrichten.
Der ROS Master hilft beim Aufbau der Verbindungen zwischen Talkers und Listeners. Hier eine schrittweise Beschreibung des Kommunikationsablaufs:
- Talker-Registrierung: Der Talker registriert sich beim ROS Master und gibt den Topic-Namen seiner Nachrichten an.
- Listener-Registrierung: Der Listener registriert sich beim ROS Master und gibt das Topic an, das er abonnieren möchte.
- Zuordnung: Der ROS Master ordnet Talker und Listener anhand des Topic-Namens zu und sendet die nötigen Verbindungsinformationen.
- Verbindungsaufbau: Der Listener fordert eine Verbindung zum Talker an, der Talker bestätigt sie.
- Nachrichtenaustausch: Sobald die Verbindung steht, beginnt der Talker damit, Nachrichten an den Listener zu senden.
Wichtige Punkte:
- Der ROS Master wird nur für den Verbindungsaufbau benötigt.
- Die Kommunikation läuft weiter, auch wenn der ROS Master nach Verbindungsaufbau heruntergefahren wird.
- Es können mehrere Talker und Listener existieren und in beliebiger Reihenfolge gestartet werden.
2. Grundlegende Topic-Kommunikationsoperationen (C++)
Ziel: Erstellen eines Publisher-Knotens, der Textnachrichten mit 10Hz sendet, und eines Subscriber-Knotens, der die empfangenen Nachrichten ausgibt.
Schritte:
-
bash
cd ~/seeed_ws/src/ catkin_create_pkg listener_and_talker roscpp rospy std_msgs cd ~/seeed_ws/src/listener_and_talker/src touch listener.cpp talker.cpp -
Publisher-Implementierung:
talker.cppcpp#include "ros/ros.h" #include "std_msgs/String.h" #include <sstream> int main(int argc, char *argv[]) { // Set locale for printing messages in the local language setlocale(LC_ALL, ""); // Initialize the ROS node with a unique name ros::init(argc, argv, "talker"); // Create a ROS node handle ros::NodeHandle nh; // Create a publisher object ros::Publisher pub = nh.advertise<std_msgs::String>("chatter", 10); std_msgs::String msg; std::string msg_front = "Hello Seeed"; int count = 0; ros::Rate r(10); // 10Hz while (ros::ok()) { std::stringstream ss; ss << msg_front << count; msg.data = ss.str(); pub.publish(msg); ROS_INFO("Sent message: %s", msg.data.c_str()); r.sleep(); count++; } return 0; } -
Subscriber-Implementierung:
listener.cppcpp#include "ros/ros.h" #include "std_msgs/String.h" void doMsg(const std_msgs::String::ConstPtr& msg_p) { ROS_INFO("Heard: %s", msg_p->data.c_str()); } int main(int argc, char *argv[]) { setlocale(LC_ALL, ""); ros::init(argc, argv, "listener"); ros::NodeHandle nh; ros::Subscriber sub = nh.subscribe<std_msgs::String>("chatter", 10, doMsg); ros::spin(); return 0; } -
CMakeLists.txt-Konfiguration:
Fügen Sie am Ende der
CMakeLists.txtIhres Pakets den folgenden Code hinzu:cmakeadd_executable(listener src/listener.cpp) add_executable(talker src/talker.cpp) target_link_libraries(listener ${catkin_LIBRARIES}) target_link_libraries(talker ${catkin_LIBRARIES}) -
Code ausführen:
-
Öffnen Sie ein Terminal und starten Sie
roscore:bashroscore -
Öffnen Sie in einem neuen Terminal Ihren Workspace und führen Sie den Publisher-Knoten aus:
bashrosrun listener_and_talker listener -
In einem weiteren Terminal führen Sie den Subscriber-Knoten aus:
bashrosrun listener_and_talker talker
Sie sollten Nachrichten sehen, die im Terminal veröffentlicht und empfangen werden.
3. Grundlegende Topic-Kommunikationsoperationen (Python)
Ziel: Erstellen eines Publisher-Knotens, der Textnachrichten mit 10Hz sendet, und eines Subscriber-Knotens, der die empfangenen Nachrichten ausgibt.
Schritte:
-
bash
cd ~/seeed_ws/src/ catkin_create_pkg listener_and_talker roscpp rospy std_msgs mkdir ~/seeed_ws/src/listener_and_talker/script cd ~/seeed_ws/src/listener_and_talker/script touch listener.py talker.py -
Publisher-Implementierung:
talker.pypython#!/usr/bin/env python import rospy from std_msgs.msg import String if __name__ == "__main__": rospy.init_node("talker_p") pub = rospy.Publisher("chatter", String, queue_size=10) msg = String() msg_front = "hello 你好" count = 0 rate = rospy.Rate(10) # 10Hz while not rospy.is_shutdown(): msg.data = msg_front + str(count) pub.publish(msg) rospy.loginfo("Sent message: %s", msg.data) rate.sleep() count += 1 -
Subscriber-Implementierung:
listener.pypython#!/usr/bin/env python import rospy from std_msgs.msg import String def doMsg(msg): rospy.loginfo("Heard: %s", msg.data) if __name__ == "__main__": rospy.init_node("listener_p") sub = rospy.Subscriber("chatter", String, doMsg, queue_size=10) rospy.spin() -
Ausführungsrechte vergeben:
bashsudo chmod +x *.py -
CMakeLists.txt-Konfiguration:
Fügen Sie am Ende der
CMakeLists.txtIhres Pakets den folgenden Code hinzu:cmakecatkin_install_python(PROGRAMS scripts/talker.py scripts/listener.py DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION} ) -
Code ausführen:
- Öffnen Sie ein Terminal und starten Sie
roscore:bashroscore - Öffnen Sie in einem neuen Terminal Ihren Workspace und führen Sie den Publisher-Knoten aus:
bash
rosrun listener_and_talker talker.py - In einem weiteren Terminal führen Sie den Subscriber-Knoten aus:
bash
rosrun listener_and_talker listener.py
- Öffnen Sie ein Terminal und starten Sie
Sie sollten Nachrichten sehen, die im Terminal veröffentlicht und empfangen werden.
Häufige ROS-Topic-Befehle
rostopic bw: Zeigt die Bandbreitennutzung eines Topics anrostopic delay: Zeigt die Verzögerung eines Topics mit Header anrostopic echo: Gibt Nachrichten auf dem Bildschirm ausrostopic find: Sucht Topics nach Typrostopic hz: Zeigt die Veröffentlichungsfrequenz eines Topics anrostopic info: Zeigt Informationen zu einem Topic anrostopic list: Listet alle aktiven Topics aufrostopic pub: Veröffentlicht Daten auf einem Topicrostopic type: Gibt den Typ eines Topics aus
Einführung in die Service-Kommunikation
Die Service-Kommunikation in ROS unterscheidet sich von der Topic-Kommunikation darin, dass sie bidirektional ist. Sie erlaubt nicht nur das Senden von Nachrichten, sondern auch den Empfang von Antworten. Dieses Modell besteht aus zwei Hauptteilen:
- Client: Die Entität, die eine Anfrage sendet.
- Server: Die Entität, die die Anfrage verarbeitet und eine Antwort zurücksendet.
Wenn ein Client eine Anfrage an einen Server sendet, wartet er, bis der Server die Anfrage verarbeitet und eine Antwort zurückgibt. Dieses Vorgehen folgt einer „Anfrage-Antwort"-Struktur und schließt damit die Kommunikation ab.
Wie funktioniert es?
- Knoten B (der Server) bietet eine Service-Schnittstelle, üblicherweise mit einem Namen wie
/service_name. - Knoten A (der Client) sendet eine Anfrage an Knoten B.
- Knoten B verarbeitet die Anfrage und sendet eine Antwort zurück.
Der Kommunikationsablauf lässt sich wie folgt darstellen:
-
Talker-Knoten kündigt einen Service über den ROS Master an:
- Der Talker-Knoten kündigt einen Service (z. B.
advertiseService("bar", foo:1234)) über den ROS Master an und signalisiert damit seine Verfügbarkeit.
- Der Talker-Knoten kündigt einen Service (z. B.
-
Listener-Knoten sucht den Service über den ROS Master:
- Der Listener-Knoten sendet eine Anfrage an den ROS Master, um den Service zu finden (z. B.
lookupService("bar")).
- Der Listener-Knoten sendet eine Anfrage an den ROS Master, um den Service zu finden (z. B.
-
ROS Master gibt die Service-Adresse zurück:
- Der ROS Master antwortet mit der Service-Adresse (z. B.
foo:3456), damit sich der Listener-Knoten verbinden kann.
- Der ROS Master antwortet mit der Service-Adresse (z. B.
-
Listener-Knoten fordert Daten vom Talker-Knoten an:
- Der Listener-Knoten sendet eine Service-Anfrage an den Talker-Knoten, wobei XML/RPC für die Kommunikation verwendet wird.
-
Talker-Knoten antwortet mit den angeforderten Daten:
- Der Talker-Knoten verarbeitet die Anfrage und sendet die Antwortdaten über TCP zurück.
Wichtige Punkte:
- Der Client wird blockiert, bis er eine Antwort vom Server erhält.
- Die Service-Kommunikation ist effizient, da sie nur bei Bedarf (d. h. wenn eine Anfrage gestellt wird) Ressourcen verbraucht.
Theoretisches Modell
Das Service-Kommunikationsmodell umfasst drei zentrale Komponenten:
- ROS Master: Verwaltet die Registrierung sowohl von Servern als auch von Clients und hilft, Verbindungen anhand übereinstimmender Service-Namen herzustellen.
- Server: Bietet den Service an.
- Client: Fordert den Service an.
Prozessübersicht:
-
Server-Registrierung:
- Der Server registriert sich beim ROS Master und gibt den Namen des bereitgestellten Service an.
-
Client-Registrierung:
- Der Client registriert sich beim ROS Master und gibt den Service an, den er nutzen möchte.
-
Zuordnung und Verbindung:
- Der ROS Master ordnet Client und Server anhand des Service-Namens zu und ermöglicht die Verbindung.
-
Anfrage-Antwort-Zyklus:
- Der Client sendet eine Anfrage an den Server, der diese verarbeitet und eine Antwort zurückgibt.
Topic- vs. Service-Kommunikation
Vergleichen wir diese beiden gängigsten ROS-Kommunikationsmethoden, um unser Verständnis zu vertiefen:
| Aspekt | Topic-Kommunikation | Service-Kommunikation |
|---|---|---|
| Kommunikationstyp | Asynchron | Synchron |
| Protokoll | TCP/IP | TCP/IP |
| Kommunikationsmodell | Publish-Subscribe | Anfrage-Antwort |
| Beziehung | Viele-zu-Viele | Eins-zu-Viele |
| Eigenschaften | Callback-basiert | Remote Procedure Call (RPC) |
| Anwendungsfälle | Kontinuierliche, hochfrequente Daten | Niederfrequente, spezielle Aufgaben |
| Beispiel | Veröffentlichung von LiDAR-Daten | Auslösen eines Sensors oder Aufnehmen eines Fotos |
Hinweis: Remote Procedure Call (RPC) bedeutet, dass eine Funktion in einem anderen Prozess ausgeführt wird, als wäre sie lokal.
5. Erstellen eines benutzerdefinierten Service (srv) in ROS
Tauchen wir in ein praktisches Beispiel ein, in dem wir einen benutzerdefinierten Service erstellen, der zwei vom Client gesendete Ganzzahlen addiert. Der Server verarbeitet diese Anfrage und gibt die Summe an den Client zurück.
Schritte zur Implementierung:
-
Ein neues Paket erstellen
bashcd ~/seeed_ws/src catkin_create_pkg service_communication roscpp rospy std_msgs cd ~/seeed_ws catkin_make -
srv-Datei definieren: Die
srv-Datei definiert die Struktur der Anfrage und der Antwort. In diesem Fall enthält die Anfrage zwei Ganzzahlen und die Antwort deren Summe. Erstellen Sie ein neues Verzeichnis namenssrvin Ihrem Paket und fügen Sie eine Datei namensAddInts.srvhinzu:bashmkdir ~/seeed_ws/src/service_communication/srv cd ~/seeed_ws/src/service_communication/srv touch AddInts.srvKopieren Sie Folgendes in
AddInts.srv:srvint32 num1 int32 num2 --- int32 sum -
package.xml aktualisieren: Fügen Sie die nötigen Abhängigkeiten zur Generierung von Nachrichtendateien in der
package.xmldes Pakets hinzu:xml<build_depend>message_generation</build_depend> <exec_depend>message_runtime</exec_depend> -
CMakeLists.txt aktualisieren:
-
Paket kompilieren:
- Kompilieren Sie Ihr Paket, um die Service-Nachrichten-Header zu generieren:
bash
cd ~/seeed_ws catkin_make source devel/setup.bash
- Kompilieren Sie Ihr Paket, um die Service-Nachrichten-Header zu generieren:
Service-Kommunikation implementieren (C++)
Dieses Beispiel zeigt, wie man Service-Kommunikation in ROS mit C++ implementiert. Wir erstellen einen einfachen Service, bei dem der Server zwei vom Client bereitgestellte Ganzzahlen addiert und die Summe zurückgibt.
1. Server-Implementierung:
add_two_ints_server.cpp
#include "ros/ros.h"
#include "service_communication/AddInts.h"
// Callback function to handle the client's request
bool add(service_communication::AddInts::Request &req,
service_communication::AddInts::Response &res) {
res.sum = req.num1 + req.num2; // Compute the sum
ROS_INFO("Request: a=%ld, b=%ld", (long int)req.num1, (long int)req.num2);
ROS_INFO("Sending back response: [%ld]", (long int)res.sum);
return true;
}
int main(int argc, char **argv) {
ros::init(argc, argv, "add_two_ints_server");
ros::NodeHandle nh;
// Advertise the service to the ROS master
ros::ServiceServer service = nh.advertiseService("add_two_ints", add);
ROS_INFO("Ready to add two integers.");
ros::spin();
return 0;
}2. Client-Implementierung:
add_two_ints_client.cpp
#include "ros/ros.h"
#include "service_communication/AddInts.h"
#include <cstdlib>
int main(int argc, char **argv) {
ros::init(argc, argv, "add_two_ints_client");
if (argc != 3) {
ROS_INFO("Usage: add_two_ints_client X Y");
return 1;
}
ros::NodeHandle nh;
ros::ServiceClient client = nh.serviceClient<service_communication::AddInts>("add_two_ints");
// Prepare the service request
service_communication::AddInts srv;
srv.request.num1 = atoll(argv[1]);
srv.request.num2 = atoll(argv[2]);
// Call the service and check if it was successful
if (client.call(srv)) {
ROS_INFO("Sum: %ld", (long int)srv.response.sum);
} else {
ROS_ERROR("Failed to call service add_two_ints");
return 1;
}
return 0;
}CMakeLists.txt-Konfiguration:
Fügen Sie unbedingt die folgenden Zeilen am Ende von CMakeLists.txt hinzu, um sowohl den Server als auch den Client zu kompilieren:
add_executable(add_two_ints_server src/add_two_ints_server.cpp)
add_executable(add_two_ints_client src/add_two_ints_client.cpp)
add_dependencies(add_two_ints_server ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS})
add_dependencies(add_two_ints_client ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS})
target_link_libraries(add_two_ints_server ${catkin_LIBRARIES})
target_link_libraries(add_two_ints_client ${catkin_LIBRARIES})Demo kompilieren und ausführen
Öffnen Sie ein Terminal:
cd ~/seeed_ws
catkin_make
roscoreÖffnen Sie ein weiteres Terminal:
cd ~/seeed_ws
source devel/setup.bash
rosrun service_communication serverÖffnen Sie ein weiteres Terminal:
cd ~/seeed_ws
source devel/setup.bash
rosrun service_communication client 1 5Service-Kommunikation implementieren (Python)
Dieses Python-Beispiel erfüllt dieselbe Funktion wie das C++-Beispiel, in dem ein Service zum Addieren zweier Ganzzahlen verwendet wird.
Erstellen Sie unter dem Paket einen Ordner scripts und darin die Dateien add_two_ints_server.py und add_two_ints_client.py.
cd ~/seeed/src/service_communication/
mkdir scripts
cd scripts
touch add_two_ints_server.py add_two_ints_client.py1. Server-Implementierung:
add_two_ints_server.py
#!/usr/bin/env python
import rospy
from service_communication.srv import AddInts,AddIntsRequest, AddIntsResponse
def doReq(req):
sum = req.num1 + req.num2
rospy.loginfo("data:num1 = %d, num2 = %d, sum = %d",req.num1, req.num2, sum)
resp = AddIntsResponse(sum)
return resp
if __name__ == "__main__":
rospy.init_node("addints_server_p")
server = rospy.Service("AddInts",AddInts,doReq)
rospy.spin()2. Client-Implementierung:
add_two_ints_client.py
#!/usr/bin/env python
import sys
import rospy
from service_communication.srv import *
if __name__ == "__main__":
if len(sys.argv) != 3:
rospy.logerr("error")
sys.exit(1)
rospy.init_node("AddInts_Client_p")
client = rospy.ServiceProxy("AddInts",AddInts)
client.wait_for_service()
req = AddIntsRequest()
req.num1 = int(sys.argv[1])
req.num2 = int(sys.argv[2])
resp = client.call(req)
rospy.loginfo("result:%d",resp.sum)CMakeLists.txt-Konfiguration:
Fügen Sie für die Python-Skripte folgende Zeilen in Ihrer CMakeLists.txt hinzu:
catkin_install_python(PROGRAMS
scripts/add_two_ints_server.py
scripts/add_two_ints_client.py
DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}
)Demo kompilieren und ausführen
Öffnen Sie ein Terminal:
cd ~/seeed_ws
catkin_make
roscoreÖffnen Sie ein weiteres Terminal:
cd ~/seeed_ws
source devel/setup.bash
rosrun service_communication add_two_ints_server.pyÖffnen Sie ein weiteres Terminal:
cd ~/seeed_ws
source devel/setup.bash
rosrun service_communication add_two_ints_client.py 1 5Befehle der Service-Kommunikation
Um in ROS mit Services zu arbeiten, verwenden Sie den Befehl rosservice. Hier eine Liste gängiger rosservice-Befehle und ihrer Funktionen:
rosservice args: Gibt die für einen Service erforderlichen Argumente ausrosservice call: Ruft einen Service mit den angegebenen Argumenten aufrosservice find: Sucht Services nach Typrosservice info: Gibt Informationen zu einem Service ausrosservice list: Listet alle aktiven Services aufrosservice type: Gibt den Typ eines Service ausrosservice uri: Gibt die ROSRPC-URI eines Service aus
Einführung in den ROS-Parameter-Server
Der ROS-Parameter-Server ist ein gemeinsam genutzter, multinutzerfähiger und über das Netzwerk zugänglicher Speicherbereich für Parameter. Er bietet eine Möglichkeit, Parameter zur Laufzeit zu speichern und abzurufen, die zur Konfiguration von Knoten oder zum Datenaustausch zwischen ihnen verwendet werden können. Parameter auf dem Server können verschiedener Datentypen sein, einschließlich Ganzzahlen, Booleans, Strings, Doubles, Listen und Dictionaries. Der Parameter-Server wird vom ROS Master verwaltet und Knoten interagieren mit ihm, indem sie Parameter setzen, abrufen oder löschen.
Theoretisches Modell des Parameter-Servers
Der Parameter-Server umfasst drei Hauptrollen:
- ROS Master: Verwaltet den Parameter-Server und fungiert als zentraler Speicher für Parameter.
- Talker: Ein Knoten, der Parameter auf dem Server setzt.
- Listener: Ein Knoten, der Parameter vom Server abruft.
Der Interaktionsprozess mit dem Parameter-Server umfasst typischerweise folgende Schritte:
-
Parameter setzen (Talker):
- Der Talker-Knoten sendet einen Parameter über RPC (Remote Procedure Call) an den Parameter-Server, einschließlich Name und Wert des Parameters. Der ROS Master speichert diesen Parameter in seiner Liste.
-
Parameter abrufen (Listener):
- Der Listener-Knoten fordert einen Parameter vom Parameter-Server an, indem er eine Anfrage mit dem Parameternamen sendet.
-
Parameter zurückgeben (ROS Master):
- Der ROS Master sucht den angeforderten Parameter in seinem Speicher und gibt den entsprechenden Wert an den Listener zurück.
Unterstützte Datentypen:
- 32-Bit-Ganzzahlen
- Booleans
- Strings
- Doubles
- ISO8601-Daten
- Listen
- Base64-codierte Binärdaten
- Dictionaries
C++-Implementierung
Parameter setzen (C++):
Wir beginnen damit, mit zwei verschiedenen APIs verschiedene Arten von Parametern auf dem Parameter-Server zu setzen: ros::NodeHandle und ros::param.
set_parameters.cpp
#include "ros/ros.h"
int main(int argc, char *argv[]) {
ros::init(argc, argv, "set_parameters");
std::vector<std::string> students = {"Alice", "Bob", "Charlie", "David"};
std::map<std::string, std::string> friends = {{"John", "Doe"}, {"Jane", "Smith"}};
// Using ros::NodeHandle to set parameters
ros::NodeHandle nh;
nh.setParam("int_param", 42);
nh.setParam("double_param", 3.14159);
nh.setParam("bool_param", true);
nh.setParam("string_param", "Hello ROS");
nh.setParam("vector_param", students);
nh.setParam("map_param", friends);
// Using ros::param to set parameters
ros::param::set("int_param_param", 84);
ros::param::set("double_param_param", 6.28318);
ros::param::set("bool_param_param", false);
ros::param::set("string_param_param", "Goodbye ROS");
ros::param::set("vector_param_param", students);
ros::param::set("map_param_param", friends);
return 0;
}Fügen Sie am Ende der CMakeLists.txt Ihres Pakets folgenden Code hinzu:
add_executable(set_parameters src/set_parameters.cpp)
target_link_libraries(set_parameters ${catkin_LIBRARIES})In diesem Beispiel:
- Wir setzen verschiedene Arten von Parametern auf dem Parameter-Server, einschließlich Ganzzahlen, Doubles, Booleans, Strings, Vektoren und Maps.
- Wir verwendeten sowohl die
ros::NodeHandle- als auch dieros::param-API, um die Parameter zu setzen.
Parameter abrufen (C++):
Als Nächstes rufen wir die zuvor gesetzten Parameter ab.
get_parameters.cpp
#include "ros/ros.h"
int main(int argc, char *argv[]) {
ros::init(argc, argv, "get_parameters");
// Using ros::NodeHandle to retrieve parameters
ros::NodeHandle nh;
int int_value;
double double_value;
bool bool_value;
std::string string_value;
std::vector<std::string> students;
std::map<std::string, std::string> friends;
nh.getParam("int_param", int_value);
nh.getParam("double_param", double_value);
nh.getParam("bool_param", bool_value);
nh.getParam("string_param", string_value);
nh.getParam("vector_param", students);
nh.getParam("map_param", friends);
ROS_INFO("Retrieved values:");
ROS_INFO("int_param: %d", int_value);
ROS_INFO("double_param: %.5f", double_value);
ROS_INFO("bool_param: %d", bool_value);
ROS_INFO("string_param: %s", string_value.c_str());
for (const auto &student : students) {
ROS_INFO("Student: %s", student.c_str());
}
for (const auto &friend_pair : friends) {
ROS_INFO("Friend: %s = %s", friend_pair.first.c_str(), friend_pair.second.c_str());
}
return 0;
}Fügen Sie am Ende der CMakeLists.txt Ihres Pakets folgenden Code hinzu:
add_executable(get_parameters src/get_parameters.cpp)
target_link_libraries(get_parameters ${catkin_LIBRARIES})In diesem Beispiel:
- Wir rufen die auf dem Server gesetzten Parameter mithilfe der
ros::NodeHandle-API ab. - Die abgerufenen Parameter werden zur Überprüfung im ROS-Log ausgegeben.
Parameter löschen (C++):
Schließlich sehen wir, wie man Parameter vom Parameter-Server löscht.
delete_parameters.cpp
#include "ros/ros.h"
int main(int argc, char *argv[]) {
ros::init(argc, argv, "delete_parameters");
ros::NodeHandle nh;
bool success;
// Using ros::NodeHandle to delete parameters
success = nh.deleteParam("int_param");
ROS_INFO("Delete int_param: %s", success ? "Success" : "Failure");
// Using ros::param to delete parameters
success = ros::param::del("int_param_param");
ROS_INFO("Delete int_param_param: %s", success ? "Success" : "Failure");
return 0;
}Fügen Sie am Ende der CMakeLists.txt Ihres Pakets folgenden Code hinzu:
add_executable(delete_parameters src/delete_parameters.cpp)
target_link_libraries(delete_parameters ${catkin_LIBRARIES})In diesem Beispiel:
- Wir verwenden sowohl die
ros::NodeHandle- als auch dieros::param-API, um Parameter vom Server zu löschen. - Der Erfolg der Löschung wird protokolliert.
2.2 Python-Implementierung
Parameter setzen (Python):
Setzen wir nun Parameter mit Python. Der Vorgang ist der C++-Version sehr ähnlich.
#!/usr/bin/env python
import rospy
if __name__ == "__main__":
rospy.init_node("set_parameters_py")
# Setting various types of parameters
rospy.set_param("int_param", 42)
rospy.set_param("double_param", 3.14159)
rospy.set_param("bool_param", True)
rospy.set_param("string_param", "Hello ROS")
rospy.set_param("list_param", ["apple", "banana", "cherry"])
rospy.set_param("dict_param", {"first_name": "John", "last_name": "Doe"})
# Modifying a parameter
rospy.set_param("int_param", 84)Fügen Sie am Ende der CMakeLists.txt Ihres Pakets folgenden Code hinzu:
catkin_install_python(PROGRAMS
scripts/set_parameters_py.py
DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}
)In diesem Beispiel:
- Wir setzen verschiedene Arten von Parametern, einschließlich Ganzzahlen, Doubles, Booleans, Strings, Listen und Dictionaries.
- Wir zeigen außerdem, wie man einen vorhandenen Parameter ändert.
Parameter abrufen (Python):
Als Nächstes rufen wir die gesetzten Parameter ab.
#!/usr/bin/env python
import rospy
if __name__ == "__main__":
rospy.init_node("get_parameters_py")
# Retrieving parameters
int_value = rospy.get_param("int_param", 0)
double_value = rospy.get_param("double_param", 0.0)
bool_value = rospy.get_param("bool_param", False)
string_value = rospy.get_param("string_param", "")
list_value = rospy.get_param("list_param", [])
dict_value = rospy.get_param("dict_param", {})
rospy.loginfo("Retrieved values:")
rospy.loginfo("int_param: %d", int_value)
rospy.loginfo("double_param: %.5f", double_value)
rospy.loginfo("bool_param: %s", bool_value)
rospy.loginfo("string_param: %s", string_value)
rospy.loginfo("list_param: %s", list_value)
rospy.loginfo("dict_param: %s", dict_value)Fügen Sie am Ende der CMakeLists.txt Ihres Pakets folgenden Code hinzu:
catkin_install_python(PROGRAMS
scripts/set_parameters_py.py
scripts/get_parameters_py.py
DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}
)In diesem Beispiel:
- Wir verwenden
rospy.get_param, um die auf dem Server gesetzten Parameter abzurufen. - Die abgerufenen Werte werden mit
rospy.loginfoprotokolliert.
Parameter löschen (Python):
Abschließend löschen wir Parameter mit Python vom Parameter-Server.
#!/usr/bin/env python
import rospy
if __name__ == "__main__":
rospy.init_node("delete_parameters_py")
try:
rospy.delete_param("int_param")
rospy.loginfo("int_param deleted successfully.")
except KeyError:
rospy.logwarn("int_param does not exist.")
try:
rospy.delete_param("non_existent_param")
rospy.loginfo("non_existent_param deleted successfully.")
except KeyError:
rospy.logwarn("non_existent_param does not exist.")Fügen Sie am Ende der CMakeLists.txt Ihres Pakets folgenden Code hinzu:
catkin_install_python(PROGRAMS
scripts/set_parameters_py.py
scripts/get_parameters_py.py
scripts/delete_parameters_py.py
DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}
)In diesem Beispiel:
- Wir versuchen, einen Parameter zu löschen, und behandeln den Fall, dass der Parameter nicht existiert, mittels Ausnahmebehandlung (
KeyError).
Häufige Befehle des ROS-Parameter-Servers
rosparam enthält Kommandozeilenwerkzeuge zum Abrufen und Setzen von ROS-Parametern auf dem Parameter-Server unter Verwendung von YAML-codierten Dateien.
rosparam set: Einen Parameter setzenrosparam get: Einen Parameter abrufenrosparam load: Parameter aus einer externen Datei ladenrosparam dump: Parameter in eine externe Datei exportierenrosparam delete: Einen Parameter löschenrosparam list: Alle Parameter auflisten
Beispiele:
rosparam list: Alle Parameter auf dem Parameter-Server auflisten.rosparam set <param_name> <value>: Einen Parameter mit einem bestimmten Wert setzen.rosparam get <param_name>: Den Wert eines bestimmten Parameters abrufen.rosparam delete <param_name>: Einen bestimmten Parameter löschen.rosparam load <file_name.yaml>: Parameter aus einer YAML-Datei laden.rosparam dump <file_name.yaml>: Die aktuellen Parameter in eine YAML-Datei exportieren.