ROS シリーズ: 第 4 章 (6)

記事ディレクトリ

4. ROSの運用管理

この章は主に、異なる機能パッケージの関連付け、多数の ROS ノード、機能パッケージ、ノード、トピックの開始、パラメータの重複、異なるホスト上のノード間の通信の問題など、マルチレベルのディープ ROS システムを解決することを目的としています。

  • メタ関数パッケージの使用構文をマスターします。
  • 起動ファイルの使用構文をマスターします。
  • ROS ワークスペースの対象範囲と、どのようなセキュリティ リスクが存在するかを理解します。
  • ノード名が重複した場合の処理​​方法をマスターしてください。
  • トピック名が重複した場合の対処方法をマスターしてください。
  • パラメータ名が重複した場合の処理​​方法をマスターしてください。
  • ROS分散通信を実現できます。

1. ROSメタ関数パッケージ

メタパッケージは、Linux ファイル管理システムの概念です。ROS の仮想パッケージであり、実体はありませんが、他のソフトウェア パッケージに依存しており、他のパッケージを組み合わせることができます。

効果:

メタ関数パッケージは ROS の他の関数パッケージに依存しており、このパッケージをインストールするときに他の依存関係もインストールされます。

実装プロセス:

  1. src を右クリックし、「Catkin パッケージの作成」を選択します。
  2. 関数パッケージの名前 plumbing_my を入力し、関数パッケージの依存関係に依存しない関数パッケージを追加し、Enter キーを押した後にその依存関係パッケージを package.xml に追加します。

<exec_depend>plumbing_pub_sub</exec_depend>
<exec_depend>plumbing_server_client</exec_depend>
<exec_depend>plumbing_param_server</exec_depend>

メタ機能パッケージの追加リクエスト:

<export>
 <!-- Other tools can request additional information be placed here -->
 <metapackage/>
</export>
  1. CMakeLists.txt を変更します。内容は次のとおりです。

    cmake_minimum_required(VERSION 3.0.2)
    project(demo)
    find_package(catkin REQUIRED)
    catkin_metapackage()
    

    注: CMakeLists.txt の最後の行には改行を含めることはできません。コードは 4 行のみで、2 行目は関数パッケージの名前です。

    コンパイルして実行するだけです。

2. ROS ノードが実行され、起動ファイルを管理します

起動ファイルは XML 形式のファイルで、複数のローカルおよびリモート ノードを起動でき、パラメータ サーバーにパラメータを設定することもできます。
機能:

ノードの構成と起動を簡素化し、ROSプログラムの起動効率を向上させます。

使用方法:
小さなカメを例に挙げます。

  1. 新しい起動ファイルを作成する
    関数パッケージの下に起動ディレクトリを追加し、そのディレクトリの下に新しい xxxx.launch ファイルを作成し、起動ファイルを編集します。
<launch>
    <node pkg="turtlesim" type="turtlesim_node"     name="myTurtle" output="screen" />
    <node pkg="turtlesim" type="turtle_teleop_key"  name="myTurtleContro" output="screen" />
</launch>
  1. 起動ファイルを呼び出す
roslaunch 包名 xxx.launch

**注意: ** roslaunch コマンドが起動ファイルを実行すると、roscore があるかどうかが自動的に判断され、ない場合は roscore を呼び出します。ctrl+shift+~ でターミナルをすばやく起動します。

2.1 起動ファイル - 起動ラベル

このタグはすべての起動ファイルのルート タグであり、他のタグのコンテナとして機能します。

属性:

deprecated = "非推奨の宣言"

効果:

現在の起動ファイルは非推奨であり、実行されないことをユーザーに通知します。

サブセットラベル:

他のすべてのタグは launch の子です

コード例:

<launch deprecated = "当前版本已经过时,请停止使用!">
    <node pkg="turtlesim" type="turtlesim_node"     name="myTurtle" output="screen" />
    <node pkg="turtlesim" type="turtle_teleop_key"  name="myTurtleContro" output="screen" />
</launch>

2.2 起動ファイル - ノードラベル

ラベルは、ROS ノードを指定するために使用され、最も一般的なラベルです。なお、roslaunch コマンドは、ノードの宣言順にノードを起動することを保証できません (ノードの起動はマルチプロセスです)。 )

属性:

属性 関数
pkg="パッケージ名" ノードが属するパッケージ
type=”ノードタイプ” ノードタイプ(同名実行可能)
名前=「ノード名」 NodeName (ROS ネットワーク トポロジ内のノードの名前)
args="xxx xxx xxx" (オプション) パラメータをノードに渡す
machine="マシン名" 指定されたマシン上でノードを起動します
respawn="true|false" (オプション) ノードが終了した場合に自動的に再起動するかどうか
respawn_lay = "N" (オプション) respawn が true の場合、N 秒の遅延後にノードを開始します
required="true|false" (オプション) ノードが必須かどうか。true の場合、ノードが終了すると、roslaunch 全体が強制終了されます。
ns="xxx" (オプション) 指定された名前空間 xxx でノードを起動します
clear_params="true|false" (オプション) 開始する前に、ノードのプライベート空間のすべてのパラメータを削除してください
Output="log|screen" (オプション) ログ送信対象。ログファイルまたは画面画面に設定できます。デフォルトはログです。

