Navigation之global_planner框架学习及参数配置分析

一、全局规划器概述

对于global planner,可以采用以下三种实现之一:

"navfn/NavfnROS", "global_planner/GlobalPlanner", "carrot_planner/CarrotPlanner"

本文分析其中一种实现:global_planner/GlobalPlanner
move_base调用global_planner需要修改的文件:
1、bgp_plugin.xml
2、package.xml
以上两个文件都在/global_planner文件夹内

二、根据nav_core提供的BaseGlobalPlanner接口:

initialize(name, costmap) ——算法实例的选取
makePlan(start, goal, plan)——两个步骤完成路径的生成(①计算可行点矩阵potential_array (planner_->calculatePotentials) → ②从可行点矩阵中提取路径plan (path_maker_->getPath))
主要是以下三个实例:
1.计算“一个点”的可行性 —— p_calc_:PotentialCalculator::calculatePotential()、 QuadraticCalculator::calculatePotential()
2.计算“所有”的可行点 —— planner_:DijkstraExpansion::calculatePotentials()、 AStarExpansion::calculatePotentials()
3.从可行点中“提取路径” —— path_maker_:GridPath::getPath()、 GradientPath::getPath()

涉及到四个算法程序:A*, Dijkstra;gradient_path, grid_path

可以总结出global_planner框架:

三、例子 

3.1  举例——A*算法:

bool AStarExpansion::calculatePotentials(unsigned char* costs, double start_x, double start_y, double end_x, double end_y,
int cycles, float* potential) 
{
    queue_.clear();
    int start_i = toIndex(start_x, start_y);

    //1.将起点放入队列
    queue_.push_back(Index(start_i, 0));//push the start point into queue_

    //2.将所有点的potential都设为一个极大值
    std::fill(potential, potential + ns_, POT_HIGH);//initial all the potential as very large value

    //3.将起点的potential设为0
    potential[start_i] = 0;//initial the start position at potential as 0

    int goal_i = toIndex(end_x, end_y);
    int cycle = 0;

    //4.进入循环,继续循环的判断条件为只要队列大小大于0且循环次数小于所有格子数的2倍
    while (queue_.size() > 0 && cycle < cycles) 
    {

        //5.得到最小cost的索引,并删除它,如果索引指向goal(目的地)则退出算法,返回true
        Index top = queue_[0];//get the Index that with mini cost
        std::pop_heap(queue_.begin(), queue_.end(), greater1());//build the heap sort
        queue_.pop_back();//remove the Index with mini cost

        int i = top.i;//the Index's i from (i,cost)
        if (i == goal_i)//stop condition
            return true;

        //6.对前后左右四个点执行add函数
        //add the neighborhood 4 points into the search scope
        add(costs, potential, potential[i], i + 1, end_x, end_y);
        add(costs, potential, potential[i], i - 1, end_x, end_y);
        add(costs, potential, potential[i], i + nx_, end_x, end_y);
        add(costs, potential, potential[i], i - nx_, end_x, end_y);
    }
    return false;
}

//add函数中,如果是已经添加的的点则忽略,根据costmap的值如果是障碍物的点也忽略。
void AStarExpansion::add(unsigned char* costs, float* potential, float prev_potential, int next_i, int end_x,int end_y)
 {
    if (potential[next_i] < POT_HIGH)//it means the potential cell has been explored
        return;

    if(costs[next_i]>=lethal_cost_ &&
     !(unknown_ && costs[next_i]==costmap_2d::NO_INFORMATION))//it means this cell is obstacle
        return;
    // compute the next_i cell in potential
    // costs[next_i] + neutral_cost_:original cost + extra cost
    //AStarExpansion::calculatePotentials()计算每一个点的potential时,用的是p_calc_实例!!
    potential[next_i] = p_calc_->calculatePotential(potential, costs[next_i] + neutral_cost_, next_i, prev_potential);

    int x = next_i % nx_, y = next_i / nx_;
    float distance = abs(end_x - x) + abs(end_y - y);

    queue_.push_back(Index(next_i, potential[next_i] + distance * neutral_cost_));
    //potential[next_i]:    是起点到当前点的cost即g(n)
    //distance * neutral_cost_:   是当前点到目的点的cost即h(n)。
    //f(n)=g(n)+h(n):  计算完这两个cost后,加起来即为f(n),将其存入队列中。

    std::push_heap(queue_.begin(), queue_.end(), greater1());//sort about the previous insert element
    //返回,继续循环
}

A* 算法是策略寻路,不保证一定是最短路径。 Dijkstra 算法是全局遍历,确保运算结果一定是最短路径。 Dijkstra 需要载入全部数据,遍历搜索。 ROS的DijkstraExpansion实现,代码明显不如A*的实现优雅,还使用了宏定义函数。

3.2  举例——grid_path算法:

bool GridPath::getPath(float* potential, double start_x, double start_y, double end_x, double end_y, std::vector<std::pair<float, float> >& path) {
    std::pair<float, float> current;
    current.first = end_x;
    current.second = end_y;

    //1.将goal(目的地)所在的点的(x,y)作为当前点加入path
    int start_index = getIndex(start_x, start_y);
    path.push_back(current);

    int c = 0;
    int ns = xs_ * ys_;

    //2.进入循环,继续循环的条件为当前点的索引不是起始点
    while (getIndex(current.first, current.second) != start_index) {
        float min_val = 1e10;
        int min_x = 0, min_y = 0;

        //3.搜索当前点的四周的四个临近点,选取这四个临近点的potential的值最小的点
        for (int xd = -1; xd <= 1; xd++) {
            for (int yd = -1; yd <= 1; yd++) {
                if (xd == 0 && yd == 0)
                    continue;
                int x = current.first + xd, y = current.second + yd;
                int index = getIndex(x, y);
                if (potential[index] < min_val) {
                    min_val = potential[index];
                    min_x = x;
                    min_y = y;
                }
            }
        }


        if (min_x == 0 && min_y == 0)
            return false;

        //4.将potential值最小的点更改为当前点,并加入path
        current.first = min_x;
        current.second = min_y;
        path.push_back(current);

        if(c++>ns*4){
            return false;
        }

    }//返回2,继续循环

    return true;
}

这个模块负责使用计算好的potential值生成一条全局规划路径。算法很好理解,首先将goal所在的点的(x,y)塞到path,然后搜索当前的点的四周的四个临近点,选取这四个临近点的potential的值最小的点min,然后把这点塞到path,然后再将当前点更新为min这点,由于start 点的potential的值是0,所以这是个梯度下降的方法。

四、全局路径规划器global_planner的参数配置与分析

4.1 简介

nav_core中提供了对应的全局路径规划接口。要想使用机器人move_base提供的便利,我们需要按照接口来实现全局路径规划算法。

global_planner是ros提供的一个全局规划器,是原本的全局规划器navfn的替代品。继承nav_core::BaseGlobalPlanner的接口。

4.2 参数说明

/allow_unknown(bool, default:true)
是否选择探索未知区域。如果和costmap配合使用的时候,其对应参数track_unknown_space必须同样设置为true

/default_tolerance(double, default: 0.0)
靠近目标点的周围多少数值就算到了目标点

/visualize_potential(bool, default: false)
可能区域是否可视化

/use_dijkstra(bool, default: true)
如果设置为false就用A*

/use_quadratic(bool, default:true)
是否使用二阶近似

/use_grid_path(bool, default: false)
输出路径是否遵循网格边界,否则就使用梯度下降法

/old_navfn_behavior(bool, default: false)
如果你想要让global_planner跟之前的navfn版本效果一样,就设true

/lethal_cost(int, default: 253)
障碍物致命区域的代价数值(dynamic reconfigure, 可以动态参数配置)

/neutral_cost (int, default: 50)
中立区域的cost值(动态配置)

/cost_factor(double, default: 3.)
cost因子,用于将每层costmap对应的cost数值乘起来(动态配置)

/publish_potential (bool, default: True)
发布可能的代价地图(动态配置)

/orientation_mode (int, default: 0)
设置每个点的朝向。 (None=0, Forward=1, Interpolate=2, ForwardThenInterpolate=3, Backward=4, Leftward=5, Rightward=6)(动态配置)

/orientation_window_size(int, default 1)
根据方向模式(参数12)指定的位置导数,确定使用哪个窗口来确定方向(动态配置)
 

注意: 所有最后标明(动态配置)的参数,都是使用功能包dynamic_reconfigure实现的参数配置。详情可以查看ROS进阶(二): dynamic_reconfigure功能包详解_little_miya的博客-CSDN博客_ddynamic_reconfigure

我认为出现这种情况是因为,跟机器人设定的方向orientation_mode有关。

总体来说这个global_planner不好用。全局路径规划还是建议使用默认的navfn插件。

参考文献

移动机器人导航技术笔记(1)-global_planner学习 - 知乎

