ROSのナビゲーションmove_baseについて理解を深めてみる

move_baseについて理解を深めていきたいを思います。
私もまだまだ勉強不足で、追加情報等ありましたら随時更新していこうと思います。

move_base.launch

<launch>
    <node pkg="move_base" type="move_base" respawn="false" name="move_base" output="screen">
        <rosparam file="$(find nav_param)/params/move_base_params.yaml" command="load" />
        <rosparam file="$(find your_param_dir)/params/base_local_planner_params.yaml" command="load" />
        <rosparam file="$(find your_param_dir)/params/costmap_common_params.yaml" command="load" ns="global_costmap" />
        <rosparam file="$(find your_param_dir)/params/costmap_common_params.yaml" command="load" ns="local_costmap" />
        <rosparam file="$(find your_param_dir)/params/local_costmap_params.yaml" command="load" />
        <rosparam file="$(find your_param_dir)/params/global_costmap_params.yaml" command="load" />
    </node>
</launch>

まずはlaunchファイルです。
パラメータは複数あるため、それぞれのパラメータをyamlファイルとして保存しています。

  • move_base_params.yaml
  • costmap_common_params.yaml
  • local_costmap_params.yaml
  • global_costmap_params.yaml
  • base_local_planner_params.yaml

costnap_common_params.yamlのns=”XXXXX_costmap”というのは名前空間NameSpaceの指定で、同じパラメータファイルをglobal_costmap、local_costmapという異なる名前空間で読み込ませています。

move_base_params.yaml

controller_frequency: 10.0
planner_patience: 5.0
controller_patience: 3.0
planner_frequency: 0.0
shutdown_costmaps: true
oscillation_timeout: 10.0
oscillation_distance: 0.2

base_global_planner   (string, default: “navfn/NavfnROS”)
move_baseで使用するグローバルプランナーのプラグインを指定。

base_local_planner   (string, default: “base_local_planner/TrajectoryPlannerROS”)
move_baseで使用するローカルプランナーのプラグインを指定。

recovery_behaviors   (list, default: [{name: conservative_reset, type: clear_costmap_recovery/ClearCostmapRecovery}, {name: rotate_recovery, type: rotate_recovery/RotateRecovery}, {name: aggressive_reset, type: clear_costmap_recovery/ClearCostmapRecovery}])
recovery behaviorsで使用するプラグインを指定。

controller_frequency   (double [Hz], default: 20.0)
cmd_velトピック(前進速度と回頭速度)をpublishする周波数。

planner_patience   (double [sec], default: 5.0)
有効なパスが見つからなかった時にプランナーがどれだけ待機するか。
待機の後にspace-clearing oparations(recovery behaviorsのことか?)が呼ばれる。
おそらく、待機時間内に障害物が移動し、liderなどのfree spaceを検出できるセンサにて障害物地図のコストがクリアされた場合、再び動き出すことができるということだろう。

ROSにデフォルトで実装されているrecovery behaviorsはその場旋回である。
円形のロボットであればその場旋回で周囲環境と接触するリスクは少ないが、大抵のロボットは円形ではなく、recovery behabiorは周囲環境と接触するリスクを伴うことをしっかり理解する必要があるだろう。

controller_patience   (double [sec], default: 15.0)
コントローラに信号が送られなかった場合、space-clearing oparations(recovery behaviorsのこと?)が呼ばれる前に待機するか。(コントローラとは???)

conservative_reset_dist   (double [m], default: 3.0)
調査中。recovery behaviorsの動きと関係ありそう。recovery_behaviorsにデフォルトのものを使用している時のみ有効の変数。

recovery_behavior_enabled   (bool, default true)
有効なパスを見つけられなかった時にrecovery behaviorsを使用するかどうか。

clearing_rotation_allowed   (bool, default true)
recovery behaviorsにて回転を許可するかどうか。
センサの死角があるロボットでは、コストマップにおいて死角領域のコストがアップデートされない。
そのため、ROSのデフォルトのrecovery behaviorではその場旋回により周囲を見渡すことで、ロボット周囲のコストマップの情報のアップデートを試みる。
当然、その場旋回時に周囲環境と接触してしまうリクスが伴う。そのことを理解した上で使用すること。

shutdown_costmaps   (bool, default false)
障害物をコストマップに残し続けておくか。これをfalseにしておくと人等の移動物体はその移動軌跡が障害物となってコストマップに現れる。

ocillation_timeout   (double [sec], default 0.0)
調査中。

ocillation_distance   (double [m], default 0.5)
調査中。

planner_frequency   (double [Hz], default 0.0)
global plannerがグローバルパスを計算する頻度。0.0に設定すると、最初にゴールが設定された時のみにグローバルパスが計算される。

max_planning_retries   (int32_t, default -1)
有効なパスが見つからなかった時に何度までパスの計算をリトライできるか?リトライの後にrecovery behaviorsに入る。-1に設定すると上限を設けない。

base_local_planner_params.yaml