サブセットラベル:

  • env 環境変数の設定
  • remap ノード名を再マップします
  • rosparamパラメータ設定
  • paramパラメータの設定

コード例:

<?xml version="1.0"?>
<launch>
<!-- <launch deprecated="此文件已经过时,不建议使用!"> -->

    <!-- 启动的节点 -->
    <!-- respawn="true" 节点关闭后自动重启 -->
    <!-- respawn_delay="10" 在respawn设置为true后可以通过delay延时自动启动节点  -->
    <!-- required="true"  节点退出后关闭整个roslaunch -->
    <!-- 当上述三个在一行时,可能会出现错误提示The traceback for the exception was written to the log file -->
    <!-- ns="hello"可以在指定命名空间启动节点  避免重名问题 -->
    <node name="my_turtlesim" pkg="turtlesim" type="turtlesim_node" output="screen" />

    <!-- 键盘控制节点 -->
    <node name="my_key" pkg="turtlesim" type="turtle_teleop_key" output="screen"/>


</launch>

2.3起動ファイル - タグを含める

属性:

  • file="$(パッケージ名を検索)/xxx/xxx.launch"

    含めるファイルパス

  • ns="xxx" (オプション)

    指定された名前空間にファイルをインポートします

効果:

他の XML 形式の起動ファイルを現在のファイルにインポートするために使用されます。

サブセットラベル:

  • env 環境変数の設定
  • arg は、インクルードされたファイルに引数を渡します

コード例:

<launch>
    <!-- 包含文件路径   $(find 功能包名)/xxx/yyy.launch   -->
    <include file="$(find launch01_basic)/launch/start_turtle.launch"/>
</launch>

2.4起動ファイル - ラベルの再マップ

属性:

  • file="$(パッケージ名を検索)/xxx/xxx.launch"

    含めるファイルパス

  • ns="xxx" (オプション)

    指定された名前空間にファイルをインポートします

効果:

トピックの名前変更用

サブセットラベル:

  • なし

コード例:

<?xml version="1.0"?>
<launch>
<!-- <launch deprecated="此文件已经过时,不建议使用!"> -->

    <!-- 启动的节点 -->
    <!-- respawn="true" 节点关闭后自动重启 -->
    <!-- respawn_delay="10" 在respawn设置为true后可以通过delay延时自动启动节点  -->
    <!-- required="true"  节点退出后关闭整个roslaunch -->
    <!-- 当上述三个在一起时,会出现错误提示The traceback for the exception was written to the log file -->
    <!-- ns="hello"可以在指定命名空间启动节点  避免重名问题 -->
    <node name="my_turtlesim" pkg="turtlesim" type="turtlesim_node" output="screen" >
        <remap from="/turtle1/cmd_vel" to="/cmd_vel"/>
    </node>
    <!-- 键盘控制节点 -->
    <node name="my_key" pkg="turtlesim" type="turtle_teleop_key" output="screen"/>   
</launch>

コード実装関数:

ros 組み込みキーボード制御ノードによって送信されるトピック名は /cmd_vel であり、タートル GUI は /turtle1/cmd_vel をサブスクライブします。トピック名が矛盾しているため、キーボード制御ノードを直接使用してタートルを制御することはできません。 gui であるため、タートル GUI を生成するノード ノードは次のようにする必要があります。ラベルはトピック名を再定義します。つまり、/turtle1/cmd_vel は /cmd_vel" に変更されます。rostopic リストを使用して、現在のトピック通信リストを表示できます。

rqt_graph を使用して、現在のトピックのコミュニケーションをより明確に取得します

2.5起動ファイル—paramタグ

属性:

  • name="名前空間/パラメータ名"

    パラメータ名。名前空間を含めることができます。

  • value="xxx" (オプション)

    パラメータ値を定義します。ここで省略した場合は、パラメータ ソースとして外部ファイルを指定する必要があります。

  • type="str|int|double|bool|yaml" (オプション)

    パラメータのタイプを指定します。指定されていない場合、roslaunch はパラメータのタイプを決定しようとします。ルールは次のとおりです。

    • 「.」を含む数値は浮動小数点型として解析されない場合、それ以外の場合は整数型になります。
    • 「true」と「false」はブール値です(大文字と小文字は区別されません)。
    • それ以外は文字列です

効果:

パラメータサーバー上のパラメータ設定に適用され、パラメータソースはタグ内の値で定義するか、外部ファイルからロードできます。ノードタグ内にある場合、プライベート名前空間と同等です。

サブセットラベル:

  • なし

コード例:

<?xml version="1.0"?>
<launch>
<!-- <launch deprecated="此文件已经过时,不建议使用!"> -->

    <!-- 启动的节点 -->
    <!-- respawn="true" 节点关闭后自动重启 -->
    <!-- respawn_delay="10" 在respawn设置为true后可以通过delay延时自动启动节点  -->
    <!-- required="true"  节点退出后关闭整个roslaunch -->
    <!-- 当上述三个在一起时,会出现错误提示The traceback for the exception was written to the log file -->
    <!-- ns="hello"可以在指定命名空间启动节点  避免重名问题 -->
    <!-- param标签 使用:向参数服务器设置参数 -->
    <!-- param标签格式1 会在参数前私有命名,node节点名称 -->
    <param name="param_A"  type="int" value="100"/>
    <node name="my_turtlesim" pkg="turtlesim" type="turtlesim_node" output="screen" >
        <remap from="/turtle1/cmd_vel" to="/cmd_vel"/>
        <!-- param标签格式2 launch目录下,node标签外 -->
        <param name="param_B" type="double" value="3.14"/>
    </node>
    <!-- 键盘控制节点 -->
    <node name="my_key" pkg="turtlesim" type="turtle_teleop_key" output="screen"/>   
</launch>

コード実装関数:

param パラメータにパラメータを設定します。rosparam リストで表示でき、rosparam get /xxx を通じてパラメータを取得できます。

2.6起動ファイル—rosparamタグ

属性:

  • command="load | dump | delete" (オプション、デフォルトのロード)

    パラメータのロード、エクスポート、または削除

  • file=“$(xxxxxを検索)/xxx/yyy…”

    ロードまたはエクスポートする yaml ファイル

  • param="パラメータ名"

  • ns="名前空間" (オプション)

効果:

yaml ファイルからパラメータをインポートするか、yaml ファイルにパラメータをエクスポートします。また、パラメータの削除にも使用できます。node タグの下で定義されている場合、プライベートとみなされます。

サブセットラベル:

  • なし

コード例:

start_turtle.launch

<?xml version="1.0"?>
<launch>
    <!-- <launch deprecated="此文件已经过时,不建议使用!"> -->

    <!-- 启动的节点 -->
    <!-- respawn="true" 节点关闭后自动重启 -->
    <!-- respawn_delay="10" 在respawn设置为true后可以通过delay延时自动启动节点  -->
    <!-- required="true"  节点退出后关闭整个roslaunch -->
    <!-- 当上述三个在一起时,会出现错误提示The traceback for the exception was written to the log file -->
    <!-- ns="hello"可以在指定命名空间启动节点  避免重名问题 -->
    <!-- param标签 使用:向参数服务器设置参数 -->
    <!-- param标签格式1 launch目录下,node标签外 -->
    <param name="param_A" type="int" value="100"/>
    <!-- rosparam 使用:操作参数服务器数据 -->
    <!-- rosparam格式1: launch 下,node 外 -->
    <!-- 加载参数 -->
    <rosparam command="load" file="$(find launch01_basic)/launch/params.yaml"/>

    <!-- 导出参数 -->
    <!-- <rosparam command="dump" file="$(find launch01_basic)/launch/params_out.yaml"/> -->

    
    <node name="my_turtlesim" pkg="turtlesim" type="turtlesim_node" output="screen">
        <remap from="/turtle1/cmd_vel" to="/cmd_vel"/>
        <!-- param标签格式2 node标签内  会在参数前私有命名,node节点名称-->
        <param name="param_B" type="double" value="3.14"/>
        <!--rosparam格式2: node 内 -->
        <rosparam command="load" file="$(find launch01_basic)/launch/params.yaml"/>

    </node>
    <!-- 键盘控制节点 -->
    <node name="my_key" pkg="turtlesim" type="turtle_teleop_key" output="screen"/>
</launch>

ダンプ.起動

<?xml version="1.0"?>
<launch>
    <rosparam command="dump" file="$(find launch01_basic)/launch/params_out.yaml"/>
    <!-- 删除参数 -->
    <rosparam command="delete" param="bg_B"/> 
</launch>

コード実装関数:

rosparam コマンドを使用して、param パラメータにパラメータを設定します。rosparam リストで表示でき、rosparam get /xxx を通じてパラメータを取得できます。

知らせ:

1. yaml ファイルで三原色を設定する場合、コロンの後にスペースを追加する必要があります。追加しないとエラーが報告されます。

2. rosparam が優先され、rosparam が最初に実行されるため、エクスポート データがターゲット パラメーターでない場合は、別の起動ファイルを設定して yaml ファイルをエクスポートできます。

2.7起動ファイル - グループラベル (group)

属性:

  • ns="名前空間" (オプション)

  • clear_params="true|false" (オプション)

    開始する前に、グループ名前空間のすべてのパラメータを削除するかどうか (使用には注意してください...この機能は危険です)

効果:

ns 属性を使用してノードをグループ化すると、ノードを名前空間に所属させることができます。

サブセットラベル:

  • 起動タグ以外のタグ

コード例:

タートルズ.ローンチ

<?xml version="1.0"?>
<launch>

    <!-- 同时启动两队乌龟GUI以及键盘控制节点 -->
    <group ns="first">
        <node name="my_turtlesim" pkg="turtlesim" type="turtlesim_node" output="screen"/>
        <node name="my_key" pkg="turtlesim" type="turtle_teleop_key" output="screen"/>
    </group>
    <group ns="second">
        <node name="my_turtlesim" pkg="turtlesim" type="turtlesim_node" output="screen"/>
        <node name="my_key" pkg="turtlesim" type="turtle_teleop_key" output="screen"/>
    </group>
