🦭 【ROS2入門⑪】Nav2入門 - 自律ナビゲーションスタックでロボットを自律移動させる
シリーズ この記事は「ROS2入門シリーズ」の一部です。 シリーズ目次を見る
2026年5月時点。ROS 2 入門の締めとして、自律移動スタック Nav2 公式ドキュメント を扱います。想定読者は Gazebo シミュまで終えた方で、ここではコンポーネントの並びと TurtleBot3 でよくある起動順を優先します。
Ubuntu 22.04 + ROS 2 Humble 想定です。SLAM 実装(Cartographer / slam_toolbox)や launch 名は環境で差が出るため、手元のパッケージ README と TurtleBot3 e-Manual が正です。細部パラメータはプロジェクト側の yaml に従ってください。
本記事を読み終えると、地図作成→map_server→Nav2 goal までの流れを説明でき、失敗時に use_sim_time や初期姿勢を疑える状態になります。
Nav2(Navigation 2)の構成はどうなっている?
Nav2 はプランナ・コントローラ・コストマップ・行動ツリーなどが協調する自律移動スタックです。全体像は Nav2 公式ドキュメント の Architecture を参照し、下表は教材としての役割整理です。
主要コンポーネント
| コンポーネント | 役割 |
|---|---|
| BT Navigator | ビヘイビアツリーでナビゲーション処理を制御 |
| Planner Server | ゴールまでのグローバルパスを計算(A*等) |
| Controller Server | ローカル障害物回避とモーター指令 |
| Costmap 2D | 障害の膨張(インフレーション)と通行可能領域のコストを管理 |
| SLAM / 自己位置まわり | Cartographer や slam_toolbox など。実際の構成はメタパッケージ側の前提に従う |
SLAM で地図はどう作る?
SLAM(Simultaneous Localization and Mapping)は、移動しながら地図を溜めつつ自己位置を推定する処理の総称です。下は Cartographer 系 launch がある前提の例です。apt で入れるパッケージ名は launch と揃え、slam_toolbox と Cartographer を取り違えないでください(TurtleBot3 e-Manual)。
# SLAM 用パッケージは、使う launch に合わせて入れる(例のためコメントのみ)
# sudo apt install ros-humble-turtlebot3-cartographer
# または slam_toolbox 版なら、その launch に対応したパッケージを選択
# ターミナル1: Gazebo起動
export TURTLEBOT3_MODEL=burger
ros2 launch turtlebot3_gazebo turtlebot3_world.launch.py
# ターミナル2: SLAM(Cartographer 前提の一例。自分の環境の launch に差し替え)
ros2 launch turtlebot3_cartographer cartographer.launch.py use_sim_time:=True
# ターミナル3: teleopでロボットを動かして地図を作成
ros2 run turtlebot3_teleop teleop_keyboard
# 地図を保存
ros2 run nav2_map_server map_saver_cli -f ~/map
Nav2 で自律移動はどう試す?
# 保存した地図を使ってNav2を起動
# ターミナル1: Gazebo
export TURTLEBOT3_MODEL=burger
ros2 launch turtlebot3_gazebo turtlebot3_world.launch.py
# ターミナル2: Nav2起動
ros2 launch turtlebot3_navigation2 navigation2.launch.py \
use_sim_time:=True \
map:=$HOME/map.yaml RViz2 が開いたら、環境により次のような流れになります:
- 2D Pose Estimate で初期姿勢の目安を与える(地図座標との整合)
- Nav2 Goal でゴールを指定
- プランナ/コントローラが通れると、cmd_vel など経由で移動指令が流れる(パラメータやコストマップ次第で止まることもあります)
Python から Nav2 にゴールはどう送る?
import rclpy
from rclpy.node import Node
from nav2_msgs.action import NavigateToPose
from rclpy.action import ActionClient
class NavGoalSender(Node):
def __init__(self):
super().__init__('nav_goal_sender')
self._client = ActionClient(
self, NavigateToPose, 'navigate_to_pose')
def send_goal(self, x, y):
goal = NavigateToPose.Goal()
goal.pose.header.frame_id = 'map'
goal.pose.header.stamp = self.get_clock().now().to_msg()
goal.pose.pose.position.x = x
goal.pose.pose.position.y = y
goal.pose.pose.orientation.w = 1.0
self._client.wait_for_server()
future = self._client.send_goal_async(goal)
self.get_logger().info(f'Goal sent: ({x}, {y})')
return future コストマップとは何か?
コストマップ = 「そのマスへ進むコスト」を敷いたレイヤーのイメージ
0 … 問題なく通行しやすい
100 … 致命的な障害として扱う(通れない判定になりやすい)
-1 … まだよく見えない(未知)な領域
検出されている障害の周りにはしばしば「避けやすい」コストが積まれ、パスが脇へ寄る。 Nav2 試行でつまずきやすい点は?
- use_sim_time:=True をシミュと揃え忘れると、TF や地図の時刻まわりで挙動がおかしくなりやすい
- 地図ファイルの map.yaml と .pgm のパスがズレると map_server が落ちる
- 初期姿勢(Pose Estimate)が大きく外れていると、局所プランナがすぐ異常終了することがある(RViz で微調整)
- navigate_to_pose の frame_id(例: map)と TF が繋がっているかを、tf2_tools/RViz で先に確認する
ROS 2 入門シリーズの振り返りは?
ROS 2 入門シリーズ(①〜⑪)ひとまとめです。自分のワークスペースで 再現できた項目から復習すると定着しやすいです。
① ROS 2 の全体像・よくある用語
② Ubuntu 22.04 と ROS 2 Humble の導入
③ ノード/トピック/サービス/アクションの概念
④ Python で Pub/Sub
⑤ カスタム .msg /.srv /.action(インターフェース用パッケージ)
⑥ Python でサービス・アクション(例題ベース)
⑦ `colcon`・パッケージひな型・launch
⑧ RViz2・rqt
⑨ TF2(フレームと変換)
⑩ Gazebo と ros_gz まわり(シミュ環境依存に注意)
⑪ 本記事: Nav2(自律移動スタックの入口) このあと広げやすいトピック
- 実機への載せ替え:センサ・オドメ・安全停止を含めて差分前提
- MoveIt 2:アームなどの経路計画
- micro-ROS:マイコンと ROS 2 の接続
- ROS 2 とセキュリティ:DDS/ネットワーク方針