ROS导航系列(四):全局路径规划器的参数配置分析_little_miya的博客-CSDN博客_ros 全局规划

  • 1
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
# Global Planner Parameters # maximum distance to the goal point goal_distance_tolerance: 0.1 # maximum allowed numerical error for goal position xy_goal_tolerance: 0.2 # maximum allowed numerical error for goal orientation yaw_goal_tolerance: 0.3 # weight for the heuristic function used in the A* algorithm # higher values prefer straighter paths, lower values prefer paths with less turning heuristic_weight: 3.0 # minimum distance to travel before attempting to replan min_replan_distance: 1.0 # minimum amount of time to wait before attempting to replan min_replan_time: 1.0 # tolerance on the robot's heading (in radians) when planning # during rotation commands this is an additional error that gets added to # yaw_goal_tolerance heading_lookahead: 0.325 # minimum lookahead to do during path planning. A shorter lookahead is more # cautious (especially in tight spaces) but may be more effective at avoiding # collisions with complex obstacles min_lookahead_distance: 0.4 # maximum lookahead to do during path planning max_lookahead_distance: 2.0 # if true, the global planner will only plan one step at a time # rather than to the final goal state intermediate_planning: false # what topic the planner should use for status feedback planner_frequency: 0.5 planner_topic: "planner_status" # how close the robot must be to the global plan before updating it with # a new one plan_update_distance: 0.5 # how often the planner should be allowed to make new plans. A value of 0 # means plans will be made as often as possible planner_patience: 5.0 # penalty for robot rotation during path planning. A higher penalty will # cause the planner to prefer straighter paths with less turns rotation_penalty: 0.8 # maximum absolute rotation speed allowed while navigating along the global # plan max_rotation_speed: 1.0 # maximum speed to travel along the global plan max_velocity: 0.6 # If true, the global planner will try to avoid obstacles with a combination # of steering and braking. Otherwise, it will only steer around obstacles braking_enabled: true # how many times to retry a goal update if the previous attempt resulted in a # collision or other error. # If set to -1, it will retry indefinitely goal_update_retries: 3 # Whether or not to use the extrinsic rotation control method in the planner use_extrinsic_rotation: true # Enabling this parameter causes the global planner to use # differential constraints for smoother trajectories use_differential_constraints: true # Enabling this parameter causes the planner to assume the # robot is driving on the right-hand side of the street drive_on_right: true # Timeout for the planning process (in seconds). If planning takes longer # than this, the planner will abort and return a failure status planning_timeout: 5.0 # If set, this parameter limits the maximum planning distance the # planner will use. Set to -1 for no limit. max_planning_distance: -1 # Enabling this parameter causes the planner to ignore the robot's ground # clearance when planning. ignore_ground_clearance: false # Whether the planner should try to avoid going backwards avoid_going_backwards: false # The maximum distance (in meters) that the planner will consider changing # the orientation of the robot to better follow the path. Set to -1 to # disable this behavior. max_orientation_change: 0.9 # The minimum distance (in meters) that the planner will consider # detecting a change in orientation of the robot to better follow the path. # Set to -1 to disable this behavior. min_orientation_change: 0.5 # Whether the planner should attempt to use the current local plan when planning. # If set to true, the planner will attempt to connect the current local plan # to the new plan. If set to false, the planner will always start from the robot's # current pose. use_local_plan: true # Whether the planner should attempt to use the current local costmap when planning. # If set to true, the planner will use the local costmap to build an estimate # of the robot's surroundings. If set to false, the planner will only use the # global costmap. use_local_costmap: true # Whether the planner should use the old behavior of setting waypoints to # the right of the global plan. This behavior causes the robot to execute # the plan with a rightward shift. However, it can be problematic if the plan # encounters obstacles on the left side. use_typical_rightward_shift: false # Whether the planner should use a zero velocity as a way to avoid oscillations. # If set to true, the planner will stop the robot and wait for the current goal # to either become unreachable or within the goal tolerance. stop_when_goal_rejected: false # The time (in seconds) that the planner will stop and wait (in case of oscillations) # before trying to replan. stop_and_wait_time: 2.0 # Distance (in meters) to be left before the end of the path. This can be useful # when the robot should stop at a certain distance from the goal pose. path_distance_offset: 0 # Maximum allowed speed deviation from the global plan (in m/s). max_allowed_speed_deviation: 1.0 # Maximum allowed angular deviation from the global plan (in rad). max_allowed_angular_deviation: 1.57 # Whether or not to use a linear navigation function to bias global plan costs toward closer parts of the map. use_linear_navigation_function: false # Whether or not to use a terrain independent cost scale to bias global plan costs toward flatter regions. use_terrain_independent_cost_scale: true # The maximum number of obstacles to check against during planning. max_obstacle_check_count: 500 # If true, the planner will skip planning during the first update cycle after initialization. skip_initial_planning: false # Scaling factor for the distances used in the Adaptive Sampling Path algorithm as_scaler: 1.0 # The maximum length of the Adaptive Sampling Path segments as_max_segment_length: 1.0 # The turning radius for the robot used in the prediction step of the Adaptive Sampling Path algorithm as_robot_radius: 0.3 # The number of areas forward used for heading smoothing in the Adaptive Sampling Path algorithm. # Set to 0 if heading smoothing is not desired. as_heading_smoothing_areas: 0 # The maximum distance the Adaptive Sampling Path algorithm will plan for. # Set to -1 for no limit. as_max_global_plan_distance: -1 # How many layers of costmaps to plan in. A higher value will allow the global # planner to take into account more layers of static and dynamic obstacles. # 0 means only use the base global costmap. planning_layers: 0

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值