</launch>

コード実装関数:

グループ化後、2 つの GUI の名前は同じですが、後から起動した GUI が前のプログラムを停止することはありません。

2.8起動ファイル - 引数ラベル

属性:

  • name="パラメータ名"

  • default="デフォルト値" (オプション)

  • value="値" (オプション)

    デフォルトと共存できません

  • doc="説明"

    パラメータの説明

効果:

関数パラメータと同様に、動的なパラメータの受け渡しに使用され、起動ファイルの柔軟性を高めることができます。

サブセットラベル:

  • なし

コード例:

タートルズ.ローンチ

<?xml version="1.0"?>
<launch>

    <!-- 演示arg的使用,需要设置多个参数,参数使用的是同一个值(小车长度) -->
    <!-- <param name="A" value="0.5"/>
    <param name="B" value="0.5"/>
    <param name="C" value="0.5"/> -->

    <arg name="car_length" default="0.55"/>
    
    <param name="A" value="$(arg car_length)"/>
    <param name="B" value="$(arg car_length)"/>
    <param name="C" value="$(arg car_length)"/>
</launch>

コード実装関数:

グローバル変数を宣言して値を割り当てるのと同様に、後で変数の値を直接変更できるため、行ごとに変更する手間が省けます。

動的パラメータ受け渡し関数:

roslaunch launch01_basic arg.launch car_length:=0.6

3. ROS ワークスペースの適用範囲の問題

ROS ワークスペースのカバレッジの問題を回避するように努めてください。

**問題の説明: **異なるワークスペースで、関数パッケージが同じ名前を持つ場合があるため、この名前の関数パッケージを呼び出すと、間違ったパスの関数パッケージが呼び出され、混乱が生じる可能性があります。通話時に発生します。

理由分析: ROS は、隠しフォルダーの .bashrc ファイルを解析し、ROS パッケージのパスを生成します。パス情報は、.bashrc で構成されたワークスペースの順序に従ってパスの優先順位を配置します。つまり、最後の構成が最も高い優先順位を持ちます。値が低いほど、現在のパスの優先順位が echo コマンドで表示され、プログラムが呼び出されたときに、前にある高い優先順位が最初に使用されます。サンプルコードは次のとおりです。

echo $ROS_PACKAGE_PATH 

**結論:** 関数パッケージが同じ名前の場合、呼び出しの優先順位が存在します。つまり、最後の設定が最初に実行され、ROS_PACKAGE_PATH を通じて確認できます。

バグの説明:

複数のワークスペースが .bashrc ファイルでソースされている場合、ROS パッケージ パスに含まれるワークスペースが 2 つだけになる場合があるため、カスタム ワークスペースの build ディレクトリと devel ディレクトリを削除し、catkin_make を再実行して、.bashrc ファイルを再ロードできます。問題が解決しました

4. ROS ノード名が重複しています

同じ名前でノードを起動する場合、または同じノードを複数回起動する必要がある場合は、ROS ノード名の重複の問題に注意する必要があります。

**概念:**ネームスペースは名前に接頭辞を追加することであり、名前の再マッピングは名前のエイリアスを作成することです。これらの戦略はどちらもノードの重複名の問題を解決できます。これら 2 つの戦略を実装するにはさまざまな方法があります。

  • rosrunコマンド
  • 起動ファイル
  • エンコーディングの実装

上記の 3 つの方法は、名前空間または名前の再マッピングによってノード名の重複を回避できます。このセクションでは、3 つの使用法を 1 つずつ説明します。3 つによって実現される要件は似ています。

4.1rosrun の名前空間の設定と再マッピング

4.1.1rosrun セット名前空間

構文: rosrun パッケージ名 ノード名 __ns:= 新しい名前

コード例:

rosrun turtlesim turtlesim_node __ns:=ergouzi
rosrun turtlesim turtlesim_node __ns:=dagouzi

両方のノードが稼働しています。

4.1.2 rosrun 名の再マッピング

構文: rosrun パッケージ名 ノード名 __name:= 新しい名前

コード例:

rosrun turtlesim  turtlesim_node __name:=daqiang
rosrun turtlesim  turtlesim_node __name:=xiaoqiang

両方のノードが稼働しています。

4.1.3 rosrun 名前空間と名前の再マッピングの重ね合わせの使用

语法: rosrun 包名 节点名 __ns:=新名称 __name:=新名称

コード例:

rosrun turtlesim  turtlesim_node __ns:=ergouzi __name:=daqiang 
rosrun turtlesim  turtlesim_node __ns:=dagouzi __name:=xiaoqiang

両方のノードが稼働しています。

甚至可以直接用  rosrun turtlesim  turtlesim_node /turtlesim_node:=daqiang  即/节点名称:=新名称

4.2 起動ファイル設定の名前空間と再マッピング

起動ファイルの構文を使用する場合、ノード タグには name と ns という 2 つの属性があり、それぞれ名前の再マッピングと名前空間の設定を実装するために使用されます。また、起動ファイルを使用してネームスペースと名前の再マッピングを設定することも比較的簡単です。