TrajectoryPlannerROS:
    acc_lim_x: 2.5
    acc_lim_theta: 3.2
    max_vel_x: 0.25
    min_vel_x: 0.0
    max_vel_theta: 1.7
    min_vel_theta: -1.7
    min_in_place_vel_theta: 0.3
    holonomic_robot: false

    yaw_goal_tolerance: 0.05
    xy_goal_tolerance: 0.06

    pdist_scale: 2.0
    gdist_scale: 0.3
    occdist_scale: 0.01
    
    meter_scoring: true

Robot Configuration Parameters   -ロボットに関するパラメータ-

~<name>/acc_lim_x   (double [m/s^2], default: 2.5)
x方向(ロボットの前進方向)の最大加速度。

~<name>/acc_lim_y   (double [m/s^2], default: 2.5)
y方向の最大加速度。(全方位移動車両等のホロノミックロボットの場合にのみ使用)

~<name>/acc_lim_theta (double [rad/s^2], default: 3.2)
回転の最大角加速度。

~<name>/max_vel_x   (double [m/s], default: 0.5)
x方向の最大速度。

~<name>/max_vel_x   (double [m/s], default: 0.1)
x方向の最小速度。

~<name>/max_vel_theta   (double [rad/s], default: 1.0)
x方向の最大角速度。

~<name>/max_vel_x   (double [rad/s], default: -1.0)
x方向の最小角速度。

~<name>/min_in_place_vel_theta (double [rad/s], default: 0.4)
目的地に到着し、ロボットの角度を合わせるために回転するときの最小角速度。

~<name>/holonomic_robot   (bool, default: true)
ホロノミックなロボットかどうか。全方位移動車両の場合にはtrueにする。差動二輪やステアリング型の場合はfalse。
(要するにロボットが真横に旋回せずに直接移動できるかどうか)

Goal Tolerance Parameters   -ゴール到達に関するパラメータ-

~<name>/yaw_goal_tolerance   (double [rad], default: 0.05)
目標角度と現在角度の差がyaw_goal_tolerance以下になった時、目標地点に到達したと判定する。

~<name>/xy_goal_tolerance   (double [m], default: 0.1)
目標地点と現在地点との距離がxy_goal_tolerance以下となった時、目標地点に到達したと判定する。

Forward Simulation Paramaters   -ロボットの移動シミュレーションのパラメータ-

ロボットの移動シミュレートは円弧にて行われる。
ある速度v、回転角速度ωに置いてt秒間ロボットが移動した際にコストがどれだけであるか。
これを複数通り生成して、コストの一番良いものが選択されるという仕組みだ。

詳しくは以下のコスト生成のパラメータを参照。

~<name>/sim_time   (double [sec], default 1.0)
ロボットの移動を何秒間シミュレートするか。

~<name>/sim_granularity   (double [m], default 0.025)
算出する経路のきめ細かさ。

~<name>/angular_sim_granularity   (double [rad], default sim_granularity)
回頭速度をシミュレートする際のステップ数。

~<name>/vx_samples   (int, default 3)
何段階速度をシミュレートするか。

~<name>/vtheta_samples   (int, default 20)
何段階回頭速度をシミュレートするか。

~<name>/controller_frequency   (double [Hz], default 20.0)
シミュレーションの頻度。

Trajectory Scoring Parameters   -経路生成のコストパラメータ-

~<name>/meter_scoreing   (bool, default: false)
経路のコストを計算する際に距離をコストマップのセル数で計算するか、距離で計算するか。

~<name>/p_dist_scale   (double, default 0.6)
~<name>/g_dist_scale   (double, default 0.8)
~<name>/occdist_scale   (double, default 0.01)
ローカルパスのコストは次のような関数で求められる。
このコストにしたがって、なるべくコストのかからないようなパスを生成する。
p_distを大きくするとよりグローバルパス近づく経路が生成され、d_distを大きくするとよりローカルゴール(グローバルパスがローカルコストマップウィンドウの端から出て行く点)を目指す経路が生成される。
occdist_scaleを大きくすると、障害物をより大きく回避するようなパスが生成される。

(コスト) =
p_dist_scale * (グローバルパスまでの距離)
+ g_dist_scale * (ローカルゴールまでの距離)
+ occdist_scale * (通過する経路のセルの中でコスト(0~254)が最大のもの)

~<name>/heading_lookahead   (double [m], default: 0.325)
その場回転を評価するとき、どのくらい先をみるか。
ロボットが前進できない時、その場回転を選択することがある。その時、どれくらい先を見てコストを評価するか。

ロボットの少し先をスコアリングポイントとすることで、ロボットの向きを合わせることができる。
(ロボットのベースリンクをスコアリングポイントに設定すると、その場旋回時に位置が変わらないため、向きが定まらない)

~<name>/heading_scoring   (bool, default: false)
コストを評価するとき、ロボットの向きも考慮に入れるかどうか。

