1、move_bae框架
参考:http://wiki.ros.org/move_base
1.主体介绍:
move_base是ROS下关于机器人路径规划的中心枢纽。
它通过订阅激光雷达、map地图、amcl的定位等数据,然后规划出全局和局部路径,再将路径转化为机器人的速度信息,最终实现机器人导航。
首先左上角的amcl左上角的amcl模块是ROS的导航定位模块,amcl也叫自适应蒙特卡罗定位,amcl通过订阅scan、map和tf信息,发布出机器人的pose,以供move_base使用。
左下角odom,即机器人里程计信息。
右上角,map,顾名思义,我们需要的先验地图信息,一般通过slam建图后保存,map_server包通过解析slam建好的地图并发布出去。
右下角的传感器topic则在局部路径规划时起到作用,这部分就是costmap包起到的作用了,costmap为代价地图,目前主要的有inflation_layer、obstacle_layer、static_layer、voxel_layer四个plugins,分别为膨胀层、障碍物层、静态层和体素层。一般我们的全局路径需要静态层和膨胀层,因为全局规划应该只考虑到地图信息,所以一般都是静态的,而局部路径规划则需要考虑到实时的障碍物信息,所以需要障碍物层和膨胀层,
2.构成
它由如下三部分构成:
- 实现一个actionlib,用于设定目标位置。
- 连接global planer和local planner,用于实现导航。可以通过重新实现nav_core::BaseGlobalPlanner 和 nav_core::BaseLocalPlanner 的接口,修改global planer和local planner的导航策略
- 维护两个two costmaps,一个为global planer,另一个为local planner
- recovery_behaviors: 如果找不到一条到达目标的路径,它就会运行一些清理机制,把地图中一些无效障碍物清理掉,重新制定路径。recovery_behaviors默认策略:
recovery_behaviors默认策略:
2、move_base参数
max_obstacle_height: 5.0 # assume something like an arm is mounted on top of the robot
# Obstacle Cost Shaping (http://wiki.ros.org/costmap_2d/hydro/inflation)
robot_radius: 0.20 # 机器人底盘形状,圆形使用robot_radius,非圆形使用footprint(kobuki: 0.18)
# footprint: [[x0, y0], [x1, y1], ... [xn, yn]] # if the robot is not circular
map_type: voxel
obstacle_layer:
enabled: true
max_obstacle_height: 0.6
origin_z: 0.0
z_resolution: 0.2
z_voxels: 10
unknown_threshold: 15
mark_threshold: 0
combination_method: 1
track_unknown_space: true #true needed for disabling global path planning through unknown space
obstacle_range: 2.5
raytrace_range: 3.0
origin_z: 0.0
z_resolution: 0.2
z_voxels: 10
publish_voxel_map: false
observation_sources: scan bump
scan:
data_type: LaserScan
topic: scan
marking: true
clearing: true
min_obstacle_height: 0.25
max_obstacle_height: 0.35
inf_is_valid: true
bump:
data_type: PointCloud2
topic: mobile_base/sensors/bumper_pointcloud
marking: true
clearing: false
min_obstacle_height: 0.0
max_obstacle_height: 0.15
#camera:
#data_type: PointCloud2
#topic: camera/depth/points
#marking: true
#clearing: true
#min_obstacle_height: 0.4
#max_obstacle_height: 0.8
# for debugging only, let's you see the entire voxel grid
#cost_scaling_factor and inflation_radius were now moved to the inflation_layer ns
inflation_layer:
enabled: true
cost_scaling_factor: 5.0 # exponential rate at which the obstacle cost drops off (default: 10)
inflation_radius: 0.5 # max. distance from an obstacle at which costs are incurred for planning paths.
static_layer:
enabled: true
2. global_costmap_params.yaml
global_costmap:
global_frame: /map
robot_base_frame: /base_footprint
update_frequency: 1.0 #基于传感器数据更新的频率,降低频率可以减少CPU负载。合理值在1~5
publish_frequency: 0.5 #对于global static map,通常不需要持续发布
static_map: true
transform_tolerance: 0.5 #TF坐标系更新容忍的最大延迟,单位秒
plugins:
- {name: static_layer, type: "costmap_2d::StaticLayer"}
- {name: obstacle_layer, type: "costmap_2d::VoxelLayer"}
- {name: inflation_layer, type: "costmap_2d::InflationLayer"}
由于在全局路径规划中,我们只应该考虑静态地图,即我们之前slam建立好的地图,所以我们把static_map设为true,rolling_window设为false,再看plugins:有两个层,静态层和膨胀层,这样就完成了global的yaml的配置,如果你需要把障碍物层也添加到全局地图中,plugins加入,同时别忘了在下面声明数据来源。
3. local_costmap_params.yaml
local_costmap:
global_frame: odom
robot_base_frame: /base_footprint
update_frequency: 5.0 基于传感器数据更新的频率,降低频率可以减少CPU负载
publish_frequency: 2.0 发布地图的更新频率, 1HZ是足够好,除非机器人移动速度更快
static_map: false
rolling_window: true
width: 4.0 rolling局部地图宽
height: 4.0 rolling局部地图长
resolution: 0.05 分辨率要与使用地图YAML文件中描述的分辨率一致
transform_tolerance: 0.5 TF坐标系更新容忍的最大延迟,单位秒
plugins:
- {name: obstacle_layer, type: "costmap_2d::VoxelLayer"}
- {name: inflation_layer, type: "costmap_2d::InflationLayer"}
这里由于是局部层,所以我们要把static_map设为fasle,我们并不希望使用静态的地图,因为这不利于我们的局部避障,rollung_window设为true。下面的plugins就为各个层的设置了,在局部路径规划中我们只需要考虑障碍物的信息就可以了,不需要考虑我们之前slam建立的静态地图,所有我们添加了两个图层,即障碍物层和障碍物的膨胀层,下面这个很重要,我们需要声明我们的障碍物层的数据来源,即scan,要把topic对应你的scan的topic,否则你可能发现rviz里的local_costmap没有数据,这就是你没有声明的原因。最后两行为设置膨胀层的半径大小。
4. dwa_local_planner_params.yaml
DWAPlannerROS:
# Robot Configuration Parameters - Kobuki
max_vel_x: 0.5 # 0.55
min_vel_x: 0.0
max_vel_y: 0.0 # diff drive robot
min_vel_y: 0.0 # diff drive robot
max_trans_vel: 0.5 # choose slightly less than the base's capability
min_trans_vel: 0.1 # this is the min trans velocity when there is negligible rotational velocity
trans_stopped_vel: 0.1
# Warning!
# do not set min_trans_vel to 0.0 otherwise dwa will always think translational velocities
# are non-negligible and small in place rotational velocities will be created.
max_rot_vel: 5.0 # choose slightly less than the base's capability
min_rot_vel: 0.4 # this is the min angular velocity when there is negligible translational velocity
rot_stopped_vel: 0.4
acc_lim_x: 1.0 # maximum is theoretically 2.0, but we
acc_lim_theta: 2.0
acc_lim_y: 0.0 # diff drive robot
# Goal Tolerance Parameters
yaw_goal_tolerance: 0.3 # 0.05
xy_goal_tolerance: 0.15 # 0.10
# latch_xy_goal_tolerance: false
# Forward Simulation Parameters
sim_time: 1.0 # 1.7
vx_samples: 6 # 3
vy_samples: 1 # diff drive robot, there is only one sample
vtheta_samples: 20 # 20
# Trajectory Scoring Parameters
path_distance_bias: 64.0 # 32.0 - weighting for how much it should stick to the global path plan
goal_distance_bias: 24.0 # 24.0 - wighting for how much it should attempt to reach its goal
occdist_scale: 0.5 # 0.01 - weighting for how much the controller should avoid obstacles
forward_point_distance: 0.325 # 0.325 - how far along to place an additional scoring point
stop_time_buffer: 0.2 # 0.2 - amount of time a robot must stop in before colliding for a valid traj.
scaling_speed: 0.25 # 0.25 - absolute velocity at which to start scaling the robot's footprint
max_scaling_factor: 0.2 # 0.2 - how much to scale the robot's footprint when at speed.
# Oscillation Prevention Parameters
oscillation_reset_dist: 0.05 # 0.05 - how far to travel before resetting oscillation flags
# Debugging
publish_traj_pc : true
publish_cost_grid_pc: true
global_frame_id: odom
# Differential-drive robot configuration - necessary?
# holonomic_robot: false
5. move_base_params.yaml
shutdown_costmaps: false
controller_frequency: 5.0
controller_patience: 3.0
planner_frequency: 1.0
planner_patience: 5.0
oscillation_timeout: 10.0
oscillation_distance: 0.2
# local planner - default is trajectory rollout
base_local_planner: "dwa_local_planner/DWAPlannerROS"
base_global_planner: "navfn/NavfnROS" #alternatives: global_planner/GlobalPlanner, carrot_planner/CarrotPlanner
GlobalPlanner: # Also see: http://wiki.ros.org/global_planner
old_navfn_behavior: false # Exactly mirror behavior of navfn, use defaults for other boolean parameters, default false
use_quadratic: true # Use the quadratic approximation of the potential. Otherwise, use a simpler calculation, default true
use_dijkstra: true # Use dijkstra's algorithm. Otherwise, A*, default true
use_grid_path: false # Create a path that follows the grid boundaries. Otherwise, use a gradient descent method, default false
allow_unknown: true # Allow planner to plan through unknown space, default true
#Needs to have track_unknown_space: true in the obstacle / voxel layer (in costmap_commons_param) to work
planner_window_x: 0.0 # default 0.0
planner_window_y: 0.0 # default 0.0
default_tolerance: 0.0 # If goal in obstacle, plan to the closest point in radius default_tolerance, default 0.0
publish_scale: 100 # Scale by which the published potential gets multiplied, default 100
planner_costmap_publish_frequency: 0.0 # default 0.0
lethal_cost: 253 # default 253
neutral_cost: 50 # default 50
cost_factor: 3.0 # Factor to multiply each cost from costmap by, default 3.0
publish_potential: true # Publish Potential Costmap (this is not like the navfn pointcloud2 potential), default true
7. navfn_global_planner_params.yaml
NavfnROS:
visualize_potential: false #Publish potential for rviz as pointcloud2, not really helpful, default false
allow_unknown: false #Specifies whether or not to allow navfn to create plans that traverse unknown space, default true
#Needs to have track_unknown_space: true in the obstacle / voxel layer (in costmap_commons_param) to work
planner_window_x: 0.0 #Specifies the x size of an optional window to restrict the planner to, default 0.0
planner_window_y: 0.0 #Specifies the y size of an optional window to restrict the planner to, default 0.0
default_tolerance: 0.0 #If the goal is in an obstacle, the planer will plan to the nearest point in the radius of default_tolerance, default 0.0
#The area is always searched, so could be slow for big values
8. rviz显示
注意:要将rviz的fixed frame设成map,因为map才是global_frame_id。
rviz居然连粒子都可以显示,显示让我对amcl粒子更新有了更深刻的理解。
首先在参数表里面有几个比较重要的参数。
~initial_pose_x (double, default: 0.0 meters)
Initial pose mean (x), used to initialize filter with Gaussian distribution.
~initial_pose_y (double, default: 0.0 meters)
Initial pose mean (y), used to initialize filter with Gaussian distribution.
~initial_pose_a (double, default: 0.0 radians)
Initial pose mean (yaw), used to initialize filter with Gaussian distribution.
~initial_cov_xx (double, default: 0.5*0.5 meters)
Initial pose covariance (x*x), used to initialize filter with Gaussian distribution.
~initial_cov_yy (double, default: 0.5*0.5 meters)
Initial pose covariance (y*y), used to initialize filter with Gaussian distribution.
~initial_cov_aa (double, default: (π/12)*(π/12) radian)
Initial pose covariance (yaw*yaw), used to initialize filter with Gaussian distribution.
这个代表了你初始化粒子时粒子分布的一个状态,注意要把方差设的大一些,要不所有例子上来就是一坨的就没法玩了。
参考:http://blog.csdn.net/chenxingwangzi/article/details/50038413
local map在rviz 中Add-> by topic-> local map
2、move_base启动
1.move_base.launch配置。
<launch>
<include file="$(find turtlebot_navigation)/launch/includes/velocity_smoother.launch.xml"/>
<include file="$(find turtlebot_navigation)/launch/includes/safety_controller.launch.xml"/>
<arg name="odom_frame_id" default="odom"/>
<arg name="base_frame_id" default="base_footprint"/>
<arg name="global_frame_id" default="map"/>
<arg name="odom_topic" default="odom" />
<arg name="laser_topic" default="scan" />
<arg name="custom_param_file" default="$(find turtlebot_navigation)/param/dummy.yaml"/>
<node pkg="move_base" type="move_base" respawn="false" name="move_base" output="screen">
<rosparam file="$(find turtlebot_navigation)/param/costmap_common_params.yaml" command="load" ns="global_costmap" />
<rosparam file="$(find turtlebot_navigation)/param/costmap_common_params.yaml" command="load" ns="local_costmap" />
<rosparam file="$(find turtlebot_navigation)/param/local_costmap_params.yaml" command="load" />
<rosparam file="$(find turtlebot_navigation)/param/global_costmap_params.yaml" command="load" />
<rosparam file="$(find turtlebot_navigation)/param/dwa_local_planner_params.yaml" command="load" />
<rosparam file="$(find turtlebot_navigation)/param/move_base_params.yaml" command="load" />
<rosparam file="$(find turtlebot_navigation)/param/global_planner_params.yaml" command="load" />
<rosparam file="$(find turtlebot_navigation)/param/navfn_global_planner_params.yaml" command="load" />
<!-- external params file that could be loaded into the move_base namespace -->
<rosparam file="$(arg custom_param_file)" command="load" />
<!-- reset frame_id parameters using user input data -->
<param name="global_costmap/global_frame" value="$(arg global_frame_id)"/>
<param name="global_costmap/robot_base_frame" value="$(arg base_frame_id)"/>
<param name="local_costmap/global_frame" value="$(arg odom_frame_id)"/>
<param name="local_costmap/robot_base_frame" value="$(arg base_frame_id)"/>
<param name="DWAPlannerROS/global_frame_id" value="$(arg odom_frame_id)"/>
<remap from="cmd_vel" to="navigation_velocity_smoother/raw_cmd_vel"/>
<remap from="odom" to="$(arg odom_topic)"/>
<remap from="scan" to="$(arg laser_topic)"/>
</node>
</launch>
2. velocity_smoother.launch配置:
<launch>
<node pkg="nodelet" type="nodelet" name="navigation_velocity_smoother" args="load yocs_velocity_smoother/VelocitySmootherNodelet mobile_base_nodelet_manager">
<rosparam file="$(find turtlebot_bringup)/param/defaults/smoother.yaml" command="load"/>
<remap from="navigation_velocity_smoother/smooth_cmd_vel" to="cmd_vel_mux/input/navi"/>
<!-- Robot velocity feedbacks; use the default base configuration -->
<remap from="navigation_velocity_smoother/odometry" to="odom"/>
<remap from="navigation_velocity_smoother/robot_cmd_vel" to="mobile_base/commands/velocity"/>
</node>
</launch>
3.safety_controller.launch配置:
<launch>
<node pkg="nodelet" type="nodelet" name="kobuki_safety_controller" args="load kobuki_safety_controller/SafetyControllerNodelet mobile_base_nodelet_manager">
<remap from="kobuki_safety_controller/cmd_vel" to="cmd_vel_mux/input/safety_controller"/>
<remap from="kobuki_safety_controller/events/bumper" to="mobile_base/events/bumper"/>
<remap from="kobuki_safety_controller/events/cliff" to="mobile_base/events/cliff"/>
<remap from="kobuki_safety_controller/events/wheel_drop" to="mobile_base/events/wheel_drop"/>
</node>
</launch>