7.1.6-ROS-Betriebsverwaltung

Verwaltung von ROS-Knoten mit Launch-Dateien

Launch-Dateien in ROS sind XML-formatierte Dateien, die zum effizienten Starten und Verwalten mehrerer ROS-Knoten verwendet werden. Dieser Abschnitt behandelt die verschiedenen Tags, die in Launch-Dateien verfügbar sind, einschließlich ihrer Attribute und Anwendungsfälle.

Das <launch>-Tag

Das <launch>-Tag ist die Wurzel jeder Launch-Datei und dient als Container für alle anderen Tags.

1. Attribute

  • deprecated="Veraltungserklärung"
    Zeigt dem Anwender an, dass die aktuelle Launch-Datei veraltet ist.

2. Untergeordnete Tags

  • Alle anderen Tags in einer Launch-Datei sind Kindelemente des <launch>-Tags.

Beispiel:

xml
<launch>
    <!-- Other tags go here -->
</launch>

Das <node>-Tag

Das <node>-Tag wird verwendet, um einen zu startenden ROS-Knoten anzugeben. Es ist eines der am häufigsten verwendeten Tags in einer Launch-Datei. Beachten Sie, dass der Befehl roslaunch nicht garantiert, dass die Knoten in der deklarierten Reihenfolge starten, da der Knotenstart mehrthreaded erfolgt.

1. Attribute

  • pkg="package_name"
    Gibt das Paket an, zu dem der Knoten gehört.

  • type="nodeType"
    Der Typ des Knotens, der dem Namen der ausführbaren Datei entspricht.

  • name="nodeName"
    Der Name des Knotens innerhalb der ROS-Netzwerktopologie.

  • args="xxx xxx xxx" (optional)
    Übergibt Argumente an den Knoten.

  • machine="machine_name"
    Gibt die Maschine an, auf der der Knoten gestartet werden soll.

  • respawn="true | false" (optional)
    Legt fest, ob der Knoten automatisch neu starten soll, wenn er beendet wird.

  • respawn_delay="N" (optional)
    Wenn respawn auf true gesetzt ist, definiert dies eine Verzögerung von N Sekunden, bevor der Knoten neu gestartet wird.

  • required="true | false" (optional)
    Gibt an, ob dieser Knoten kritisch ist. Bei true wird der gesamte roslaunch-Prozess beendet, wenn der Knoten beendet wird.

  • ns="namespace" (optional)
    Startet den Knoten innerhalb des angegebenen Namespaces.

  • clear_params="true | false" (optional)
    Löscht vor dem Knotenstart alle Parameter im privaten Namespace des Knotens.

  • output="log | screen" (optional)
    Legt fest, wohin die Log-Ausgabe gesendet wird: in eine Log-Datei oder auf den Bildschirm. Standard ist log.

2. Untergeordnete Tags

  • env: Zum Setzen von Umgebungsvariablen.
  • remap: Zum Umbenennen von Topic- oder Service-Namen.
  • rosparam: Zum Setzen von Parametern.
  • param: Zum Setzen von Parametern.

Beispiel:

xml
<launch>
    <node name="node1" pkg="my_package" type="node_executable" output="screen" respawn="true" respawn_delay="5">
        <param name="param_name" value="param_value"/>
        <remap from="/old_topic" to="/new_topic"/>
    </node>
</launch>

Das <include>-Tag

Das <include>-Tag wird verwendet, um eine andere XML-formatierte Launch-Datei in die aktuelle Launch-Datei einzubinden. Dies ermöglicht modulare und wiederverwendbare Konfigurationen.

1. Attribute

  • file="$(find package_name)/path/to/file.launch"
    Gibt den Pfad zur einzubindenden Launch-Datei an.

  • ns="namespace" (optional)
    Bindet die Datei unter dem angegebenen Namespace ein.

2. Untergeordnete Tags

  • env: Zum Setzen von Umgebungsvariablen.
  • arg: Zum Übergeben von Argumenten an die eingebundene Launch-Datei.

Beispiel:

xml
<launch>
    <include file="$(find my_package)/launch/another_launch_file.launch" ns="my_namespace"/>
</launch>

Das <remap>-Tag

Das <remap>-Tag wird verwendet, um ROS-Topic- oder Service-Namen umzubenennen. Dies ist nützlich, um Namenskonflikte zu vermeiden oder Namen über verschiedene Knoten hinweg zu vereinheitlichen.

