ROS(11)move_base详解

2023-05-16

11. move_base详解

11.1. move_base配置参数解读

参考链接:https://blog.csdn.net/banzhuan133/article/details/90239252
https://wenku.baidu.com/view/1ae6d9a56729647d27284b73f242336c1fb9304d.html
https://blog.csdn.net/qq_29313679/article/details/106237063
在仿真中,查看turtlebot3_navigation/launch/move_base.launch,发现局部规划器用的是DWAPlannerROS,同时加载了下面几个yaml文件:

costmap_common_params_$(arg model).yaml  
local_costmap_params.yaml  
global_costmap_params.yaml  
move_base_params.yaml  
dwa_local_planner_params_$(arg model).yaml  

这里的(arg model)用的burger模型。
在rviz下,直接用鼠标选定2D navigation goal就可以指定目标了,但是,你可能会发现效果不太好,比如,疯狂原地打转,走S型,绕大圈等现象。这些都可以通过调参搞定。
重点看后两个move_base_params.yaml、dwa_local_planner_params_$(arg model).yaml文件,地图相关参数放到Costmap2DROS分析章节中。
move_base_params.yaml:

shutdown_costmaps: false   #当move_base不在活动状态时,是否关掉costmap的加载。  
controller_frequency: 10.0 #局部规划器执行频率,也是发送cmd_vel命令的频率。     
planner_patience: 5.0  #全局规划器未规划出路线超过本时间,进行清理操作。        
controller_patience: 15.0  #局部规划器未规划出路线超过本时间,进行清理操作。   
conservative_reset_dist: 3.0 #在恢复模块执行后,重置的代价地图范围  
planner_frequency: 5.0   #全局规划操作频率,如果为0,则仅在接收到新的目标点或局部路径堵塞时才重新规划一次路径。       
oscillation_timeout: 10.0  #执行修复机制前,允许的震荡时长(秒)     
oscillation_distance: 0.2  #来回运动在多大距离以上不会认为是震荡  
recovery_behavior_enabled: true  #是否使用恢复模块     
clearing_rotation_allowed: true  #在清除操作时,是否原地旋转

dwa_local_planner_params.yaml

DWAPlannerROS:  
 # Robot Configuration Parameters (机器人配置参数)                                 
   max_vel_x: 0.22  #最大x轴方向线速度  
   min_vel_x: -0.22 #最小x轴方向线速度  

   max_vel_y: 0.0  
   min_vel_y: 0.0  

  # The velocity when robot is moving in a straight line (机器人直线运行时的速度)  
    max_vel_trans:  0.22  #最大线速度  
    min_vel_trans:  0.11  
 
    max_vel_theta: 2.75  #最大角速度  
    min_vel_theta: 1.37  
 
    acc_lim_x: 2.5  #x轴方向最高加速度  
    acc_lim_y: 0.0  
    acc_lim_theta: 3.2  
 
  # Goal Tolerance Parametes (目标误差参数)  
    xy_goal_tolerance: 0.05  #路径规划到达点与目标点的距离允许偏差  
    yaw_goal_tolerance: 0.17 #路径规划到达点与目标点的角度允许偏差  
    latch_xy_goal_tolerance: true  
    trans_stopped_vel: 0 #当机器人线速度低于这个时候,就认为是停止的
 
  # Forward Simulation Parameters(前向仿真参数)  
    sim_time: 1.5  #仿真时间,仿真距离=sim_time*vel  
    vx_samples: 20 #x轴方向速度采样数量,至少是1,否则会被强制设定为1  
    vy_samples: 0  
    vth_samples: 40  
    controller_frequency: 10.0  #发布控制速度的频率    
 
  # Trajectory Scoring Parameters(轨迹评分参数),系数影响的是本代价算法在最终代价中的一个比例    
    path_distance_bias: 32.0  #局部规划路径与全局路径保持一致的权重系数, path_costs和alignment_costs使用 
    goal_distance_bias: 20.0 #无论从什么路径以多大权重尝试到达目标点,增大后于全局规划路径一致性降低,goal_costs_和goal_front_costs_使用  
    occdist_scale: 0.02  #权衡机器人以多大的权重躲避障碍物。该值过大会导致机器人陷入困境,obstacle_costs_使用  
    forward_point_distance: 0.325  #将机器人与目标点连线并延长forward_point_distance距离作为一个评分点  
    stop_time_buffer: 0.2  #为防止碰撞,机器人必须提前停止的时间长度  
    scaling_speed: 0.25  #开始缩放机器人足迹时的速度的绝对值,单位为m/s  
    max_scaling_factor: 0.2  #最大缩放因子  
 
  # Oscillation Prevention Parameters(避免振荡参数)  
    oscillation_reset_dist: 0.05  #机器人运动多远距离才会重置振荡标记  
 
  # Debugging  
    publish_traj_pc : true  
    publish_cost_grid_pc: true  #是否发布计算后的cost话题  

