ROSにおける計算グラフリソースの命名とリマッピング機構

命名規則の概要

ROS(Robot Operating System)において、ノード、パラメータ、トピック、サービスといった要素は「計算グラフリソース」と総称されます。これらのリソース名は、柔軟な階層構造を持っており、大規模で複雑なシステムにおけるモジュールの統合や再利用性を高めるように設計されています。

有効なリソース名を構成するためのルールは以下の通りです。

  1. 先頭文字: 英字(a-z, A-Z)、チルダ(~)、またはスラッシュ(/)のいずれかである必要があります。
  2. 2文字目以降: 英数字、アンダースコア(_)、またはスラッシュ(/)を使用できます。

以下に具体例を示します。

/global_sensor
/localization/particle_filter
~private_param

名前空間(Namespace)の活用

名前空間は、リソース同士の衝突を防ぐためのカプセル化メカニズムです。特定の名前空間内で定義されたリソースは、その空間内だけでなくグローバルなスコープからもアクセス可能ですが、異なる名前空間に同名のリソースが存在しても干渉し合いません。

名前空間を設定する方法は多岐にわたります。

1. プログラムコードによる設定
ros::init関数を呼び出す際、__nsというキーを持つ引数マップを渡すことで、デフォルトの名前空間を指定できます。

std::map<std::string, std::string> remappings;
remappings["__ns"] = "sensor_group";
ros::init(remappings, "camera_node");

2. Launchファイルでの設定
Launchファイルを使用する場合、ns属性を用いてノードの属する名前空間を定義します。

<node pkg="navigation_pkg" type="laser_scanner" name="base_scan" ns="hardware" />

3. コマンドライン引数での指定
rosrunコマンド実行時に引数を渡します。

rosrun navigation_pkg laser_scanner __ns:=/hardware/sensors

4. 環境変数による設定
実行環境の環境変数ROS_NAMESPACEを定義することで、そのシェル内で起動されるすべてのノードのデフォルト名前空間を変更できます。

export ROS_NAMESPACE=global_mapping

名前解決の種類

計算グラフリソースの名前は、その記述形式に基づいて4つのカテゴリに分類され、それぞれ異なる解決ルールを持ちます。

  • ベース名(Base Name): リソース名そのものを指します(例: velocity)。相対名の一種とみなされます。
  • グローバル名(Global Name): 先頭がスラッシュ(/)で始まる名前です(例: /robot/velocity)。ルートからの完全パスとして解釈されるため、どこからでも絶対的なパスとしてアクセス可能です。ただし、使いすぎるとパッケージの移植性が低下するため、必要最小限に留めるのが推奨されます。
  • 相対名(Relative Name): 先頭にスラッシュを持たない名前です(例: velocity)。現在のデフォルト名前空間に対する相対パスとして解決されます。例えば、デフォルト名前空間が/robotである場合、velocity/robot/velocityとして解決されます。
  • プライベート名(Private Name): 先頭がチルダ(~)で始まる名前です(例: ~config_value)。ノードの内部でのみ使用されるリソースを指し、現在のデフォルト名前空間ではなく、そのノード自身のグローバル名をベースとして解決されます。例えば、グローバル名が/robot/controllerのノードにおいて~paramは、/robot/controller/paramとなります。

以下の表は、異なるコンテキストにおける名前解決の挙動をまとめたものです。

ノード名 デフォルト名前空間 相対名の解決結果 グローバル名の解決結果 プライベート名の解決結果
/node_alpha / data -> /data /data -> /data ~data -> /node_alpha/data
/group/sub_node /group status -> /group/status /status -> /status ~status -> /group/sub_node/status
/group/worker /group log/info -> /group/log/info /log/info -> /log/info ~log/info -> /group/worker/log/info

ノード名の再割り当て(Remapping)

ROSの強力な機能の一つとして、ノード起動時にリソース名を再割り当て(リマップ)できることが挙げられます。これにより、同じノードを異なる名前で複数同時実行し、競合を回避することが可能です。

1. コードによる設定
C++では初期化オプションを使用して名前を変更したり、匿名化(タイムスタンプの付与)を行ったりできます。

// 名前を明示的に変更
std::map<std::string, std::string> args;
args["__name"] = "custom_node_name";
ros::init(args, "original_name");

// 匿名化(名前の衝突を防ぐためタイムスタンプを付与)
ros::init(argc, argv, "base_name", ros::init_options::AnonymousName);

Pythonでは以下のように記述します。

rospy.init_node("base_name", anonymous=True)

2. コマンドライン(rosrun)での設定
起動コマンドに引数を追加します。

# ノード自体の名前を変更
rosrun demo_pkg executable __name:=my_unique_node

# 特定のトピック名等を変更(ノード名以外も対象)
rosrun demo_pkg executable original_topic:=new_topic

3. Launchファイルでの設定
Launchファイル内のnodeタグにあるname属性を変更します。

<node pkg="demo_pkg" type="executable" name="unique_node_instance" />

トピック・サービス名の再割り当て

トピックやサービス名は、コード内部では名前を定義するのみで、リマップ処理そのものは起動時の設定に依存します。これにより、コードを修正することなく、ノード間の接続先を動的に変更できます。

1. コマンドラインによるリマップ

rosrun demo_pkg executable old_topic:=remapped_topic

2. Launchファイルによるリマップ
remapタグを使用して、入力(from)と出力(to)の対応関係を定義します。

<node pkg="demo_pkg" type="executable" name="node_name">
    <remap from="input_topic" to="output_topic" />
</node>

注意点として、同一ノード内にトピックとサービスで同名のリソースが存在する場合、これらのリマップ操作は両方に適用されます。

タグ: ROS 計算グラフ 名前空間 リマッピング C++

6月18日 00:25 投稿