1. Attribute

  • from="xxx"
    Der ursprüngliche Topic- oder Service-Name.

  • to="yyy"
    Der neue Name für das Topic oder den Service.

2. Untergeordnete Tags

  • Keine

Beispiel:

xml
<launch>
    <node name="node1" pkg="my_package" type="node_executable">
        <remap from="/old_topic" to="/new_topic"/>
    </node>
</launch>

Das <param>-Tag

Das <param>-Tag wird verwendet, um Parameter auf dem ROS-Parameter-Server zu setzen. Die Quelle des Parameters kann direkt im Tag angegeben oder aus einer externen Datei geladen werden. Wenn es innerhalb eines <node>-Tags verwendet wird, wird der Parameter im privaten Namespace des Knotens gesetzt.

1. Attribute

  • name="namespace/parameter_name"
    Der Name des Parameters, der einen Namespace enthalten kann.

  • value="xxx" (optional)
    Definiert den Wert des Parameters. Wenn weggelassen, muss eine externe Datei als Parameterquelle angegeben werden.

  • type="str | int | double | bool | yaml" (optional)
    Gibt den Typ des Parameters an. Falls nicht angegeben, versucht roslaunch, den Typ aus dem Wert abzuleiten:

    • Zahlen mit einem . werden als Gleitkomma (double) interpretiert.
    • Die Strings "true" und "false" werden als boolesche Werte interpretiert (Groß-/Kleinschreibung wird ignoriert).
    • Alles andere wird als String interpretiert.

2. Untergeordnete Tags

  • Keine

Beispiel:

xml
<launch>
    <node name="node1" pkg="my_package" type="node_executable">
        <param name="namespace/param_name" value="param_value" type="str"/>
    </node>
</launch>

Das <rosparam>-Tag

Das <rosparam>-Tag erlaubt es, Parameter aus einer YAML-Datei zu laden, in eine YAML-Datei zu exportieren oder zu löschen. Wenn es innerhalb eines <node>-Tags verwendet wird, gelten die Parameter als privat.

1. Attribute

  • command="load | dump | delete" (optional, Standard ist load)
    Gibt den auszuführenden Vorgang an: Parameter aus einer Datei laden, in eine Datei exportieren oder löschen.

  • file="$(find package_name)/path/to/file.yaml"
    Gibt die YAML-Datei an, aus der Parameter geladen oder in die exportiert werden soll.

  • param="parameter_name"
    Der Name des Parameters.

  • ns="namespace" (optional)
    Gibt den Namespace für die Parameter an.

2. Untergeordnete Tags

  • Keine

Beispiel:

xml
<launch>
    <rosparam file="$(find my_package)/config/params.yaml" command="load" ns="my_namespace"/>
</launch>

Das <group>-Tag

Das <group>-Tag dient dazu, Knoten und andere Tags zu gruppieren, und ermöglicht es, einen Namespace oder andere Einstellungen auf die gesamte Gruppe anzuwenden.

1. Attribute

  • ns="namespace" (optional)
    Wendet einen Namespace auf alle Knoten und Parameter innerhalb der Gruppe an.

  • clear_params="true | false" (optional)
    Löscht alle Parameter im Namespace der Gruppe vor dem Start. Mit Vorsicht verwenden, da dies kritische Parameter entfernen kann.

2. Untergeordnete Tags

  • Alle Tags außer dem <launch>-Tag können Kinder von <group> sein.

Beispiel:

xml
<launch>
    <group ns="my_namespace" clear_params="true">
        <node name="node1" pkg="my_package" type="node_executable"/>
        <node name="node2" pkg="my_package" type="node_executable"/>
    </group>
</launch>

Das <arg>-Tag

Das <arg>-Tag dient zum Definieren dynamischer Argumente, die zur Laufzeit an die Launch-Datei übergeben werden können, ähnlich wie Funktionsparameter. Dadurch wird die Flexibilität von Launch-Dateien erhöht.

1. Attribute

  • name="argument_name"
    Der Name des Arguments.

  • default="default_value" (optional)
    Gibt den Standardwert für das Argument an.

  • value="value" (optional)
    Gibt den Wert des Arguments an. Kann nicht gleichzeitig mit default verwendet werden.

  • doc="description"
    Stellt eine Beschreibung des Arguments bereit.

2. Untergeordnete Tags

  • Keine

3. Beispiel

Launch-Datei mit Argumentsyntax, hello.launch:

xml
<launch>
    <arg name="robot_name" default="my_robot"/>
    <param name="robot_name" value="$(arg robot_name)"/>
</launch>

Aufruf von der Kommandozeile mit Argumentübergabe:

bash
roslaunch hello.launch robot_name:=robot_value

ROS-Workspace-Overlay

Stellen Sie sich vor, Sie haben zwei benutzerdefinierte Workspaces, Workspace A und Workspace B, die beide ein Paket namens turtlesim enthalten. Zusätzlich enthält der systeminterne Workspace ebenfalls ein Paket namens turtlesim. Welches wird verwendet, wenn Sie das Paket turtlesim aufrufen?

Implementierungsschritte

Schritt 0: Workspaces A und B erstellen

Erstellen Sie zunächst zwei separate Workspaces, A und B. Erstellen Sie in jedem Workspace ein Paket namens turtlesim.

Schritt 1: Die Datei ~/.bashrc bearbeiten

Fügen Sie folgende Zeilen in Ihre ~/.bashrc-Datei ein, um die Setup-Dateien beider Workspaces zu sourcen:

bash
source /home/user/path/to/workspaceA/devel/setup.bash
source /home/user/path/to/workspaceB/devel/setup.bash

Ersetzen Sie /home/user/path/to/ durch die tatsächlichen Pfade Ihrer Workspaces.

Schritt 2: Umgebungsvariablen laden

Öffnen Sie ein neues Terminal und führen Sie folgenden Befehl aus, um die aktualisierten Umgebungsvariablen zu laden:

bash
source ~/.bashrc

Schritt 3: ROS-Umgebungsvariablen prüfen

Um die ROS-Paketpfade zu überprüfen, führen Sie aus:

bash
echo $ROS_PACKAGE_PATH

Ergebnis: Die Ausgabe zeigt die Pfade in folgender Reihenfolge: Workspace B → Workspace A → systeminterner Workspace.

Schritt 4: Das Paket turtlesim aufrufen

Führen Sie nun folgenden Befehl aus, um in das Paket turtlesim zu navigieren:

bash
roscd turtlesim

Ergebnis: Sie werden in das Paket turtlesim innerhalb von Workspace B geführt.

Umgang mit Namenskonflikten von ROS-Knoten

Szenario

In ROS hat jeder Knoten einen Namen, der bei der Knoteninitialisierung definiert wird. In C++ erfolgt das mit der API ros::init(argc, argv, "node_name");, in Python mit rospy.init_node("node_name"). In der ROS-Netzwerktopologie müssen Knoten eindeutige Namen haben, da das Teilen desselben Namens beim Aufrufen für Verwirrung sorgen kann. Konkret: Wird ein Knoten mit doppeltem Namen gestartet, wird der bestehende Knoten mit diesem Namen automatisch heruntergefahren. Doch was, wenn Sie mehrere Instanzen desselben Knotens ausführen oder Namenskonflikte handhaben müssen?

ROS bietet zwei Strategien für solche Situationen: Namespaces und Name-Remapping.

  • Namespaces fügen Knotennamen ein Präfix hinzu.
  • Name-Remapping weist einem Knotennamen einen Alias zu.

Beide Strategien können Konflikte bei Knotennamen lösen und können auf mehrere Arten implementiert werden:

  1. Mit dem Befehl rosrun.
  2. Über Launch-Dateien.
  3. Im Code des Knotens.

Dieser Abschnitt zeigt, wie Sie diese drei Methoden verwenden, um Namenskonflikte bei Knoten zu vermeiden.

Beispielszenario

Lassen Sie uns zwei turtlesim_node-Knoten starten. Wenn Sie zwei Terminals öffnen und die Knoten direkt ohne Änderungen starten, wird der erste Knoten beim Start des zweiten heruntergefahren. Sie sehen eine Warnung:

plaintext
[ WARN] [1578812836.351049332]: Shutdown request received.
[ WARN] [1578812836.351207362]: Reason given for shutdown: [new node registered with same name]

Da Knoten nicht denselben Namen teilen können, untersuchen wir verschiedene Strategien zur Lösung dieses Problems.

rosrun für Namespaces und Remapping verwenden

1. Einen Namespace mit rosrun setzen

Sie können einen Namespace für einen Knoten mit folgender Syntax setzen:

bash
rosrun package_name node_name __ns:=/new_namespace

Beispiel:

bash
rosrun turtlesim turtlesim_node __ns:=/xxx
rosrun turtlesim turtlesim_node __ns:=/yyy

Mit diesen Befehlen laufen beide Knoten ohne Probleme.

Ergebnisse:

Verwenden Sie rosnode list, um die Knoten zu prüfen:

plaintext
/xxx/turtlesim
/yyy/turtlesim

2. Knotennamen mit rosrun umbenennen

Sie können den Namen eines Knotens auch umbenennen, ihm also einen Alias geben, mit folgender Syntax:

bash
rosrun package_name node_name __name:=new_name

Beispiel:

bash
rosrun turtlesim turtlesim_node __name:=t1
rosrun turtlesim turtlesim_node __name:=t2

Mit diesen Befehlen laufen beide Knoten mit ihren neuen Namen.

Ergebnisse:

Verwenden Sie rosnode list, um die Knoten zu prüfen:

plaintext
/t1
/t2

3. Namespace und Namens-Remapping mit rosrun kombinieren

Sie können beide Techniken kombinieren, indem Sie gleichzeitig einen Namespace setzen und den Knotennamen umbenennen:

bash
rosrun package_name node_name __ns:=/new_namespace __name:=new_name

Beispiel:

bash
rosrun turtlesim turtlesim_node __ns:=/xxx __name:=tn

Ergebnisse:

Verwenden Sie rosnode list, um den Knoten zu prüfen:

plaintext
/xxx/tn

Alternativ können Sie den Namespace über eine Umgebungsvariable vor dem Start des Knotens setzen:

bash
export ROS_NAMESPACE=xxxx

Launch-Dateien für Namespaces und Remapping verwenden

In Launch-Dateien enthält das <node>-Tag zwei wichtige Attribute: name und ns. Sie werden für das Namens-Remapping bzw. das Setzen von Namespaces verwendet. Mit einer Launch-Datei lassen sich Namespaces und Namens-Remapping leicht handhaben.

1. Beispiel einer Launch-Datei

So können Sie Namespaces und Namens-Remapping in einer Launch-Datei einstellen:

xml
<launch>
    <node pkg="turtlesim" type="turtlesim_node" name="t1" />
    <node pkg="turtlesim" type="turtlesim_node" name="t2" />
    <node pkg="turtlesim" type="turtlesim_node" name="t1" ns="hello"/>
</launch>

In diesem Beispiel ist das Attribut name erforderlich, ns ist optional.

2. Die Launch-Datei ausführen

Führen Sie die Launch-Datei aus und verwenden Sie dann rosnode list, um die Ergebnisse zu sehen:

plaintext
/t1
/t2
/hello/t1

Namespaces und Remapping im Code setzen

Wenn Sie eigene Knoten implementieren, haben Sie mehr Flexibilität, Namespaces und Namens-Remapping direkt in Ihrem Code zu setzen.

1. C++-Implementierung: Namens-Remapping

Sie können einen Namensalias mit folgendem Code setzen:

cpp
ros::init(argc, argv, "zhangsan", ros::init_options::AnonymousName);

Ausführung:

Dies hängt einen Zeitstempel an den Knotennamen an und stellt seine Eindeutigkeit sicher.

2. C++-Implementierung: Setzen eines Namespaces

Sie können einen Namespace direkt im Code setzen:

cpp
std::map<std::string, std::string> map;
map["__ns"] = "xxxx";
ros::init(map, "wangqiang");

Ausführung:

Dadurch wird dem Knoten ein Namespace zugewiesen und er kann konfliktfrei laufen.

3. Python-Implementierung: Namens-Remapping

In Python erreichen Sie eine ähnliche Funktionalität mit folgendem Code:

python
rospy.init_node("lisi", anonymous=True)

Topic-Namens-Remapping in ROS

In ROS erlaubt das Topic-Namens-Remapping, den Namen eines Topics zu ändern, das ein Knoten abonniert oder veröffentlicht, ohne den Code des Knotens zu modifizieren. Das ist besonders nützlich, wenn mehrere Knoten integriert werden, die über unterschiedliche Topic-Namen kommunizieren müssen. Es gibt drei Hauptmethoden, Topic-Namen in ROS zu remappen:

  1. Mit dem Befehl rosrun.
  2. Über Launch-Dateien.
  3. Durch direkte Code-Änderung in C++ oder Python.

rosrun zum Remappen von Topics verwenden

Die Syntax zum Remappen eines Topic-Namens mit rosrun lautet:

bash
rosrun package_name node_name old_topic_name:=new_topic_name

Beispiel: Integration von teleop_twist_keyboard mit turtlesim

Es gibt zwei Möglichkeiten, die Kommunikation zwischen dem teleop_twist_keyboard-Knoten und dem turtlesim-Anzeigeknoten einzurichten:

1. Lösung 1: Topic von teleop_twist_keyboard remappen

Bei diesem Ansatz remappen wir das Topic des teleop_twist_keyboard-Knotens auf /turtle1/cmd_vel.

  • Tastatursteuerungsknoten starten:

    bash
    rosrun teleop_twist_keyboard teleop_twist_keyboard.py /cmd_vel:=/turtle1/cmd_vel
  • Turtlesim-Anzeigeknoten starten:

    bash
    rosrun turtlesim turtlesim_node

Beide Knoten kommunizieren korrekt über das Topic /turtle1/cmd_vel.

2. Lösung 2: Topic von turtlesim remappen

Alternativ können wir das Topic des turtlesim-Knotens auf /cmd_vel remappen.

  • Tastatursteuerungsknoten starten:

    bash
    rosrun teleop_twist_keyboard teleop_twist_keyboard.py
  • Turtlesim-Anzeigeknoten starten:

    bash
    rosrun turtlesim turtlesim_node /turtle1/cmd_vel:=/cmd_vel

Beide Knoten kommunizieren korrekt über das Topic /cmd_vel.

Launch-Dateien zum Remappen von Topics verwenden

Sie können Topics auch in einer Launch-Datei remappen. Die Syntax zum Remappen eines Topics in einer Launch-Datei lautet:

xml
<node pkg="package_name" type="node_type" name="node_name">
    <remap from="original_topic" to="new_topic" />
</node>

Beispiel: Integration von teleop_twist_keyboard mit turtlesim mittels Launch-Dateien

Auch hier gibt es zwei Lösungen:

1. Lösung 1: Topic von teleop_twist_keyboard remappen

Bei diesem Ansatz remappen wir das Topic des teleop_twist_keyboard-Knotens auf /turtle1/cmd_vel.

xml
<launch>
    <node pkg="turtlesim" type="turtlesim_node" name="t1" />
    <node pkg="teleop_twist_keyboard" type="teleop_twist_keyboard.py" name="key">
        <remap from="/cmd_vel" to="/turtle1/cmd_vel" />
    </node>
</launch>

Beide Knoten kommunizieren korrekt.

2. Lösung 2: Topic von turtlesim remappen

Bei diesem Ansatz remappen wir das Topic des turtlesim-Knotens auf /cmd_vel.

xml
<launch>
    <node pkg="turtlesim" type="turtlesim_node" name="t1">
        <remap from="/turtle1/cmd_vel" to="/cmd_vel" />
    </node>
    <node pkg="teleop_twist_keyboard" type="teleop_twist_keyboard.py" name="key" />
</launch>

Beide Knoten kommunizieren korrekt.

Topics im Code remappen

Der Topic-Name in ROS wird vom Namespace des Knotens, dem Knotennamen und dem Topic-Namen selbst beeinflusst. Topic-Namen lassen sich allgemein in drei Typen einteilen:

  1. Global: Der Topic-Name ist absolut und beginnt mit /, sodass er unabhängig vom Namespace des Knotens ist.
  2. Relativ: Der Topic-Name ist relativ und beginnt nicht mit /, was bedeutet, dass er innerhalb des Namespaces des Knotens interpretiert wird.
  3. Privat: Der Topic-Name ist privat und beginnt mit ~, das heißt, er wird relativ zum privaten Namespace des Knotens aufgelöst.

Lassen Sie uns diese Konzepte anhand von Beispielen in C++ und Python erkunden.

1. C++-Implementierung

Vorbereitung des Beispiels:

  1. Den Knoten mit einem Namen initialisieren:

    cpp
    ros::init(argc, argv, "hello");
  2. Verschiedene Arten von Topic-Namen festlegen.

  3. Beim Start des Knotens ein __ns:=xxx-Argument übergeben.

  4. Nach dem Start des Knotens rostopic verwenden, um die Topic-Informationen zu prüfen.

Globaler Topic-Name