11.2. 启动流程

move_base节点源文件位于/navigation-melodic-devel/move_base/move_base_node.cpp,其调用了move_base.cpp中的MoveBase的构造。主要的初始化过程也在这个构造中。main函数只有下面几句话:

  tf2_ros::Buffer buffer(ros::Duration(10));// 10s的缓冲数据
  tf2_ros::TransformListener tf(buffer); //内部监听"/tf"和"/tf_static"坐标
  move_base::MoveBase move_base( buffer );

由节点关系图可以看到,这里监听的"/tf"来自定位模块,可以是amcl或其他定位模块,传输的是各个坐标系间的转换关系。
构造流程下:

  • 构建MoveBaseActionServer,基于ROS的actionlib机制启动了一个action服务,主要作用是接收客户端发送的目标点,在回调中处理目标点并驱动AGV行走,回调函数是executeCb
  • 各个参数的初始化,在上面的仿真中,很多默认参数已经被配置文件修改了,如上面的仿真中局部规划器被改为了DWA;
  • 创建全局规划器线程;
  • 创建全局地图和局部地图;
  • 加载全局规划器、局部规划器的插件;
  • 初始化状态机状态等等。

11.3. executeCb回调

该回调函数在收到目标点时会触发调用,收到新的目标点的话会通过ROS的actionlib机制进行处理,可以调用一些接口来判断,actionlib我们不关心,大概的流程如下:

  • 通过一个信号量planner_cond_激发了全局规划器线程进行了规划,
  • 定义变量ros::Rate r(controller_frequency_)来控制下面while循环的频率,这个频率比较关键,最终体现在发送cmd_vel指令的频率上,我们称之为“控制频率”,程序中好多地方用到;
  • 中间过程不关心,调用了executeCycle()接口,来控制AGV行走,该接口会返回AGV是否到达目标点。

11.4. executeCycle接口

本函数的核心在状态CONTROLLING处理逻辑中:

  • 通过调用LatchedStopRotateController类的isGoalReached()接口判断是否到达目标点,这个类参考后面的<目标点达到控制>章节;
  • 通过调用dwa_planner_ros.cppDWAPlannerROS类的computeVelocityCommands()接口来计算下发给AGV底盘的指令。这里AGV清除恢复CLEARING及流程我们不关心。

11.5. DWAPlannerROS::computeVelocityCommands

DWA参考链接: http://gaoyichao.com/Xiaotu/?book=turtlebot&title=dwa_local_planner
本接口会进行一个是否到达目标点的判断(通过LatchedStopRotateController):

  • 最开始部分会调用planner_util_.getLocalPlan()接口,将原/map坐标系下的全局路径转换到/odom坐标系下;
  • 调用LatchedStopRotateController::isPositionReached只判断XY是否到达,如果到达那么会调用latchedStopRotateController_.computeVelocityCommandsStopRotate()来判断角度是否到达,角度没到达进行旋转控制,否则发送停止;如果没到达xy,那么会调用DWAPlannerROS::dwaComputeVelocityCommands()来把最佳轨迹对应的速度作为下发底盘的速度cmd_vel。xy到达后的旋转参考后面的<目标点到达控制>章节;
  • 未到达目标点,调用DWAPlanner类的findBestPath()接口,它又调用了SimpleScoredSamplingPlanner接口中的findBestTrajectory(),后者会通过SimpleTrajectoryGenerator类创建出轨迹,并调用代价算法来计算轨迹得分。
    DWAPlanner类中存储了7种代价计算方法,分别是:
OscillationCostFunction oscillation_costs_  // 减少晃动  
ObstacleCostFunction obstacle_costs_        // 减少机器人撞上障碍物
MapGridCostFunction goal_front_costs_       // prefers trajectories that make the nose go towards (local) nose goal
MapGridCostFunction alignment_costs_        // prefers trajectories that keep the robot nose on nose path
MapGridCostFunction path_costs_             // 通过波传播的一种代价算法,更倾向于贴近全局轨迹
MapGridCostFunction goal_costs_             // 通过波传播的一种代价算法,更倾向于全局路径和局部地图的交点
TwirlingCostFunction twirling_costs_        // 减少原地打转     

通过设定的比例系数,来对各个代价进行加权得出最后的代价数值。当计算出最优轨迹后,将轨迹对应的速度下发到底盘。

11.5.1. SimpleTrajectoryGenerator轨迹创建

该类中主要的接口有两个:initialisegenerateTrajectory

  • initialise接口首先根据<x,y,th>三个加速度,根据当前速度和“控制频率”时间,计算一个时间片后的最大和最小速度;然后根据设定的采样数量对三个速度方向进行<min_vec,max_vec>范围采样,得到一堆速度(turtlebot3仿真中的参数得到了800个速度);
  • generateTrajectory接口,一个速度计算一段轨迹,轨迹中点的个数计算公式:
线速度仿真距离 = 线速度 * 采样时间;  
角速度速度仿真距离 = 角速度速度 * 采样时间;  
线速度方向个数 = 线速度仿真距离 / 线速度仿真间隔;  
角速度方向个数 = 角速度仿真距离 / 角速度仿真间隔;
总数量 = max(线速度方向个数,角速度方向个数)

11.6. MapGridCostFunction代价计算

有四种代价都是通过本类实现的,这里只关注了两个主要的:贴近全局轨迹和贴近全局轨迹与局部地图的交点。
这个类主要的接口有两个:prepare()scoreTrajectory()

  • prepare():其中调用的逻辑是由MapGrid类实现的,需要提前调用,生成代价数据表来加速代价查询。该函数有两个作用:
    一个是提前算好局部网格地图(注意是网格地图)中每个网格点距离全局路径在局部地图中的单位长度,如图,其中0是全局路径占用的网格,其他网格数据通过一个扩散的算法实现的(不是欧式距离),这里1 2 3代表离0的一个相对距离:
3 2 1 0 1 2 3 
3 2 1 0 1 2 3
2 1 0 1 1 2 3
1 0 1 2 3 4 5
1 0 1 2 4 4 5

另一个是计算每个网格到全局路径和局部地图交点的单位长度,也是通过同样的扩散算法实现的,这里0是目标点:

- 2 1 0 1 2 -
- 3 2 1 2 3 -
- 4 3 2 3 4 -
  • scoreTrajectory():这个函数很简单,就是直接查询代价表,来通过三种策略计算轨迹的代价值:
Last:默认是这个,只保留最后一个轨迹点距离全局轨迹的相对距离,来作为最终的代价;
Sum:所有点相对距离的累加;
Product:所有点相对距离的累乘。

11.7. OscillationCostFunction代价计算

本代价是为了减少车身的晃动。逻辑非常简单,总体来说就是AGV往前行驶一段距离的过程中,每次创建轨迹并进行打分时,都会考虑这些轨迹的速度和初始速度的正负关系,保证<x,y,th>都和初始速度方向一致。行驶一段距离后会重置初始的速度方向,重新开始统计。
关键的接口有:

  • updateOscillationFlags() : 每次计算出最优轨迹时调用,如果超出了设定的距离,会重置检测标记;
  • scoreTrajectory() : 对某个轨迹进行打分,就是看看轨迹的<x, y, th>速度方向是否和初始设置的一致。

11.8. 目标点到达控制(LatchedStopRotateController)

  • isPositionReached(): 只判断XY是否到达,不判断角度是否到达。
  • isGoalReached(): 判断xy和朝向角都在误差范围、且会通过里程计信息判断<x,y,th>速度是满足到达误差。此函数会在CONTROLLING状态下每次控制频率到后都会调用,以此来切换控制状态。其中有个标志latch_xy_goal_tolerance_可以对xy判断进行锁存,意思是说如果如果该标记为true且曾经满足当前位置和目标位置的xy在误差范围内,那么后续再调用本接口时,不再判断xy是否满足误差范围,只判断角度和速度是否满足误差范围,这样到达目标点(xy到达)后调整角度过程中,如果xy偏离了也不关心。核心代码如下:
//这个if条件中的||是关键,当前两者为true时,后面那个xy距离判断将不再起作用。
if ((latch_xy_goal_tolerance_ && xy_tolerance_latch_) ||
      base_local_planner::getGoalPositionDistance(global_pose, goal_x, goal_y) <= xy_goal_tolerance) {
    if (latch_xy_goal_tolerance_ && ! xy_tolerance_latch_) {
      xy_tolerance_latch_ = true; //这里是上面||后面条件起作用进入的
    }
    if (fabs(angle) <= limits.yaw_goal_tolerance) { //角度满足误差
      if (base_local_planner::stopped(base_odom, theta_stopped_vel, trans_stopped_vel)) {//速度满足误差
        return true;
      }
    }
return false; //如果旋转过程中不锁存xy,一旦xy超出误差那么上面角度误差判定就进入了,直接返回false!
  • computeVelocityCommandsStopRotate() : 该函数的进入条件为xy已经到了,然后判断角度是否到了,如果到了那么直接发送0速度来强行停止(如果第一次到达xy并且角度也满足,这样做太粗暴了;如果角度不满足,这里就是旋转过程中控制停止的条件,是可以的)。如果没到那么会检查是否速度<x,y,th>已经满足停止条件:
    • 满足:此时可以认为机器人已经停下了,则进行旋转操作rotateToGoal(),这里会根据最大最小限速及和目标角度的夹角计算角速度,这里注意当离目标角度越近的时候,速度计算会直接采用这个距离,也就是旋转过程离目标点越近旋转速度越慢,并下发下去,进行下次循环,继续在computeVelocityCommandsStopRotate中判断是否角度到了发送0速度;
    • 不满足:则进行减速操作,通过加速度计算下个仿真周期减速后的<x,y,th>方向的速度,这里会调用轨迹检查接口,不用关心该调用。发送的速度计算:v-at,如果为负的,那么就是0。

这个目标点到达控制如果在到达目标点且角度也一样时,会强行停止,比如在行驶速度特别大的时候,可能会出现急停滑行的问题等等,实际应用的话还需要改进。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

ROS(11)move_base详解 的相关文章

随机推荐

  • Linux Shell 实现一键部署Redis6

    redis 前言 Redis xff08 Remote Dictionary Server xff0c 即远程字典服务 xff0c 是一个开源的使用ANSI C语言编写 支持网络 可基于内存亦可持久化的日志型 Key Value数据库 xf
  • Linux Shell 实现一键部署Rabbitmq

    rabbitmq 前言 RabbitMQ是实现了高级消息队列协议 xff08 AMQP xff09 的开源消息代理软件 xff08 亦称面向消息的中间件 xff09 RabbitMQ服务器是用Erlang语言编写的 xff0c 而集群和故障
  • [linux]mount与nfs挂载简介

    文章目录 挂载mount目录间挂载卸载与fuserfstabNFS Server配置命令 NFS client mount用于挂载设备 xff1a 挂载分区 xff1a mount dev sdb1 data xff1b 文件夹间 xff1
  • Linux Shell 实现一键部署Nginx

    nginx前言 nginx engine x 是 HTTP 和反向代理服务器 邮件代理服务器和通用 TCP UDP 代理服务器 xff0c 最初由Igor Sysoev编写 很长一段时间以来 xff0c 它一直在许多负载重的俄罗斯网站上运行
  • Linux Shell 实现一键部署二进制Rabbitmq

    rabbitmq 前言 RabbitMQ是实现了高级消息队列协议 xff08 AMQP xff09 的开源消息代理软件 xff08 亦称面向消息的中间件 xff09 RabbitMQ服务器是用Erlang语言编写的 xff0c 而集群和故障
  • Linux Shell 实现一键部署二进制docker+docker_compose

    docker 前言 Docker 是一个开源的应用容器引擎 xff0c 让开发者可以打包他们的应用以及依赖包到一个可移植的镜像中 xff0c 然后发布到任何流行的 Linux或Windows 机器上 xff0c 也可以实现虚拟化 容器是完全
  • PowerShell install Docker+docker-compoer

    docker 前言 Docker 是一个开源的应用容器引擎 xff0c 让开发者可以打包他们的应用以及依赖包到一个可移植的镜像中 xff0c 然后发布到任何流行的 Linux或Windows 机器上 xff0c 也可以实现虚拟化 容器是完全
  • PoweShell Win_server install wsl

    什么是 WSL 2 WSL 2 是适用于 Linux 的 Windows 子系统体系结构的一个新版本 xff0c 它支持适用于 Linux 的 Windows 子系统在 Windows 上运行 ELF64 Linux 二进制文件 它的主要目
  • PoweShell Win_desktop install wsl

    什么是 WSL 2 WSL 2 是适用于 Linux 的 Windows 子系统体系结构的一个新版本 xff0c 它支持适用于 Linux 的 Windows 子系统在 Windows 上运行 ELF64 Linux 二进制文件 它的主要目
  • Linux Shell 实现一键部署二进制go+caddy+filebrowser

    filebrowser filebrowser 是一个使用go语言编写的软件 xff0c 功能是可以通过浏览器对服务器上的文件进行管理 可以是修改文件 xff0c 或者是添加删除文件 xff0c 甚至可以分享文件 xff0c 是一个很棒的文
  • PowerShell install go+caddy+filebrowser+nssm 实现部署文件系统

    filebrowser filebrowser 是一个使用go语言编写的软件 xff0c 功能是可以通过浏览器对服务器上的文件进行管理 可以是修改文件 xff0c 或者是添加删除文件 xff0c 甚至可以分享文件 xff0c 是一个很棒的文
  • Linux Shell 实现一键部署http+用户名密码登录

    Apache 前言 Apache 音译为阿帕奇 是世界使用排名第一的Web服务器软件 它可以运行在几乎所有广泛使用的计算机平台上 xff0c 由于其跨平台和安全性被广泛使用 xff0c 是最流行的Web服务器端软件之一 它快速 可靠并且可通
  • PowerShell install 一键部署http+用户名密码登录实现文件系统

    Apache 前言 Apache 音译为阿帕奇 是世界使用排名第一的Web服务器软件 它可以运行在几乎所有广泛使用的计算机平台上 xff0c 由于其跨平台和安全性被广泛使用 xff0c 是最流行的Web服务器端软件之一 它快速 可靠并且可通
  • [python]异常处理与try语句

    文章目录 异常处理try语句异常信息抛出异常 异常类型自定义异常预定义异常 使用 try except else 来捕获异常 xff0c 且要求异常必须继承自Exception类 异常处理 运行期检测到错误称为异常 try语句 python
  • 大杂烩·OSI和TCP/IP协议与ZigBee技术·一

    1 ZigBee技术 ZigBee是基于IEEE802 15 4标准的低功耗局域网协议 根据国际标准规定 xff0c ZigBee技术是一种短距离 低功耗的无线通信技术 这一名称 xff08 又称紫蜂协议 xff09 来源于蜜蜂的八字舞 x
  • Linux Shell 实现一键部署subversion

    subversion SVN是subversion的缩写 xff0c 是一个开放源代码的版本控制系统 xff0c 通过采用分支管理系统的高效管理 xff0c 简而言之就是用于多个人共同开发同一个项目 xff0c 实现共享资源 xff0c 实
  • PowerShell install 一键部署TortoiseSVN

    TortoiseSVN TortoiseSVN是 Subversion 版本控制系统的一个免费开源客户端 xff0c 可以超越时间的管理文件和目录 文件保存在中央版本库 xff0c 除了能记住文件和目录的每次修改以外 xff0c 版本库非常
  • PowerShell install 一键部署subversion

    subversion SVN是subversion的缩写 xff0c 是一个开放源代码的版本控制系统 xff0c 通过采用分支管理系统的高效管理 xff0c 简而言之就是用于多个人共同开发同一个项目 xff0c 实现共享资源 xff0c 实
  • ROS(1)安装

    1 ros安装 安装过程参考https www cnblogs com letisl p 11815191 html安装wsl略 xff0c 利用mobaxterm进行连接与可视化 1 1 添加源 sudo sh c 39 etc lsb
  • ROS(11)move_base详解

    11 move base详解 11 1 move base配置参数解读 参考链接 xff1a https blog csdn net banzhuan133 article details 90239252 https wenku baid