ナビゲーションでは、自律移動ロボットが、作成した地図に基づき、自己位置を認識し、目標位置への経路を計画し移動します。
自律移動ロボット(AMR)のマッピング
上の画像は、シミュレータGazeboの画面(左)と、RViz2の画面(右)
マッピングでは、自律移動ロボット(AMR)を移動させて、部屋の地図を作成します。
シミュレータ上で地図作成の準備
シミュレータGazeboを起動します。willowgarageの部屋を使います。
ros2 launch hajimecart_gazebo willowgarage_world.launch.py
willowgarage_world.launch.py
import os
from ament_index_python.packages import get_package_share_directory
from launch import LaunchDescription
from launch.actions import DeclareLaunchArgument
from launch.actions import IncludeLaunchDescription
from launch.launch_description_sources import PythonLaunchDescriptionSource
from launch_ros.actions import Node
from launch_ros.parameter_descriptions import ParameterValue
from launch.substitutions import Command, LaunchConfiguration
def generate_launch_description():
pkg_gazebo_ros = get_package_share_directory('gazebo_ros')
pkg_my_gazebo = get_package_share_directory('hajimecart_gazebo')
worlds = os.path.join(pkg_my_gazebo, 'worlds', 'willowgarage.world')
urdf_model_dir = get_package_share_directory('hajimecart_description')
urdf_model_path = os.path.join(urdf_model_dir, 'urdf', 'hajimecart_gazebo.urdf')
model_arg = DeclareLaunchArgument(name='model', default_value=str(urdf_model_path),
description='Absolute path to robot urdf file')
robot_description = ParameterValue(Command(['xacro ', LaunchConfiguration('model')]),
value_type=str)
# Gazebo launch
gazebo = IncludeLaunchDescription(
PythonLaunchDescriptionSource(
os.path.join(pkg_gazebo_ros, 'launch', 'gazebo.launch.py'),
)
)
spawn_entity = Node(package='gazebo_ros', executable='spawn_entity.py',
arguments=['-entity', 'hajimecart', '-topic', '/robot_description',
'-x', '8',
'-y', '-8',
'-z', '0',
'-Y', '3.141592654'],
output='screen')
robot_state_publisher = Node(
package='robot_state_publisher',
executable='robot_state_publisher',
parameters=[{'robot_description': robot_description}]
)
return LaunchDescription([
DeclareLaunchArgument(
'world',
default_value=[worlds, ''],
description='SDF world file'),
model_arg,
gazebo,
spawn_entity,
robot_state_publisher
])
地図作成プログラムを起動します。
ros2 launch hajimecart_navigation online_async_launch.py use_sim_time:=True
online_async_launch.py
import os
from launch import LaunchDescription
from launch.actions import DeclareLaunchArgument
from launch.substitutions import LaunchConfiguration
from launch_ros.actions import Node
from ament_index_python.packages import get_package_share_directory
def generate_launch_description():
use_sim_time = LaunchConfiguration('use_sim_time')
slam_params_file = LaunchConfiguration('slam_params_file')
default_params_file = os.path.join(get_package_share_directory("hajimecart_navigation"),
'config', 'mapper_params_online_async.yaml')
declare_use_sim_time_argument = DeclareLaunchArgument(
'use_sim_time',
default_value='true',
description='Use simulation/Gazebo clock')
declare_slam_params_file_cmd = DeclareLaunchArgument(
'slam_params_file',
default_value=default_params_file,
description='Full path to the ROS2 parameters file to use for the slam_toolbox node')
start_async_slam_toolbox_node = Node(
parameters=[
slam_params_file,
{'use_sim_time': use_sim_time}
],
package='slam_toolbox',
executable='async_slam_toolbox_node',
name='slam_toolbox',
output='screen')
ld = LaunchDescription()
ld.add_action(declare_use_sim_time_argument)
ld.add_action(declare_slam_params_file_cmd)
ld.add_action(start_async_slam_toolbox_node)
return ld
willowgarage.world
<?xml version="1.0" ?>
<sdf version="1.6">
<world name="default">
<include>
<uri>model://sun</uri>
</include>
<include>
<uri>model://ground_plane</uri>
</include>
<include>
<uri>model://willowgarage</uri>
</include>
</world>
</sdf>
地図作成の様子を画面に表示するために、RViz2を起動します。
ros2 launch hajimecart_description display_nav.launch.py use_sim_time:=True
シミュレータ上で地図作成
キーボードで自律移動ロボットを操縦して、部屋を周ります。
ros2 run teleop_twist_keyboard teleop_twist_keyboard
RViz2の画面上に生成されている地図が表示されます。
自律移動ロボットが動いていくと地図が生成されていきます。画面を見ながら地図の出来具合を確認します。
作成した地図を保存
地図がよい具合に出来上がったら、地図を保存します。この例では、ファイル名 my_map-willowに地図を出力します。
ros2 run nav2_map_server map_saver_cli -f my_map-willow
作成した地図です。
画像で、黒線が占有領域(壁や障害物)、白色が自由領域(移動可能)、グレーが未知領域です。
動画
地図作成の様子を動画にしました。
シミュレーションによる自律移動ロボットの地図作成 (ROS2 Humble)
自律移動ロボット(AMR)のナビゲーション
上の画像は、シミュレータGazeboの画面(左)と、RViz2の画面(右)
ナビゲーションでは、自律移動ロボット(AMR)が、自己位置を認識し、目標位置への経路を計画し移動します。
シミュレータを起動
シミュレータGazeboを起動します。地図作成に使用したwillowgarageの部屋を使います。
ros2 launch hajimecart_gazebo willowgarage_world.launch.py
シミュレータでナビゲーションを起動
ナビゲーションプログラムを起動します。地図は上で作成した地図を指定します。
ros2 launch hajimecart_navigation navigation2.launch.py use_sim_time:=True map:=${HOME}/hajimecart_ws/src/hajimecart_navigation/maps/my_map-willow.yaml
navigation2.launch.py
import os
from ament_index_python.packages import get_package_share_directory
from launch import LaunchDescription
from launch.actions import DeclareLaunchArgument
from launch.actions import IncludeLaunchDescription
from launch.launch_description_sources import PythonLaunchDescriptionSource
from launch.substitutions import LaunchConfiguration
def generate_launch_description():
use_sim_time = LaunchConfiguration('use_sim_time', default='false')
map_dir = LaunchConfiguration(
'map',
default=os.path.join(
get_package_share_directory('hajimecart_navigation'),
'maps',
'my_map.yaml'))
param_dir = LaunchConfiguration(
'params_file',
default=os.path.join(
get_package_share_directory('hajimecart_navigation'),
'params',
'nav2_params.yaml'))
nav2_launch_file_dir = os.path.join(get_package_share_directory('nav2_bringup'), 'launch')
return LaunchDescription([
DeclareLaunchArgument(
'map',
default_value=map_dir,
description='Full path to map file to load'),
DeclareLaunchArgument(
'params_file',
default_value=param_dir,
description='Full path to param file to load'),
DeclareLaunchArgument(
'use_sim_time',
default_value='True',
description='Use simulation (Gazebo) clock if true'),
IncludeLaunchDescription(
PythonLaunchDescriptionSource([nav2_launch_file_dir, '/bringup_launch.py']),
launch_arguments={
'map': map_dir,
'use_sim_time': use_sim_time,
'params_file': param_dir}.items(),
)
])
画面表示および操作用にRViz2を起動します。
ros2 launch hajimecart_description display_nav.launch.py use_sim_time:=True
display_nav.launch.py
import os
from ament_index_python.packages import get_package_share_path
from launch import LaunchDescription
from launch.actions import DeclareLaunchArgument
from launch_ros.actions import Node
from launch_ros.parameter_descriptions import ParameterValue
from launch.substitutions import Command, LaunchConfiguration
def generate_launch_description():
use_sim_time = LaunchConfiguration('use_sim_time', default='True')
urdf_model_dir = get_package_share_path('hajimecart_description')
urdf_model_path = os.path.join(urdf_model_dir, 'urdf', 'hajimecart.urdf')
model_arg = DeclareLaunchArgument(name='model', default_value=str(urdf_model_path),
description='Absolute path to robot urdf file')
rviz_config_dir = get_package_share_path('hajimecart_description')
rviz_config_path = os.path.join(rviz_config_dir, 'rviz', 'nav2_default_view.rviz')
# rviz_config_path = os.path.join(rviz_config_dir, 'rviz', 'slam_toolbox_default.rviz')
rviz_arg = DeclareLaunchArgument(name='rvizconfig', default_value=str(rviz_config_path),
description='Absolute path to rviz config file')
rviz_node = Node(
package='rviz2',
executable='rviz2',
name='rviz2',
output='screen',
arguments=['-d', LaunchConfiguration('rvizconfig')],
)
robot_description = ParameterValue(Command(['xacro ', LaunchConfiguration('model')]),
value_type=str)
robot_state_publisher_node = Node(
package='robot_state_publisher',
executable='robot_state_publisher',
parameters=[{'use_sim_time': use_sim_time, 'robot_description': robot_description}]
)
return LaunchDescription([
model_arg,
rviz_arg,
rviz_node,
robot_state_publisher_node
])
RViz2を起動すると、画面上に地図が現れます。
自律移動ロボットの現在位置と向きを設定
自律移動ロボットの現在位置と向きを設定します。
RViz2の上のメニューから「2D Pose Estimate」をクリックします。
表示された緑色の矢印で、矢印の起点がロボットの位置、矢印の先がロボットの向きになるように設定します。
設定したロボットの現在位置の周りに、緑色の点群が表示されます。
<自己位置の推定>
車輪の回転量から計算した位置(オドメトリ)と、LiDARの情報と地図を照らし合わせて、確率な方法で求めます。
地図の黒線の周囲が水色とピンク色で表示されます。
<グローバル・コストマップ>
地図にある障害物の情報を管理します。
ロボット近辺ではコストマップの色が濃くなります。
<ローカル・コストマップ>
センサ(LiDAR)による障害物の情報を管理します。
自律移動ロボットの目標位置と向きを設定
目標地点を設定します。
RViz2の上のメニューから「Nav2 Goal」をクリックします。
表示された緑色の矢印で、ロボットの目標位置と向きを設定します。
現在位置と目標位置の間に、赤い線が引かれます。
<グローバル・パス(経路)>
地図に基づき、障害物を避けて(グローバル・コストマップ)、目標位置までの経路です。
ロボットはおおむね赤い線に沿って進みます。
<ローカル・パス(経路)>
円弧状の青い線はグローバルの経路に沿うように、障害物を避けて(ローカル・コストマップ) 、ロボットの加速度を考慮した経路です。
自律移動ロボットの移動
径路が計算されると、自律移動ロボットは移動を始めます。
ロボットには、移動機構による移動方向の制限、速度や加速度の制限があります。それらを考慮し、さらに、LiDARにより検出された地図にない新たな障害物を避けて進みます。
目標位置と向きに到達するとロボットは停止します。
動画
自律移動ロボットでナビゲーションにより移動するシミュレーション(ROS2 Humble使用)