起動ファイル:

<?xml version="1.0"?>
<launch>
    <node name="turtlesim" pkg="turtlesim" type="turtlesim_node" output="screen"/>
    <!-- 名称重映射 -->
    <node name="t1" pkg="turtlesim" type="turtlesim_node" output="screen"/>
    <!-- 命名空间 -->
    <node name="turtlesim" ns="ergouzi" pkg="turtlesim" type="turtlesim_node" output="screen"/> 
    <!-- 命名空间 + 名称重映射 -->
    <node name="t2" ns="dagouzi" pkg="turtlesim" type="turtlesim_node" output="screen"/> 
</launch>

起動ファイルのノード タグには、name 属性が存在する必要があります。ns 名前空間はオプションです。

操作結果:

rosnode list
/dagouzi/t2
/ergouzi/turtlesim
/rosout
/t1
/turtlesim

ここから、ノード ラベルの呼び出しは厳密にプログラミングの順序で実行されるわけではなく、呼び出しの逆の順序で実行される可能性があることもわかります。

4.3 エンコーディング設定の名前空間と再マッピング

ノードの実装をカスタマイズすると、名前空間の設定と名前の再マッピングをより柔軟に実装できます。

4.3.1 C++ 実装: 再マッピング

4.3.1.1 ネームエイリアスの設定

コアコード:ros::init(argc,argv,"zhangsan",ros::init_options::AnonymousName);

4.3.1.2 実行

名前にはタイムスタンプが付加されます。

4.3.2 C++ 実装: 名前空間

4.3.2.1 名前空間の設定

コアコード

  std::map<std::string, std::string> map;
  map["__ns"] = "xxxx";
  ros::init(map,"wangqiang");
Copy
4.3.2.2 実行効果

ノード名は名前空間を設定します。

5. ROSトピック名の設定

ROS では、トピック名が同じ名前を持つことがあります。サブスクライブされたメッセージが同じ名前である場合、サブスクライバーが不要なメッセージを受信したときに問題が発生し、ノードが異常に動作する可能性があります。または、この 2 つのメッセージが同じ名前にならないようにする必要があります。通信する ノードはトピック上で通信するため、トピックが同じになるように変更する必要があります。

プレフィックスの違いに応じて、グローバル、相対、プライベートの 3 つのタイプがあります。

  • グローバル (パラメーター名は、ノード名前空間と同じレベルにある ROS システムを直接参照します)
  • 相対 (パラメータ名は、ノード名と同じレベルにあるノードの名前空間を参照します)
  • private (パラメータ名はノード名を参照し、ノード名の子です)

名前の再マッピングは、名前のエイリアスを設定し、名前にプレフィックスを追加することです。この実装はノードの名前変更よりも複雑です。名前空間をプレフィックスとして使用するだけでなく、ノード名もプレフィックスとして使用します。2 つの戦略を実装するには、いくつかの方法があります。

  • rosrunコマンド
  • 起動ファイル
  • エンコーディングの実装

このセクションでは、3 つの使い方を 1 つずつ説明しますが、3 つによって実現される要件は似ています。

場合:

ros-noetic-teleop-twist-keyboard 関数パッケージを使用してタートル表示 GUI を制御する

5.1 rosrun 設定トピックの再マッピング

**構文: **rosrun 名の再マッピング構文: rorun パッケージ名ノード名トピック名: = 新しいトピック名

5.1.1 解決策 1: キーボード コントロール ノードを変更してトピック名を公開する

teleop_twist_keyboard ノードのトピックを次のように設定します。/turtle1/cmd_vel

キーボード制御ノードを開始します。rosrun teleop_twist_keyboard teleop_twist_keyboard.py /cmd_vel:=/turtle1/cmd_vel

カメの表示ノードを開始します。rosrun turtlesim turtlesim_node

二人は正常なコミュニケーションが取れる

5.1.2 解決策 2: Turtle GUI ノードのサブスクリプション トピック名を変更する

タートル表示ノードのトピックを次のように設定します。/cmd_vel

キーボード制御ノードを開始します。rosrun teleop_twist_keyboard teleop_twist_keyboard.py

カメの表示ノードを開始します。rosrun turtlesim turtlesim_node /turtle1/cmd_vel:=/cmd_vel

二人は正常なコミュニケーションが取れる

5.2 起動ファイル設定トピックの再マッピング

** 構文: ** リマップタグを使用する

<node pkg="xxx" type="xxx" name="xxx">
    <remap from="原话题" to="新话题" />
</node>
5.2.1 解決策 1: teleop_twist_keyboard ノードのトピックを次のように設定します。/turtle1/cmd_vel
<?xml version="1.0"?>
<!-- 执行键盘功能包直接控制小乌龟 -->
<launch>
    <!-- 将乌龟的话题设置与键盘控制一致 -->
    <node name="my_turtle" pkg="turtlesim" type="turtlesim_node" >
       
    </node>

    <!-- 将乌龟的话题设置与键盘控制一致 -->
    <node name="key" pkg="teleop_twist_keyboard" type="teleop_twist_keyboard.py">
        <remap from="/cmd_vel" to="/turtle1/cmd_vel"/>
    </node>