Globale Topic-Namen beginnen mit / und sind unabhängig vom Namen oder Namespace des Knotens.

  • Beispiel 1:

    cpp
    ros::Publisher pub = nh.advertise<std_msgs::String>("/chatter", 1000);

    Ergebnis: /chatter

  • Beispiel 2:

    cpp
    ros::Publisher pub = nh.advertise<std_msgs::String>("/chatter/money", 1000);

    Ergebnis: /chatter/money

Relativer Topic-Name

Relative Topic-Namen beginnen nicht mit / und werden relativ zum Namespace des Knotens aufgelöst.

  • Beispiel 1:

    cpp
    ros::Publisher pub = nh.advertise<std_msgs::String>("chatter", 1000);

    Ergebnis: xxx/chatter

  • Beispiel 2:

    cpp
    ros::Publisher pub = nh.advertise<std_msgs::String>("chatter/money", 1000);

    Ergebnis: xxx/chatter/money

Privater Topic-Name

Private Topic-Namen beginnen mit ~ und werden relativ zum privaten Namespace des Knotens aufgelöst.

  • Beispiel 1:

    cpp
    ros::NodeHandle nh("~");
    ros::Publisher pub = nh.advertise<std_msgs::String>("chatter", 1000);

    Ergebnis: /xxx/hello/chatter

  • Beispiel 2:

    cpp
    ros::NodeHandle nh("~");
    ros::Publisher pub = nh.advertise<std_msgs::String>("chatter/money", 1000);

    Ergebnis: /xxx/hello/chatter/money

  • Sonderfall: Bei Verwendung von ~ wird der Topic-Name als absolut behandelt, wenn er mit / beginnt.

    cpp
    ros::NodeHandle nh("~");
    ros::Publisher pub = nh.advertise<std_msgs::String>("/chatter/money", 1000);

    Ergebnis: /chatter/money

Python-Implementierung

Vorbereitung des Beispiels:

  1. Den Knoten mit einem Namen initialisieren:

    python
    rospy.init_node("hello")
  2. Verschiedene Arten von Topic-Namen festlegen.

  3. Beim Start des Knotens ein __ns:=xxx-Argument übergeben.

  4. Nach dem Start des Knotens rostopic verwenden, um die Topic-Informationen zu prüfen.

Globaler Topic-Name

Globale Topic-Namen beginnen mit / und sind unabhängig vom Namen oder Namespace des Knotens.

  • Beispiel 1:

    python
    pub = rospy.Publisher("/chatter", String, queue_size=1000)

    Ergebnis: /chatter

  • Beispiel 2:

    python
    pub = rospy.Publisher("/chatter/money", String, queue_size=1000)

    Ergebnis: /chatter/money

Relativer Topic-Name

Relative Topic-Namen beginnen nicht mit / und werden relativ zum Namespace des Knotens aufgelöst.

  • Beispiel 1:

    python
    pub = rospy.Publisher("chatter", String, queue_size=1000)

    Ergebnis: xxx/chatter

  • Beispiel 2:

    python
    pub = rospy.Publisher("chatter/money", String, queue_size=1000)

    Ergebnis: xxx/chatter/money

Privater Topic-Name

Private Topic-Namen beginnen mit ~ und werden relativ zum privaten Namespace des Knotens aufgelöst.

  • Beispiel 1:

    python
    pub = rospy.Publisher("~chatter", String, queue_size=1000)

    Ergebnis: /xxx/hello/chatter

  • Beispiel 2:

    python
    pub = rospy.Publisher("~chatter/money", String, queue_size=1000)

    Ergebnis: /xxx/hello/chatter/money


Parameter in ROS setzen

In ROS werden Parameter zur Konfiguration von Knoten zur Laufzeit verwendet. Sie können auf verschiedene Arten gesetzt werden: mit dem Befehl rosrun, in Launch-Dateien oder direkt im Code. Parameter können global, relativ oder privat sein, je nach ihrer Definition.

Parameter mit rosrun setzen

Sie können Parameter beim Starten eines Knotens mit dem Befehl rosrun setzen. Die Syntax zum Setzen von Parametern ist:

bash
rosrun package_name node_name _parameter_name:=parameter_value

Beispiel: Einen Parameter für den Turtlesim-Knoten setzen

Lassen Sie uns den turtlesim_node starten und einen Parameter A = 100 setzen.

bash
rosrun turtlesim turtlesim_node _A:=100

Parameter prüfen

Sie können den folgenden Befehl verwenden, um alle Parameter aufzulisten und das Ergebnis zu überprüfen:

