概要
ロボットカート(ロボット台車)のナビゲーションを行います。
1)ロボットカートを使って部屋の2D地図を作成します。
2)地図上で目標位置・向きを指定して、そこまでロボットカートを自動運転させます。経路上に障害物があっても、それを避けてロボットカートが移動します。
2)地図上で目標位置・向きを指定して、そこまでロボットカートを自動運転させます。経路上に障害物があっても、それを避けてロボットカートが移動します。
3)パラメータ調整のためシミュレーションを使用します。
動画
ロボットカートをROSのナビゲーションで動かす
ロボットカートをROSのナビゲーションで動かす(その2)
ロボットカートを動かし、地図上にLiDARの測距データを表示する
ロボットカートのナビゲーションをROSでシミュレーションする
ロボットカートをジョイパッドで操縦する
地図作成
ロボットカートが移動する部屋の地図を作成します。
ロボットカートをジョイパッドで操縦し、部屋を一周します。
Launchファイルを起動します。
<launch>
<!-- Load the HajimeCart URDF model into the parameter server -->
<param name="robot_description" textfile="$(find hajimecart_description)/urdf/hajimecart_robothw.urdf" />
<!-- Convert /joint_states messages published by Gazebo to /tf messages,
e.g., for rviz-->
<node name="joint_state_publisher" pkg="joint_state_publisher" type="joint_state_publisher" output="screen" />
<node name="robot_state_publisher" pkg="robot_state_publisher" type="robot_state_publisher" output="screen" />
</launch>
roslaunch hajimecart_description hajimecart_robothw.launch
ros_serial関連のノードをまとめて起動します。
hajimecart_rosserial_all.launch
<launch>
<node pkg="rosserial_python" type="serial_node.py" name="serial_node">
<param name="port" value="/dev/ttyACM0"/>
<param name="baud" value="230400"/>
</node>
<node name="cmdvel_cmdmotorspeed" pkg="cmdvel_cmdmotorspeed" type="cmdvel_cmdmotorspeed"/>
<node name="odometry_publisher" pkg="odometry_publisher" type="odometry_publisher"/>
</launch>
roslaunch teleop_joy hajimecart_rosserial_all.launch
ジョイパッド関連のノードをまとめて起動します。
hajimecart_teleop.launch
<launch>
<arg name="dev" default="/dev/input/js0"/>
<node name="joy_node" pkg="joy" type="joy_node">
<param name="dev" value="$(arg dev)"/>
</node>
<node name="teleop_joy" pkg="teleop_joy" type="teleop_joy"/>
</launch>
roslaunch teleop_joy hajimecart_teleop.launch dev:=/dev/input/js0
360度測距センサーのLiDARを起動します。
roslaunch rplidar_ros rplidar.launch
rosbagを起動して、これから測定するデータを記録していきます。
rosbag record -a -O sakamotobag
ロボットカートをジョイパッドで操縦して、ロボットカートに部屋を一周させます。
記録を終了するには、rosbagをCTRL-Cで終了させます。
記録したbagファイルの情報を確認するには以下のコマンドです。
rosbag info sakamotobag.bag
path: sakamotobag.bag
version: 2.0
duration: 1:46s (106s)
start: Sep 13 2019 13:41:36.38 (1568349696.38)
end: Sep 13 2019 13:43:22.47 (1568349802.47)
size: 7.3 MB
messages: 24918
compression: none [10/10 chunks]
types: diagnostic_msgs/DiagnosticArray [60810da900de1dd6ddd437c3503511da]
geometry_msgs/Twist [9f195f881246fdfa2798d1d3eebca84a]
nav_msgs/Odometry [cd5e73d190d741a2f92e81eda573aca7]
rosgraph_msgs/Log [acffd30cd6b6de30f120938c17c593fb]
sensor_msgs/JointState [3066dcd76a6cfaef579bd0f34173e9fd]
sensor_msgs/Joy [5a9ea5f83505693b71e785041e67a8bb]
sensor_msgs/LaserScan [90c7ef2dc6895d81024acba2ac42f369]
std_msgs/Float32MultiArray [6a40e0ffa6a17a503ac3f8616991b1f6]
std_msgs/Int32MultiArray [1d99f79f8b325b44fee908053e9c945b]
tf2_msgs/TFMessage [94810edda583a504dfda3829e70d7eec]
topics: /cmd_vel 10601 msgs : geometry_msgs/Twist
/cmdmotorspeed 2658 msgs : std_msgs/Float32MultiArray
/diagnostics 92 msgs : diagnostic_msgs/DiagnosticArray
/encoder 2646 msgs : std_msgs/Int32MultiArray
/joint_states 1066 msgs : sensor_msgs/JointState
/joy 688 msgs : sensor_msgs/Joy
/odom 2653 msgs : nav_msgs/Odometry
/rosout 14 msgs : rosgraph_msgs/Log (4 connections)
/rosout_agg 2 msgs : rosgraph_msgs/Log
/scan 774 msgs : sensor_msgs/LaserScan
/tf 3723 msgs : tf2_msgs/TFMessage (2 connections)
/tf_static 1 msg : tf2_msgs/TFMessage
測定データを記録したbagファイルを使用して地図作成にかかります。
地図作成のためのプログラムgmappingを起動します。
hajimecart_gmapping.launch
<launch>
<param name="use_sim_time" value="true"/>
<node pkg="gmapping" type="slam_gmapping" name="slam_gmapping" output="screen">
<param name="base_frame" value="base_footprint"/>
<param name="odom_frame" value="odom"/>
<param name="map_frame" value="map"/>
<param name="map_update_interval" value="2.0"/>
<param name="maxUrange" value="6.0"/>
<param name="sigma" value="0.05"/>
<param name="kernelSize" value="1"/>
<param name="lstep" value="0.05"/>
<param name="astep" value="0.05"/>
<param name="iterations" value="5"/>
<param name="lsigma" value="0.075"/>
<param name="ogain" value="3.0"/>
<param name="lskip" value="0"/>
<param name="minimumScore" value="0.0"/>
<param name="srr" value="0.1"/>
<param name="srt" value="0.2"/>
<param name="str" value="0.1"/>
<param name="stt" value="0.2"/>
<param name="linearUpdate" value="1.0"/>
<param name="angularUpdate" value="0.2"/>
<param name="temporalUpdate" value="1.0"/>
<param name="resampleThreshold" value="0.5"/>
<param name="particles" value="100"/>
<param name="xmin" value="-10.0"/>
<param name="ymin" value="-10.0"/>
<param name="xmax" value="10.0"/>
<param name="ymax" value="10.0"/>
<param name="delta" value="0.05"/>
<param name="llsamplerange" value="0.01"/>
<param name="llsamplestep" value="0.01"/>
<param name="lasamplerange" value="0.005"/>
<param name="lasamplestep" value="0.005"/>
</node>
</launch>
roslaunch hajimecart_navigation hajimecart_gmapping.launch
bagファイルを再生します。
rosbag play --clock sakamotobag.bag
地図を保存します。
rosrun map_server map_saver -f sakamotomap
gmappingで作成した地図
sakamotomap.pgm
作成した地図の情報ファイル
sakamotomap.yaml
image: sakamotomap.pgm resolution: 0.050000 origin: [-10.000000, -10.000000, 0.000000] negate: 0 occupied_thresh: 0.65 free_thresh: 0.196
ナビゲーション(実機)
ナビゲーションのためにロボットカートを起動します。
roslaunch hajimecart_description hajimecart_robothw.launch roslaunch teleop_joy hajimecart_rosserial_all.launch roslaunch rplidar_ros rplidar.launch
ナビゲーション用のLaunchファイルで、map_server、amcl、move_baseなどをまとめて起動します。
hajimecart_robothw_navigation.launch
hajimecart_robothw_navigation.launch
<launch>
<!-- Load the HajimeCart URDF model into the parameter server -->
<param name="robot_description" textfile="$(find hajimecart_description)/urdf/hajimecart_robothw.urdf"/>
<!-- Convert /joint_states messages published by Gazebo to /tf messages,
e.g., for rviz-->
<node name="robot_state_publisher" pkg="robot_state_publisher"
type="robot_state_publisher" output="screen"/>
<node name="map_server" pkg="map_server" type="map_server"
args="$(find hajimecart_navigation)/maps/sakamotomap.yaml" output="screen"/>
<include file="$(find hajimecart_navigation)/launch/amcl.launch"/>
<include file="$(find hajimecart_navigation)/launch/move_base.launch"/>
</launch>
amcl.launch
<launch>
<!-- AMCL -->
<node pkg="amcl" type="amcl" name="amcl">
<param name="min_particles" value="500"/>
<param name="max_particles" value="3000"/>
<param name="kld_err" value="0.02"/>
<param name="update_min_d" value="0.20"/>
<param name="update_min_a" value="0.20"/>
<param name="resample_interval" value="1"/>
<param name="transform_tolerance" value="0.5"/>
<param name="recovery_alpha_slow" value="0.00"/>
<param name="recovery_alpha_fast" value="0.00"/>
<param name="initial_pose_x" value="0.0"/>
<param name="initial_pose_y" value="0.0"/>
<param name="initial_pose_a" value="0.0"/>
<param name="gui_publish_rate" value="50.0"/>
<param name="laser_max_range" value="3.5"/>
<param name="laser_max_beams" value="180"/>
<param name="laser_z_hit" value="0.5"/>
<param name="laser_z_short" value="0.05"/>
<param name="laser_z_max" value="0.05"/>
<param name="laser_z_rand" value="0.5"/>
<param name="laser_sigma_hit" value="0.2"/>
<param name="laser_lambda_short" value="0.1"/>
<param name="laser_likelihood_max_dist" value="2.0"/>
<param name="laser_model_type" value="likelihood_field"/>
<param name="odom_model_type" value="diff"/>
<param name="odom_alpha1" value="0.6"/>
<param name="odom_alpha2" value="0.1"/>
<param name="odom_alpha3" value="0.1"/>
<param name="odom_alpha4" value="0.1"/>
<param name="odom_frame_id" value="odom"/>
<param name="base_frame_id" value="base_footprint"/>
</node>
</launch>
move_base.launch
<launch>
<node pkg="move_base" type="move_base" respawn="false" name="move_base" output="screen">
<param name="base_local_planner" value="dwa_local_planner/DWAPlannerROS" />
<rosparam file="$(find hajimecart_navigation)/params/costmap_common_params.yaml" command="load" ns="global_costmap" />
<rosparam file="$(find hajimecart_navigation)/params/costmap_common_params.yaml" command="load" ns="local_costmap" />
<rosparam file="$(find hajimecart_navigation)/params/local_costmap_params.yaml" command="load" />
<rosparam file="$(find hajimecart_navigation)/params/global_costmap_params.yaml" command="load" />
<rosparam file="$(find hajimecart_navigation)/params/move_base_params.yaml" command="load" />
<rosparam file="$(find hajimecart_navigation)/params/dwa_local_planner_params.yaml" command="load" />
</node>
</launch>
costmap_common_params.yaml
obstacle_range: 2.0
raytrace_range: 2.5
footprint: [[0.340, 0.160], [0.340, -0.16], [-0.100, -0.16], [-0.100, 0.16]]
inflation_radius: 0.5
cost_scaling_factor: 3.0
map_type: costmap
observation_sources: laser_scan_sensor
laser_scan_sensor: {sensor_frame: base_scan, observation_persistence: 0.0, max_obstacle_height: 0.3, min_obstacle_height: 0.0, data_type: LaserScan, topic: scan, marking: true, clearing: true}
local_costmap_params.yaml
local_costmap: global_frame: /odom robot_base_frame: /base_footprint update_frequency: 10.0 publish_frequency: 10.0 transform_tolerance: 1.0 static_map: false rolling_window: true width: 3 height: 3 resolution: 0.05
global_costmap_params.yaml
global_costmap: global_frame: /map robot_base_frame: /base_footprint update_frequency: 10.0 publish_frequency: 10.0 transform_tolerance: 1.0 static_map: true
move_base_params.yaml
shutdown_costmaps: false controller_frequency: 10.0 planner_patience: 5.0 controller_patience: 15.0 conservative_reset_dist: 3.0 planner_frequency: 5.0 oscillation_timeout: 10.0 oscillation_distance: 0.2
dwa_local_planner_params.yaml
DWAPlannerROS: # Robot Configuration Parameters max_vel_x: 0.2 min_vel_x: -0.2 max_vel_y: 0.0 min_vel_y: 0.0 # The velocity when robot is moving in a straight line max_trans_vel: 0.2 min_trans_vel: 0.04 max_rot_vel: 0.3 min_rot_vel: 0.06 acc_lim_x: 1.0 acc_lim_y: 0.0 acc_lim_theta: 1.0 # Goal Tolerance Parametes xy_goal_tolerance: 0.2 yaw_goal_tolerance: 0.2 latch_xy_goal_tolerance: false # Forward Simulation Parameters sim_time: 4.0 vx_samples: 20 vy_samples: 0 vth_samples: 40 controller_frequency: 10.0 # Trajectory Scoring Parameters path_distance_bias: 32.0 goal_distance_bias: 20.0 occdist_scale: 0.02 forward_point_distance: 0.325 stop_time_buffer: 0.2 scaling_speed: 0.25 max_scaling_factor: 0.2 # Oscillation Prevention Parameters oscillation_reset_dist: 0.05 # Debugging publish_traj_pc : true publish_cost_grid_pc: true
Launchファイルを起動します。
roslaunch hajimecart_navigation hajimecart_robothw_navigation.launch
ナビゲーション用のGUIのrvizを起動します。起動時に設定ファイルurdf_map.rvizを読み込みます。
display_map.launch
<launch> <arg name="gui" default="true" /> <arg name="rvizconfig" default="$(find hajimecart_description)/launch/urdf_map.rviz" /> <param name="use_gui" value="$(arg gui)"/> <node name="rviz" pkg="rviz" type="rviz" args="-d $(arg rvizconfig)" required="true" output="screen" /> </launch>
roslaunch hajimecart_description display_map.launch
rviz画面の地図上で、目標位置と向きをマウスで指定すると、ロボットカートは動き出します。
移動の経路上に障害物があればそれを避けて通り、目標に到達します。目標位置と向きを合わせてロボットカートは停止します。
LiDARで測定された測距データが地図上に表示されています。
本来の地図にはなかった、青色のサイコロもLiDARで検出されて、障害物として表示されています。(下の写真)
ナビゲーション(シミュレーション)
ナビゲーションで設定するパラメータは多いため、シミュレーションを使用して、パラメータを調整します。
willowgarageの世界でシミュレータgazeboを起動します。
hajimecart_gazebo_willow.launch
hajimecart_gazebo_willow.launch
<launch>
<!-- Start Gazebo with an empty world -->
<include file="$(find gazebo_ros)/launch/empty_world.launch">
<arg name="world_name" value="worlds/willowgarage.world"/>
<arg name="paused" value="false"/>
<arg name="use_sim_time" value="true"/>
<arg name="gui" value="true"/>
<arg name="headless" value="false"/>
<arg name="debug" value="false"/>
</include>
<!-- Load the HajimeCart URDF model into the parameter server -->
<param name="robot_description" textfile="$(find hajimecart_description)/urdf/hajimecart.urdf" />
<!-- Spawn a HajimeCart in Gazebo, taking the description from the
parameter server -->
<node name="spawn_urdf" pkg="gazebo_ros" type="spawn_model"
args="-param robot_description -urdf -model hajimecart -x 8 -y -8" output="screen"/>
</launch>
roslaunch hajimecart_description hajimecart_gazebo_willow.launch
willowgarageの地図でmap_serverを起動します。
hajimecart_gazebo_willow_navigation.launch
hajimecart_gazebo_willow_navigation.launch
<launch>
<!-- Load the HajimeCart URDF model into the parameter server -->
<param name="robot_description" textfile="$(find hajimecart_description)/urdf/hajimecart.urdf"/>
<!-- Convert /joint_states messages published by Gazebo to /tf messages,
e.g., for rviz-->
<node name="robot_state_publisher" pkg="robot_state_publisher"
type="robot_state_publisher" output="screen"/>
<node name="map_server" pkg="map_server" type="map_server"
args="$(find hajimecart_navigation)/maps/willow.yaml" output="screen"/>
<include file="$(find hajimecart_navigation)/launch/amcl.launch"/>
<include file="$(find hajimecart_navigation)/launch/move_base.launch"/>
</launch>
roslaunch hajimecart_navigation hajimecart_gazebo_willow_navigation.launch
ナビゲーション用のGUIのrvizを起動します。
display_map.launch
display_map.launch
<launch> <arg name="gui" default="true" /> <arg name="rvizconfig" default="$(find hajimecart_description)/launch/urdf_map.rviz" /> <param name="use_gui" value="$(arg gui)"/> <node name="rviz" pkg="rviz" type="rviz" args="-d $(arg rvizconfig)" required="true" output="screen" /> </launch>
roslaunch hajimecart_description display_map.launch
左側ウインドウのrviz画面の地図上で、目標位置と向きをマウス操作で与えると、右側ウインドウのgazebo画面でロボットカートは動き出します。
移動の経路上に障害物があればそれを避けて通り、目標に到達します。目標位置と向きを合わせてロボットカートは停止します。
移動の経路上に障害物があればそれを避けて通り、目標に到達します。目標位置と向きを合わせてロボットカートは停止します。
ROSのパラメータを調整するために、rqt_reconfigureを起動します。
rosrun rqt_reconfigure rqt_reconfigure
rqt_reconfigureを使うと、パラメータ変更がリアルタイムに反映されます。
ロボットカートのシミュレーションの動きを確認しながら、ナビゲーションのパラメータを調整していきます。
ロボットカートのシミュレーションの動きを確認しながら、ナビゲーションのパラメータを調整していきます。