</launch>

二人は正常なコミュニケーションが取れる

5.2.2 解決策 2: タートル表示ノードのトピックを次のように設定します。/cmd_vel
<?xml version="1.0"?>
<!-- 执行键盘功能包直接控制小乌龟 -->
<launch>
    <!-- 将乌龟的话题设置与键盘控制一致 -->
    <node name="my_turtle" pkg="turtlesim" type="turtlesim_node" >
        <remap from="/turtle1/cmd_vel" to="/cmd_vel"/>   
    </node>
    <node name="key" pkg="teleop_twist_keyboard" type="teleop_twist_keyboard.py"/>
    <!-- 将乌龟的话题设置与键盘控制一致 -->

</launch>

二人は正常なコミュニケーションが取れる

5.3 コード設定トピック名

トピック名はノードの名前空間やノード名と一定の関係があり、大きく次の3種類に分けられます。

  • グローバル (トピックはノード名前空間と同じレベルにある ROS システムを参照します)
  • 相対 (トピックはノード名と同じレベルにあるノードの名前空間を参照します)
  • プライベート (トピックはノード名の子であるノード名を参照します)

[外部リンク画像の転送に失敗しました。ソース サイトにはリーチ防止メカニズムがある可能性があります。画像を保存して直接アップロードすることをお勧めします (img-2SKGiOC6-1667583256847) (C:\Users\Haotian\AppData\Roaming\Typora\) typora-user-images \1667384023357.png)]

特定の関係を示すコーディング:

プロセス:

5.3.1 グローバル名の C++ 実装

**形式:**/で始まる名前はノード名とは関係ありません

例: /xxx/yyy/zzz

例 1:ros::Publisher pub = nh.advertise("/chatter",1000);

結果 1:/chatter

例 2:ros::Publisher pub = nh.advertise("/chatter/money",1000);

結果 2:/chatter/money

コード例:

#include "ros/ros.h"
#include "std_msgs/String.h"
/**
 * @brief 需求:演示不同类型的话题名称设置
 *             设置话题名称以及命名空间
 *  
 *
 */
int main(int argc, char *argv[])
{
    
    

    ros::init(argc, argv, "hello");
    ros::NodeHandle nh;
    //核心:设置不同类型的话题
    // 1.全局 --- 话题名称需要以 / 开头(也可以设置自己的命名空间),此时话题名称与节点(命名空间以及名称)没有任何关系
    // ros::Publisher pub = nh.advertise<std_msgs::String>("/chatter",1000);
    ros::Publisher pub = nh.advertise<std_msgs::String>("/yyy/chatter", 1000);

    // 2.相对

    // 3.私有

    while (ros::ok())
    {
    
    
        

    }
    return 0;
}

5.3.2 相対名の C++ 実装

**形式:**/先頭以外の名前。名前空間 (ノード名のレベル) を参照してトピック名を決定します。

例 1:ros::Publisher pub = nh.advertise("chatter",1000);

結果 1:xxx/chatter

例 2:ros::Publisher pub = nh.advertise("chatter/money",1000);

結果 2:xxx/chatter/money

コード例:

#include "ros/ros.h"
#include "std_msgs/String.h"
/**
 * @brief 需求:演示不同类型的话题名称设置
 *             设置话题名称以及命名空间
 *  
 *
 */
int main(int argc, char *argv[])
{
    
    

    ros::init(argc, argv, "hello");
    ros::NodeHandle nh;
    //核心:设置不同类型的话题
    // 1.全局 --- 话题名称需要以 / 开头(也可以设置自己的命名空间),此时话题名称与节点(命名空间以及名称)没有任何关系
    // ros::Publisher pub = nh.advertise<std_msgs::String>("/chatter",1000);
    // ros::Publisher pub = nh.advertise<std_msgs::String>("/yyy/chatter", 1000);

    // 2.相对 --- 非 / 开头    相对的会把话题后缀到命名空间后方,与命名空间同级
    // ros::Publisher pub = nh.advertise<std_msgs::String>("chatter",1000);
    ros::Publisher pub = nh.advertise<std_msgs::String>("yyy/chatter", 1000);

    // 3.私有

    while (ros::ok())
    {
    
    
        

    }
    

    return 0;
}

5.3.3 プライベート名 C++

**形式:**で~始まる名前

例 1:

ros::NodeHandle nh("~");
ros::Publisher pub = nh.advertise("chatter",1000);

結果 1:/xxx/hello/chatter

例 2:

ros::NodeHandle nh("~");
ros::Publisher pub = nh.advertise("chatter/money",1000);

結果 2:/xxx/hello/chatter/money

PS: を使用し~、トピック名が/で始まる場合がある場合、トピック名は絶対名です。

例 3:

ros::NodeHandle nh("~");
ros::Publisher pub = nh.advertise("/chatter/money",1000);

結果 3:/chatter/money

コード例:

#include "ros/ros.h"
#include "std_msgs/String.h"
/**
 * @brief 需求:演示不同类型的话题名称设置
 *             设置话题名称以及命名空间
 *  
 *
 */