bash
rosparam list

Ausgabe:

plaintext
/turtlesim/A
/turtlesim/background_b
/turtlesim/background_g
/turtlesim/background_r

Erklärung: Der Parameter A ist mit dem Knotennamen (/turtlesim/) versehen, was darauf hinweist, dass rosrun beim Setzen eines Parameters den privaten Namespace-Modus verwendet.

Parameter in Launch-Dateien setzen

Wie zuvor besprochen, können Parameter in Launch-Dateien mit den Tags <param> oder <rosparam> gesetzt werden. Außerhalb des <node>-Tags gesetzte Parameter sind global, während innerhalb des <node>-Tags gesetzte Parameter privat und relativ zum Namespace des Knotens sind.

Beispiel: Parameter mit dem <param>-Tag setzen

Hier ein Beispiel, in dem wir einen globalen und einen privaten Parameter setzen:

xml
<launch>
    <param name="p1" value="100" />
    <node pkg="turtlesim" type="turtlesim_node" name="t1">
        <param name="p2" value="100" />
    </node>
</launch>

Parameter prüfen

Nach dem Ausführen der Launch-Datei können Sie die Parameter mit folgendem Befehl prüfen:

bash
rosparam list

Ausgabe:

plaintext
/p1
/t1/p2

Erklärung: Der Parameter p1 ist global, während p2 privat zum Knoten t1 ist, wie der Namespace anzeigt.

Parameter im Code setzen

Das Setzen von Parametern im Code bietet mehr Flexibilität und erlaubt es, globale, relative und private Parameter programmatisch zu definieren.

1. C++-Implementierung

In C++ können Parameter mit der ros::param-API oder über ein ros::NodeHandle-Objekt gesetzt werden.

1.1 ros::param zum Setzen von Parametern verwenden

Die Funktion ros::param::set wird zum Setzen von Parametern verwendet. Das erste Argument der Funktion ist der Parametername, das zweite der Parameterwert. Beginnt der Parametername mit /, ist es ein globaler Parameter. Beginnt er mit ~, ist es ein privater Parameter. Andernfalls ist er relativ.

Beispiel:

cpp
ros::param::set("/set_A", 100); // Global, independent of namespace and node name
ros::param::set("set_B", 100);  // Relative, dependent on namespace
ros::param::set("~set_C", 100); // Private, dependent on namespace and node name

Angenommen, der Namespace ist xxx und der Knotenname yyy, würde das Prüfen der Parameter mit rosparam list Folgendes anzeigen:

plaintext
/set_A
/xxx/set_B
/xxx/yyy/set_C

ros::NodeHandle zum Setzen von Parametern verwenden

Um Parameter mit ros::NodeHandle zu setzen, erstellen Sie zuerst ein NodeHandle-Objekt und rufen dann die setParam-Methode auf. Beginnt der Parametername mit /, ist er global. Beginnt er nicht mit /, hängt es davon ab, wie das NodeHandle-Objekt erstellt wurde, ob er relativ oder privat ist.

Beispiel:

cpp
ros::NodeHandle nh;
nh.setParam("/nh_A", 100); // Global, independent of namespace and node name

nh.setParam("nh_B", 100);  // Relative, dependent on namespace

ros::NodeHandle nh_private("~");
nh_private.setParam("nh_C", 100); // Private, dependent on namespace and node name

Angenommen, der Namespace ist xxx und der Knotenname yyy, würde das Prüfen der Parameter mit rosparam list Folgendes anzeigen:

plaintext
/nh_A
/xxx/nh_B
/xxx/yyy/nh_C

2. Python-Implementierung

In Python ist das Setzen von Parametern etwas einfacher als in C++. Die Funktion rospy.set_param wird zum Setzen von Parametern verwendet. Das erste Argument ist der Parametername, das zweite der Wert. Wie in C++ ist der Parameter global, wenn der Name mit / beginnt; mit ~ ist er privat. Andernfalls ist er relativ.

Beispiel:

python
rospy.set_param("/py_A", 100)  # Global, independent of namespace and node name
rospy.set_param("py_B", 100)   # Relative, dependent on namespace
rospy.set_param("~py_C", 100)  # Private, dependent on namespace and node name

Angenommen, der Namespace ist xxx und der Knotenname yyy, würde das Prüfen der Parameter mit rosparam list Folgendes anzeigen:

plaintext
/py_A
/xxx/py_B
/xxx/yyy/py_C