~<name>/heading_scoring_timestep   (double [s], default: 0.8)
何秒先を見るか。heading_scoringをtrueにした時に使用される。

~<name>/dwa   (bool, default: true)   <- 公式ドキュメントにはデフォルトでtrueになっているが、明示しないとfalseになる。
経路計画の際にdwa(ダイナミックウィンドウアプローチ)という手法を使用するか。

~<name>/publish_cost_grid_pc   (bool, default: false)
プランナーが経路計画をする際に使用するコストのグリッドを~<name>/cost_cloudトピック(型はPointCloud)として出力するかどうか。

~<name>/global_frame_id   (string, default: odom)
cost_cloudをpublishする際のフレーム。ローカルコストマップのglobal frameと合わせなければならない。

Oscillation Prevention Parameters

~<name>/oscillation_reset_dist   (double [m], default: 0.05)
調査中。

Global Plan Parameters

~<name>/prune_plan   (bool, default: true)
ロボットが通過した後のグローバルプランを破棄するかどうか。

costmap_common_params.yaml

obstacle_range: 2.0
raytrace_range: 2.5
footprint: [[0.14, 0.16], [-0.14, 0.16], [-0.14, -0.16], [0.14, -0.16]]
# robot_radius: 0.16
# inflation_radius: 0.19
# cost_scaling_factor: 10.0

observation_sources: laser_scan_sensor
laser_scan_sensor: {sensor_frame: laser, data_type: LaserScan, topic: scan, marking: true, clearing: true, inf_is_valid: true}

obstacle_range :   [m, default 2.5]
ロボットとの距離がobstacle_range以下のオブジェクトは障害物としてみなし、コストマップに反映する。

raytrace_range :   [m, default 3.0]
ロボットとの距離がraytrace_range以下のオブジェクトが検出された場合、そのオブジェクトの内側のコストマップの障害物がクリアされる。

footprint :  
ロボットの形状を多角形で指示することができる。footprintの形状に応じてコストマップのdefinitery in collisionとpossibly in collisionの径が決定される。

robot_radius :   [m]
footpritによって多角形でロボットの形状を指定する代わりに、ロボットを円とみなしてその半径を指定することができる。

observation_sources :   [string, default “”]
以下に設定するセンサ情報の名前空間を指定する。<source_name>

<source_name>/topic : [string, default source_name]
コストマップに使用されるセンサのトピック。デフォルトでは上で指定したobservation_sourcesで指定した値となる。

<source_name>/sensor_frame : [string, default “”]
センサの座標系の指定。

<source_name>/data_type :
センサから送られてくるデータタイプ。LaserScan、PointCloud、PointCloud2のいずれかが指定できる。

<source_name>/clearing :   [bool, default false]
センサデータを障害物のクリアに使うか。(レーザで距離が計測された時、その内側の領域は障害物が無いとみなされる。)

3次元空間の情報を2次元のコストマップに落とし込んでいるため、障害物のクリアには注意が必要。
例えば、地面から高さ1mのところに2dLidarを水平に設置したロボットの場合、背丈1m以下の障害物は検出できない。背丈1m以下の障害物が存在するにも関わらず、センサには映らなかったためにコストをクリアしてしまう場合がある。

<source_name>/marking : [bool, default true]
このセンサデータを障害物としてコストマップに反映させるか。

<source_name>/inf_is_vaild :   [bool, default false]
レーザなどで無限遠を検出した際にscanの配列にinfの値が入ることがある。その値を使用するかどうか。
(trueにするとinfの値を障害物のクリアに用いることができる.)

local_costmap_params.yaml

local_costmap:
    global_frame: odom
    robot_base_frame: base_link
    update_frequency: 5.0
    publish_frequency: 0.2
    static_map: false
    rolling_window: true
    width: 5.0
    height: 5.0
    resolution: 0.01
    meter_scoring: true

global_frame :
ロボットから得られるオドメトリ情報のトピック名。

robot_base_frame :
ロボットの足元のフレーム。 (私の場合は次のようにtfがつながります   map -> odom -> base_link -> laser)

update_frequency :
local_costmapを更新する頻度。(Hz)

publish_frequency :
rvizで可視化するためにcostmapなどの情報をpublishする頻度。[Hz]

static_map :
調査中。

rolling_window :
調査中。

width :
ローカルコストマップを計算する範囲。[m]

height :
ローカルコストマップを計算する範囲。[m]

resolution :
ローカルコストマップの解像度。[m/pixel]

meter_scoring :
調査中。

global_costmap_params.yaml

global_costmap:
    global_frame: map
    robot_base_frame: base_link
    update_frequency: 0.5
    publish_frequency: 3.0
    inflation_radius: 0.4
    static_map: true
    rolling_window: false
    transform_tolerance: 1.0

関連トピック。自己位置推定amclの使い方についてはこちら。
ROSのナビゲーションamclについて理解を深めてみる | MY ROBOTICS

以上。ROSのmove_baseについてでした。