int main(int argc, char *argv[])
{
    
    

    ros::init(argc, argv, "hello");
    // ros::NodeHandle nh;
    //核心:设置不同类型的话题
    // 1.全局 --- 话题名称需要以 / 开头(也可以设置自己的命名空间),此时话题名称与节点(命名空间以及名称)没有任何关系
    // ros::Publisher pub = nh.advertise<std_msgs::String>("/chatter",1000);
    // ros::Publisher pub = nh.advertise<std_msgs::String>("/yyy/chatter", 1000);

    // 2.相对 --- 非 / 开头    相对的会把话题后缀到命名空间后方,与命名空间同级
    // ros::Publisher pub = nh.advertise<std_msgs::String>("chatter",1000);
    // ros::Publisher pub = nh.advertise<std_msgs::String>("yyy/chatter", 1000);

    // 3.私有--- 需要创建特定句柄 NodeHandle  nh(~);
    ros::NodeHandle nh("~");
    // ros::Publisher pub = nh.advertise<std_msgs::String>("chatter", 1000);
    // ros::Publisher pub = nh.advertise<std_msgs::String>("yyy/chatter", 1000);

    //注意:如果私有的NH创建的话题以 / 开通(全局话题) 生成的话题就是全局话题而非私有话题
    //全局话题优先级更高
    ros::Publisher pub = nh.advertise<std_msgs::String>("/yyy/chatter", 1000);//私有句柄 话题名称变全局名称时 变成全局话题,因为全局话题优先级最高

    while (ros::ok())
    {
    
    
        

    }
    

    return 0;
}

6. ROSトピック名の設定


ROS では、ノード名トピック名が同じ名前になる場合があり、パラメータ名も同じ名前になる場合があります。ただし、パラメータの重複に対する名前の再マッピング操作はなく、重複を避けるために、前セクションのトピック名のグローバル、相対、およびプライベートの方法と同様に、パラメータにプレフィックスを追加する方法が使用されます。 ;

  • グローバル (パラメーター名は、ノード名前空間と同じレベルにある ROS システムを直接参照します)
  • 相対 (パラメータ名は、ノード名と同じレベルにあるノードの名前空間を参照します)
  • private (パラメータ名はノード名を参照し、ノード名の子です)

パラメータを設定するには 3 つの方法もあります。

  • rosrunコマンド
  • 起動ファイル
  • エンコーディングの実装

6.1 rosrun設定パラメータ

rosrun がノードを起動するときに、パラメーターを設定できます。

**構文:**rosrun 関数パッケージ パッケージ名 ノード名_パラメータ名:=パラメータ値

1. パラメータの設定

rosrun turtlesim turtlesim_node _radius:=3.56

2.走る

rosparam listノード情報を表示し、結果を表示します。

/rosdistro
/roslaunch/uris/host_wht_vpc__35637
/rosversion
/run_id
/turtlesim/background_b
/turtlesim/background_g
/turtlesim/background_r
/turtlesim/radius

結果は、パラメーター A がノード名の先頭に付いていることを示しています。これは、rosrun 実行設定パラメーター名がプライベート モードを使用していることを意味します。

6.2 起動設定パラメータ

起動ファイルを介してパラメータを設定する方法は以前に紹介されましたが、パラメータはノード ラベルの外側で設定することも、ノード ラベル内の param または rosparam を介して設定することもできます。ノード タグの外側で設定されたパラメータはグローバルであり、 / を参照します。ノード タグ内で設定されたパラメータはプライベートで、 /namespace/nodename を参照します。

1. パラメータの設定

パラメータを設定するには、例として param タグを使用します。

<!-- 设置参数 -->
<launch>
    <!-- 格式1:全局 -->
    <param name="radius" value="0.2"/>
    <node name="my_turtle" pkg="turtlesim" type="turtlesim_node" ns="xxx">
        <!-- 格式2:私有 -->
        <param name="radius" value="0.08"/>
    </node>
</launch>

2.走る

rosparam listノード情報を表示し、結果を表示します。

/radius
/rosdistro
/roslaunch/uris/host_wht_vpc__45767
/rosversion
/run_id
/xxx/my_turtle/background_b
/xxx/my_turtle/background_g
/xxx/my_turtle/background_r
/xxx/my_turtle/radius

実行結果は期待と一致しています。

6.3 エンコード設定パラメータ

エンコード方法は、グローバル、相対、およびプライベート パラメーターでより簡単に設定できます。

6.3.1 ros::param 設定パラメータ

パラメータを設定するための呼び出しAPIはros::param::setです。この関数では、パラメータ1はパラメータ名に渡され、パラメータ2は渡されたパラメータの値です。パラメータ1にパラメータ名を設定する場合、 / で始まる場合はグローバル パラメーター、~ で始まる場合はプライベート パラメーター、/ または ~ で始まらない場合は相対パラメーターです。

コード例:

#include <ros/ros.h>

int main(int argc, char* argv[])
{
    
    
    ros::init(argc, argv, "hello");
    ros::NodeHandle nh;
    /*
         使用ros::param来设置参数
    */
    //全局,和命名空间以及节点名称无关
    ros::param::set("/radiusA", 100);
    //相对,参考命名空间
    ros::param::set("radiusB", 100);  
    //私有,参考命名空间与节点名称
    ros::param::set("~radiusC", 100); 

    return 0;
}

