目次
このパッケージは、空間のセンサーデータを取り込む2Dコストマップの実装を提供し、2Dまたは3Dの占有グリッドデータ(ボクセルベースの実装を使用するかどうかに依存)を構築します。そして、占有グリッドとユーザー定義のインフレーション半径でベースの2Dコストマップのコストをインフレーション(増大)します。 このパッケージは、map_serverベースのコストマップの初期化、ローリングウィンドウベースのコストマップ、およびパラメータベースのセンサートピックのサブスクリプションと設定もサポートしています。
出典:http://wiki.ros.org/costmap_2d
注:上の図では、赤色のセルはコストマップ内の障害物を表し、青色のセルはロボットの内接円半径によってインフレーションした領域を表し、細い赤枠はロボットのfootprint(占有領域)を表します。ロボットが衝突を避けるためには、ロボットのfootprintが赤色のセルと交差せず、且つ、ロボットの中心点が青色のセルと交差してはいけません。
costmap_2dパッケージは、ロボットが占有グリッドの形式でナビゲートする場所に関する情報を保持した設定可能な構造体を提供します。コストマップは、静的マップのセンサーデータと情報を使用して、costmap_2d :: Costmap2DROSオブジェクトを介して、空間の障害物に関する情報を保存および更新します。 costmap_2d :: Costmap2DROSオブジェクトは、純粋に2次元のインタフェースをユーザーに提供します。つまり、障害物の判定は"列"単位でのみ行うことができます。
たとえば、XY平面で同じ位置にあるがZ位置が異なる"テーブル"と"靴"の場合、costmap_2d :: Costmap2DROSオブジェクトのコストマップの対応するセルのコスト値は同じになります(下図参照)。これは、平面空間での経路探索がしやすいように設計されています。
Hydroリリースの時点で、コストマップはレイヤー構造で、自由に作成することができます。レイヤーを操作する基本的な関数は、各レイヤー内に実装されます。たとえば、静的マップは1つのレイヤーであり、障害物は別のレイヤーです。デフォルトでは、障害物レイヤーは3次元で情報を保持します( voxel_grid を参照)。 3D障害物データを保持することにより、レイヤーはマークとクリアをよりインテリジェントに処理できます。
主なインタフェースはcostmap_2d :: Costmap2DROSであり、ROS関連の機能の多くを持っています。各レイヤーを追跡するために使用されるcostmap_2d :: LayeredCostmapが含まれています。各レイヤーは、 pluginlib を使用してCostmap2DROSでインスタンス化され、LayeredCostmapに追加されます。レイヤー自体を個別にコンパイルして、C++インタフェースを介してコストマップに任意の変更を加えることができます。 costmap_2d :: Costmap2Dクラスは、2次元コストマップを保存およびアクセスするための基本的なデータ構造を実装します。
コストマップが占有グリッドを更新する方法についての詳細は、以下で説明します。
コストマップは、ROSを介してセンサートピックを自動的にサブスクライブし、それに応じて更新されます。 各センサーは、マーク(障害物情報をコストマップに挿入)、クリア(障害物情報をコストマップから削除)、またはその両方に使用されます。 マーク操作は、セルのコストを変更するための配列への単なるインデックスです。 しかしながら、クリア操作は、レポートされる各観測について、センサーの原点から外側に向かってグリッドを通過するレイトレーシングで構成されます。 3次元構造を使用して障害物情報を保存する場合、各"列"からの障害物情報は、コストマップに配置されるときに2次元に投影されます。
コストマップの各セルには255の異なるコスト値のいずれかを持つことができますが( インフレーション のセクションを参照)、使用する基本構造は3つの状態のみを表すことができます。 具体的には、この構造の各セルは、空き、占有、未知スペースのいずれかです。 各ステータスには、コストマップへの投影時に割り当てられる、特別なコスト値があります。 一定数の占有セル( mark_threshold パラメータを参照)がある"列"にはcostmap_2d :: LETHAL_OBSTACLEコストが割り当てられ、一定数の未知のセル( unknown_threshold パラメータを参照)がある"列"にはcostmap_2d :: NO_INFORMATIONコストが割り当てられ、その他の"列"には costmap_2d :: FREE_SPACEコストが割り当てられます。
コストマップは、 update_frequency パラメータで指定された周期でマップ更新サイクルを実行します。 周期ごとに、センサーデータが入力され、マークとクリアの操作がコストマップの基本的な占有構造で実行されます。この構造は、 上記 のように適切なコスト値が割り当てられるコストマップに投影されます。 その後、障害物のインフレーションはcostmap_2d :: LETHAL_OBSTACLEコストを持ったそれぞれのセルで実行されます。 これは、占有されている各セルからユーザー定義のインフレーション半径までコスト値を外側に伝播することで構成されます。 このインフレーション処理の詳細を 以下 に示します。
センサーソースからコストマップにデータを挿入するために、costmap_2d :: Costmap2DROSオブジェクトは tf を広範囲に使用します。 具体的には、 global_frame パラメータで指定された座標フレーム間の全ての変換、 robot_base_frame パラメータ、センサーソースが接続され、最新である想定で使用しています。 transform_tolerance パラメータは、これらの変換間で許容されるレイテンシーの最大量を設定します。 tf ツリーがこの予想されるレートで更新されない場合、 NavigationStack はロボットを停止します。
出典:http://wiki.ros.org/costmap_2d
インフレーションは、距離とともに減少する占有セルからコスト値を伝播するプロセスです。この目的のために、ロボットに関連するコストマップ値に5つの特定のシンボルを定義します。
これらの定義の背景にある理論的根拠は、正確なfootprintを気にするかどうかはプランナーの実装に任せていますが、それでも、オリエンテーションが実際に重要な状況でのみfootprintを追跡すれば済むような、十分な情報を提供することです。
costmap_2d :: Costmap2DROSオブジェクトを初期化するには、主に2つの方法があります。 1つは、ユーザー生成の静的マップを元に初期化する方法です(マップの構築に関するドキュメントについては、map_server パッケージを参照してください)。この場合、静的マップによって提供される幅、高さ、障害物の情報に一致するように、コストマップが初期化されます。この構成は通常、 amcl などの自己位置推定システムと組み合わせて使用され、ロボットがマップフレームに障害物を登録し、環境を通過するときにセンサーデータからコストマップを更新できるようにします。このタイプは、move_baseの基本的な構成においては、グローバルコストマップに使用されます。
costmap_2d :: Costmap2DROSオブジェクトを初期化する2番目の方法は、オブジェクトに幅と高さを与え、 rolling_window パラメータをtrueに設定することです。 rolling_window パラメータは、ロボットが空間を移動するときにロボットをコストマップの中心に保ち、ロボットが移動して特定の領域から離れすぎた障害物情報を地図から削除します。このタイプの構成は、ロボットがローカルエリア内の障害物のみを対象とする走行距離座標フレームで最もよく使用されます。このタイプは、move_baseの基本的な構成においては、ローカルコストマップに使用されます。
costmap_2d :: Costmap2DROSオブジェクトは、 C++ ROSラッパー として機能を公開するcostmap_2d :: Costmap2Dオブジェクトの ラッパー です。 これは、初期化時に指定されたROS名前空間(以降、nameと仮表記)内で動作します。
my_costmap名前空間を指定するcostmap_2d :: Costmap2DROSオブジェクトの作成例:
1 #include <tf/transform_listener.h>
2 #include <costmap_2d/costmap_2d_ros.h>
3
4 ...
5
6 tf::TransformListener tf(ros::Duration(10));
7 costmap_2d::Costmap2DROS costmap("my_costmap", tf);
costmap_2dノードを直接rosrunまたはroslaunchすると、costmap名前空間で実行されます。 この場合、以下の name へのすべての参照は costmap に変更する必要があります。
より一般的なケースは、move_baseノードを起動して完全なナビゲーションスタックを実行します。 これにより、それぞれ独自の名前空間のlocal_costmapとglobal_costmapの2つのコストマップが作成されます。 いくつかのパラメータについては、2回(コストマップごとに1回)設定が必要な場合があります。
Hydroで、C++ APIが変更されました。
トピック名 | 型 | 内容 |
---|---|---|
~<name>/footprint | geometry_msgs/Polygon | ロボットfootprintの仕様。 これは、以前のfootprintの仕様を置き換えます。 |
トピック名 | 型 | 内容 |
---|---|---|
~<name>/costmap | nav_msgs/OccupancyGrid | コストマップの値 |
~<name>/costmap_updates | map_msgs/OccupancyGridUpdate | コストマップの更新された領域の値 |
~<name>/voxel_grid | costmap_2d/VoxelGrid | 基礎となる占有グリッドがボクセルを使用し、ユーザーがボクセルグリッドのパブリッシュを要求したときに、必要に応じて通知されます。 |
~<name>/visualization_marker | visualization_msgs/Marker | (ROSWiki未掲載)可視化環境用のMarker情報 |
Hydro以降のリリースでは、すべてのcostmap_2dレイヤーにpluginsが使用されます。 pluginsパラメータを指定しない場合、初期化コードは、構成がHydro以前であると想定し、デフォルトの名前空間を持つプラグインのデフォルト設定をロードします。 パラメータは自動的に新しい名前空間に移動されます。 デフォルトの名前空間は、static_layer、obstacle_layer、inflation_layerです。 一部のチュートリアル(および書籍)では、以前のHydroのパラメータを参照しているので、細心の注意を払ってください。 安全のために、必ずpluginsパラメータを指定してください。
パラメータ名 | 内容 | 型 | 単位 | デフォルト |
---|---|---|---|---|
~<name>/plugins | レイヤーごとに1つのプラグイン仕様のシーケンス。 各仕様は、名前とタイプのフィールドを持つ辞書です。 この名前は、pluginパラメータの名前空間を定義するために使用されます。 例については、 チュートリアル を参照してください。 | sequence | - | Hydro以前の動作 |
パラメータ名 | 内容 | 型 | 単位 | デフォルト |
---|---|---|---|---|
~<name>/global_frame | 操作するコストマップのグローバルフレーム。 | string | - | /map |
~<name>/robot_base_frame | ロボットのベースリンクのフレームの名前。 | string | - | base_link |
~<name>/transform_tolerance | 許容できる変換(tf)データの遅延を秒単位で指定します。 このパラメータは、ユーザーがシステム内に存在するのに十分な遅延を許容しながら、tfツリー内のリンクを失うことに対する安全策として機能します。 たとえば、0.2秒古い変換は許容範囲内ですが、8秒古い変換は許容範囲外です。 global_frameパラメータとrobot_base_frameパラメータで指定された座標フレーム間の tf 変換が、ros :: Time :: now()よりもtransform_tolerance秒古い場合、 NavigationStack はロボットを停止します。 | double | s | 0.2 |
パラメータ名 | 内容 | 型 | 単位 | デフォルト |
---|---|---|---|---|
~<name>/update_frequency | マップの更新周波数 | double | Hz | 5.0 |
~<name>/publish_frequency | マップの表示情報パブリッシュ周波数 | double | Hz | 0.0 |
パラメータ名 | 内容 | 型 | 単位 | デフォルト |
---|---|---|---|---|
~<name>/rolling_window | ローリングウィンドウバージョンのコストマップを使用するかどうか。 static_mapパラメータがtrueに設定されている場合、このパラメータはfalseに設定する必要があります。 | bool | - | false |
~<name>/always_send_full_costmap | trueの場合、更新のたびに完全なコストマップが「〜<name>/costmap」にパブリッシュされます。 falseの場合、変更されたコストマップの部分のみが「〜<name>/costmap_updates」トピックでパブリッシュされます。 | bool | - | false |
~<name>/track_unknown_space | (ROSWiki未掲載)未知スペースの扱い。trueの場合、未知スペースとして扱い、falseの場合、空きとして扱います。 | bool | - | false |
次のパラメータは、一部のレイヤー、つまり静的マップレイヤーによって上書きできます。
パラメータ名 | 内容 | 型 | 単位 | デフォルト |
---|---|---|---|---|
~<name>/width | マップの幅 | int | m | 10 |
~<name>/height | マップの高さ | int | m | 10 |
~<name>/resolution | マップの解像度 | double | m/cell | 0.05 |
~<name>/origin_x | グローバルフレーム内のマップのx原点 | double | m | 0.0 |
~<name>/origin_y | グローバルフレーム内のマップのy原点 | double | m | 0.0 |
(global_frameパラメータの値)→(robot_base_frameパラメータの値)
通常、 amcl などの走行距離測定または自己位置推定を担当するノードによって提供されます。
costmap_2d :: Costmap2DROSクラスのC ++レベルAPIドキュメントについては、次のページを参照してください: Costmap2DROS C++ API
コストマップは、レイヤードコストマップという仕組みで、下の階層からプラグインを順に呼び出す形で、コストマップにコスト値を埋めていきます。Navigationスタックには、下記の3つのレイヤーがあります。
呼び出すコストマップレイヤーは、パラメータで任意に指定可能です。独自に開発したコストマップレイヤーを間に挟むこともできます。
障害物マップレイヤー は、センサーデータによって読み取られた障害物を追跡します。 ObstacleCostmapPluginは障害物を2次元でマークおよびレイトレースしますが、 VoxelCostmapPlugin は3次元で障害物をマークします。
インフレーションレイヤー は、コストマップがロボットの構成スペースを表すようにするため、致命的な障害物の周りに新しい値を追加(つまり、障害物をインフレーションする)最適化処理です。