Hello,
I am using Ubuntu 16.04, ROS-kinetic to run the navigation stack (with global_planner and teb_local_planner) on a Youbot (on Gazebo).
Although I am able to send goals and get them executed properly, I have issues under the following scenario (configuration data follows):
When I add an obstacle(unmapped) into the environment(mapped), say blocking a certain path (alternative path available), and give a goal beyond the obstacle. I am running a rolling window for the local planner here, and the alternate path is not covered in the local costmap.
The issues I face:
Case 1: using obstacle layer in global costmap and local costmap: As soon as my laserscan detects the obstacle, marking of the global costmap starts and the planner issues a new global path upon sensing blocked path. Here, obviously the obstacle "avoidance" is being done by the global planner instead of the local planner.
Case 2: using obstacle layer only in the local costmap: The global costmap stays oblivious to the obstacle and upon reaching the blocked path, the local planner starts trying to look for alternative paths while the global planner directs it to continue moving along this path( since it is still unaware of obstacle). [Here, I believed that if unsuccessful in finding the path even after recovery behaviour, the global planner would issue a viable path. However, it never reaches even recovery stage as the local planner keeps probing the rolling window for trajectories.] As mentioned earlier, upon blocking this path, the alternative route is too far away to be included in the local costmap window [It achieves this when the window size is increased, but that takes up too much system processing for me to consider.] and the robot gets stuck.
Is it ok to stick with Case 1 and lower local planner's utility or Case 2 can be improved to cause global planner to take information from local costmap to replan when needed? or would some other plan of action be better?
I did read up similar questions like this one here. However, increasing the planner frequency doesn't seem to have any effect as probably the global planner still does not consider the path blocked?
I also came across this which suggests that a 'false' returned from computeVelocityCommands from localplanner would force globalplanner to consider an alternative route? Considering this, is there a way to allow 'max_controller_retries' after which the local planner would give up and issue this 'False'?
Thanks
The configuration files:
---> move_base_params
oscillation_distance: 0.1
oscillation_timeout: 5.0
base_global_planner: "global_planner/GlobalPlanner"
planner_frequency: 10.0
planner_patience: 1.0
base_local_planner: "teb_local_planner/TebLocalPlannerROS"
controller_frequency: 10.0
controller_patience: 15.0
shutdown_costmaps: true
clearing_rotation_allowed: false
recovery_behaviours: [{name: potential_field_recovery, type: potential_field_recovery/PotentialFieldRecovery},{name: aggressive_reset, type: clear_costmap_recovery/ClearCostmapRecovery}]
aggressive_reset:
reset_distance: 0.5
layer_names: ["obstacle_layer"]
--> global_costmap_params : set for Case1
global_costmap:
global_frame: /map
robot_base_frame: base_footprint
update_frequency: 4.0
publish_frequency: 2.0
static_map: true
resolution: 0.05
inflation_radius: 0.38
cost_scaling_factor: 10.0
transform_tolerance: 3.0
plugins:
- {name: static_layer, type: "costmap_2d::StaticLayer"}
- {name: obstacle_layer, type: "costmap_2d::ObstacleLayer"}
- {name: inflation_layer, type: "costmap_2d::InflationLayer"}
--> local_costmap_params
local_costmap:
global_frame: /map
robot_base_frame: base_footprint
update_frequency: 2.5
publish_frequency: 2.0
static_map: false
rolling_window: true
width: 4.0
height: 4.0
resolution: 0.1
transform_tolerance: 3.0
plugins:
- {name: static_layer, type: "costmap_2d::StaticLayer"}
- {name: obstacle_layer, type: "costmap_2d::ObstacleLayer"}
--> costmap_common_params
footprint: [ [-0.3,-0.225], [0.3,-0.225], [0.3,0.225], [-0.3,0.225] ]
transform_tolerance: 0.2
map_type: costmap
obstacle_layer:
enabled: true
obstacle_range: 5.0
raytrace_range: 5.5
inflation_radius: 0.38
track_unknown_space: false
combination_method: 1
observation_sources: base_scan
base_scan: {sensor_frame: base_laser_front_link, data_type: LaserScan, topic: /scan, marking: true, clearing: true, expected_update_rate: 0.5, observation_persistence: 0.0, min_obstacle_height: -0.10, max_obstacle_height: 2.0}
inflation_layer:
enabled: true
cost_scaling_factor: 10.0 # exponential rate at which the obstacle cost drops off (default: 10)
inflation_radius: 0.38 # max. distance from an obstacle at which costs are incurred for planning paths.
static_layer:
enabled: true
map_topic: "/map"
--> teb_local_planner_params
TebLocalPlannerROS:
odom_topic: odom
teb_autosize: True
dt_ref: 0.3 #0.5
dt_hysteresis: 0.1
global_plan_overwrite_orientation: True
global_plan_viapoint_sep: -0.1 #1.0
max_global_plan_lookahead_dist: 3.0 #2
feasibility_check_no_poses: 4 #2
allow_init_with_backwards_motion: True
# Robot
max_vel_x: 0.8
max_vel_y: 0.8
max_vel_x_backwards: 0.8
max_vel_theta: 1.2 # the angular velocity is also bounded by min_turning_radius in case of a carlike robot (r = v / omega)
acc_lim_x: 1.25
acc_lim_theta: 1.6
# ********************** Carlike robot parameters ********************
min_turning_radius: 0.0 # Min turning radius of the carlike robot (compute value using a model or adjust with rqt_reconfigure manually)
footprint_model: # types: "point", "circular", "two_circles", "line", "polygon"
type: "line"
radius: 0.2 # for type "circular"
line_start: [-0.168, 0.0] # for type "line"
line_end: [0.168, 0.0] # for type "line"
front_offset: 0.2 # for type "two_circles"
front_radius: 0.2 # for type "two_circles"
rear_offset: 0.2 # for type "two_circles"
rear_radius: 0.2 # for type "two_circles"
vertices: [ [0.25, -0.05], [0.18, -0.05], [0.18, -0.18], [-0.19, -0.18], [-0.25, 0], [-0.19, 0.18], [0.18, 0.18], [0.18, 0.05], [0.25, 0.05] ] # for type "polygon"
# GoalTolerance
xy_goal_tolerance: 0.15
yaw_goal_tolerance: 0.1
free_goal_vel: False
# Obstacles
min_obstacle_dist: 0.25 # This value must also include our robot's expansion, since footprint_model is set to "line".
inflation_dist: 0.3
dynamic_obstacle_inflation_distance: 0.4
include_costmap_obstacles: True
costmap_obstacles_behind_robot_dist: 2.0
obstacle_poses_affected: 30
costmap_converter_plugin: ""
costmap_converter_spin_thread: True
costmap_converter_rate: 5
# Optimization
no_inner_iterations: 3
no_outer_iterations: 3
optimization_activate: True
optimization_verbose: False
penalty_epsilon: 0.1
weight_max_vel_x: 2
weight_max_vel_theta: 1
weight_acc_lim_x: 1
weight_acc_lim_theta: 1
weight_kinematics_nh: 0
weight_kinematics_forward_drive: 0 #100 when obstacles
weight_kinematics_turning_radius: 0
weight_optimaltime: 1
weight_obstacle: 50
weight_dynamic_obstacle: 10 # not in use yet
weight_viapoint: 5
# Homotopy Class Planner
enable_homotopy_class_planning: True
enable_multithreading: True
simple_exploration: False
max_number_classes: 3
selection_cost_hysteresis: 1.0
selection_obst_cost_scale: 1.0
selection_alternative_time_cost: False
roadmap_graph_no_samples: 15
roadmap_graph_area_width: 5
h_signature_prescaler: 0.5
h_signature_threshold: 0.1
obstacle_keypoint_offset: 0.1
obstacle_heading_threshold: 0.45
visualize_hc_graph: False
Originally posted by harshal on ROS Answers with karma: 35 on 2018-03-05
Post score: 0
Original comments
Comment by tropic on 2020-10-24:
Hi. Did you find a proper setup to have the global planner take the blocked path into consideration? I have tried very similar settings as yours, but it does not work as intended, especially the static layers for the local costmap makes the costmap non-functional.
Comment by harshal on 2020-10-30:
Hi, I carried on with keeping the obstacle layer in the global costmap as well. Turning the global planner frequency to 0.0 makes the planner use only the data available at plan time, and lets the local planner carry on the "dynamic" obstacle avoidance for anything not reflected in the initial plan. As for the local planner, I let the local planner fail after some tries and this triggers the global planner to plan around the obstacles sanely.
I do still have the static layer in my current local costmap setup (needed). Could you elaborate as to what a non-functional costmap means in your case?
P.S.: This strategy is likely to fail for larger obstacles. Depending upon your configuration, the local planner might continuously keep trying to look for new paths. So if you have a local planner struggling unrelentingly(no timeouts or max no. of attempts, etc.) to go around bigger map changes/obstacles, a non-zero rate of global planning might be useful.