実行時、設定された名前空間が xxx、ノード名が yyy であると仮定し、rosparam リストを使用して表示します。

/radiusA
/rosdistro
/roslaunch/uris/host_wht_vpc__46715
/rosversion
/run_id
/xxx/hello/radiusC
/xxx/radiusB

6.3.2 ros::NodeHandle 設定パラメータ

パラメータを設定する場合は、まず NodeHandle オブジェクトを作成し、そのオブジェクトの setParam 関数を呼び出す必要があります。この関数のパラメータ 1 はパラメータ名で、パラメータ 2 は設定するパラメータ値です。パラメータ名が/ で始まる場合は、グローバル パラメーターです。パラメーター名が / で始まらない場合、パラメーターが相対パラメーターであるかプライベート パラメーターであるかは、NodeHandle オブジェクトに関連付けられます。NodeHandle オブジェクトが作成されたときに作成される場合は、デフォルトの引数なしの構築が呼び出されると、パラメータは相対パラメータになります。NodeHandle オブジェクトが ros::NodeHandle nh("~") を使用して作成された場合、このパラメータはプライベート パラメータです。コード例:

#include <ros/ros.h>

int main(int argc, char* argv[])
{
    
    
    ros::init(argc, argv, "hello");
    ros::NodeHandle nh;
    /*
         使用ros::param来设置参数
    */
    //全局,和命名空间以及节点名称无关
    ros::param::set("/radiusA", 100);
    //相对,参考命名空间
    ros::param::set("radiusB", 100);  
    //私有,参考命名空间与节点名称
    ros::param::set("~radiusC", 100);
    /*
         使用NodeHandle来设置参数
    */
    //全局,和命名空间以及节点名称无关
    nh.setParam("/radius_nh_A", 100);
    //相对,参考命名空间
    nh.setParam("radius_nh_B", 100);
    //私有,参考命名空间与节点名称
    ros::NodeHandle nh_private("~");
    nh_private.setParam("radius_nh_C", 100); 
    return 0;
}

実行時、設定された名前空間が xxx、ノード名が yyy であると仮定し、rosparam リストを使用して表示します。

/radiusA
/radius_nh_A
/rosdistro
/roslaunch/uris/host_wht_vpc__36311
/rosversion
/run_id
/yyy/hello/radiusC
/yyy/hello/radius_nh_C
/yyy/radiusB
/yyy/radius_nh_B

**注意:** パラメータが異常な場合は、roscore を 1 回更新してから、rosparam リストを再実行して表示を更新できます。

7. ROS分散通信


ROS は分散コンピューティング環境です。実行中の ROS システムは、複数のコンピューターに分散された複数のノードで構成されます。システムの構成方法によっては、どのノードでも、いつでも他のノードと通信する必要がある場合があります。

したがって、ROS にはネットワーク構成に関して特定の要件があります。

  • すべてのポート上のすべてのマシン間で完全な双方向接続が必要です。
  • 各コンピュータは、他のすべてのコンピュータが解決できる名前で自分自身をアナウンスする必要があります。

成し遂げる

1. 準備する

まず、異なるコンピュータが同じネットワーク内にあることを確認します。固定 IP を個別に設定するのが最善です。仮想マシンの場合は、ネットワーク アダプタをブリッジ モードに変更する必要があります。

2. 設定ファイルの変更

異なるコンピュータの /etc/hosts ファイルをそれぞれ変更し、相手の IP アドレスとコンピュータ名をファイルに追加します。

ホスト側:

从机的IP    从机计算机名

スレーブ側:

主机的IP    主机计算机名

設定後、pingコマンドを使用してネットワーク通信が正常かどうかをテストできます。

IP アドレスビュー名: ifconfig

コンピュータ名を確認します: ホスト名

3. ホストIPの構成

ホストのIPアドレスを設定する

~/.bashrc 追加

export ROS_MASTER_URI=http://主机IP:11311
export ROS_HOSTNAME=主机IP

4. スレーブIPの設定

スレーブ マシンの IP アドレスを構成します。複数のスレーブ マシンが存在し、それぞれが次の設定を行うことができます。

~/.bashrc 追加

export ROS_MASTER_URI=http://主机IP:11311
export ROS_HOSTNAME=从机IP

4. スレーブIPの設定

スレーブ マシンの IP アドレスを構成します。複数のスレーブ マシンが存在し、それぞれが次の設定を行うことができます。

~/.bashrc 追加

export ROS_MASTER_URI=http://主机IP:11311
export ROS_HOSTNAME=从机IP

テスト

1. ホストが roscore を開始します (必須)

2. ホストはサブスクリプション ノードを起動し、スレーブはパブリッシング ノードを起動して、通信が正常かどうかをテストします。

3. リバーステスト。マスターはパブリッシングノードを起動し、スレーブはサブスクリプションノードを起動し、通信が正常かどうかをテストします。

おすすめ

転載: blog.csdn.net/TianHW103/article/details/127699152