计算速度cmd_vel

  • 夹角。若没特别指明,文中夹角指的是机器人偏航角和路径之间角度。路径角度是以路径的起点和终点生成一条直线,该直线在坐标系的角度。
  • 对笔直,可归纳为两种处理。一是要去方向没有障碍物,这情况称不拐弯,这时给个较大linear_x,angular_z则是有个弥补夹角速度。二是要去方向有障碍物,这情况称拐弯,因为有障碍物,想着先拐出个“较大”弯,使机器人平行窄道。拐弯angular_z同样要弥补夹角。对linear_x,则使用一个只等于0.01(ROS_RID_PRESSURE_LINEAR_X)的值。
  • 对可能须要调头,可归纳为三种处理:是用同一个方向的持续拐弯(UTurn),还是后退,还是根据障物障情况、走一步是一步。
  • 两次theta判断。adjust_traj_backward后退时,可认为线速度是个固定值,角速度可能是两种。一是转出的角度能减少夹角,二是0,即径直后退。把依次判断这两种速度的操作称为两次theta判断。
  • adjust_traj_backward后退时,线速度固定是-0.12米/秒。有种情况会例外,发现前面顶着障碍物时,此时如果不能用-0.12,还要判断-0.1、-0.08、-0.06,这么做的目的是先摆脱前面障碍物。

 

窄道判断后,会得到此刻正处于哪种路况,笔直、可能须要调头、还是其它。

路况判断变量备注
笔直straight_ward_=true, maybe_uturn_=falseuse_negative_vel=false表示笔直向前,否则笔直向后
可能须要调头straight_ward_=false, maybe_uturn_=true 
其它straight_ward_=false, maybe_uturn_=false 

straight_ward_和maybe_uturn_不可能同时true。

接下要根据哪种路况,计算此次要发送到底盘的速度cmd_vale。这过程,可归纳为四次计算。分别是第一次findBestPath、笔直调整、调头调整和adjust_traj_backward。

过程中可能会有两次findBestPath,第一次是有第一步。第二次是在调头调整,如果那里没通过半圈检查、而且背后没有障碍物,会触发。

 

一、第一次findBestPath

findBestPath会枚举所有可能速度,然后给出个最好速度。

  base_local_planner::Trajectory DWAPlanner::findBestPath(
      const geometry_msgs::PoseStamped& global_pose,
      const geometry_msgs::PoseStamped& global_vel,
      geometry_msgs::Twist& cmd_vel, 
      bool use_negative_vel, bool straight_ward, bool path_all_back) {
    ...
    if (use_negative_vel) {
        limits.min_vel_x = -ros::min_moveable_vel_x;  // -0.08
        limits.max_vel_x = -0.02;
        if (straight_ward) {
            limits.min_vel_x = -0.12;
            limits.max_vel_theta = ros::min_moveable_vel_theta;
        } else {
            limits.max_vel_theta = ros::min_moveable_vel_theta;

窄道判断后,如果use_negative_vel=true,那一定是straight_ward=true,所以第一次findBestPath不会进这入口。要能进这入口,是发生在“调头调整”中的findBestPath。

        }

use_negative_vel=true,顾名思义,此时只能使用<0的负linear_x。

    } else {
        if (maybe_uturn) {
            vsamples[0] = 1;
            limits.min_vel_x = 0.00; // 0.02
            limits.max_vel_x = 0.00; // 0.02
            limits.min_vel_trans = 0.03; // 0.52333

            limits.min_vel_theta = DEG2RAD(30); // DEG2RAD(30)[0.52333]  DEG2RAD(35)[0.6109]
            // limits.max_vel_theta = DEG2RAD(35); // 0.6109

调头调整可能会有两次findBestPath,这是第一次。

        } else {
            // must use Positive velocity
            limits.min_vel_x = 0.02; // 
            if (straight_ward) {
                limits.max_vel_theta = ros::min_moveable_vel_theta;
            }
        }
    }
    ...
}

use_negative_vel=true时,会用一个负速度,并且都只有一个限制在[-min_moveable_vel_theta, min_moveable_vel_theta]的小拐弯。

 

二、笔直调整(straight_ward_=true)

要进入笔直调整,是有条件的,条件是此次路况是笔直。

笔直走,第一次findBestPath只是判断有没有路能通,只要判断出有路能通,就要新算出一个速度,覆盖掉findBestPath算出的速度。

那自已的速度是什么呢?分两种情况。

  1. 前面或后面没有障碍物,把这情况称不拐弯。不拐弯时,angular_z都有个弥补夹角速度。对linear_x,前进是“ros::min_moveable_vel_x + 0.06”,后退是“ ros::min_moveable_vel_x + 0.04”。
  2. 前面或后面有障碍物,把这情况称拐弯。因为有障碍物,想着先拐出个“较大”弯,使机器人平行窄道。拐弯angular_z同样要弥补夹角。对linear_x,则使用一个只等于0.01(ROS_RID_PRESSURE_LINEAR_X)的值。

 

三、掉头调整(maybe_uturn_=true)

要进入掉头调整,是有条件的,条件是此次路况是可能须要掉头。

此时所有路径点夹角都超过60度,认为目标点在机器人背后,这时机器人要做决定,怎么调头。是用同一个方向的持续拐弯(UTurn)、还是后退,还是根据障物障情况,走一步是一步?

 

3.1 同一个方向的持续拐弯(UTurn)

进行半圈检测,即模拟转半圈。模拟不是180度都试一遍,只是查45、60、75、90、105、130、145、160,看机器人是不可能转到这此个角度。如果都可能,通过半圈检测,那此次要第一次findBestPath得到的速度。这备战以着个正速度的转法,称为UTurn。

如果半圈检测失败,认为再以findBestPath得到的速度转的话,迟早会碰到障碍物。那得用自算速度了,这速度是啥,要根据背后是否有障碍物,分两种情况。

 

3.2 后退

背后没有障碍物。执行策略:后退。至于选择何样后退速度,由第二次findBestPath决定。在调用findBestPath前,会把use_negative_vel_置为true,maybe_uturn_置为false。这么做的原因是,既然现在这点上不能UTurn,估计是一侧或两侧有障碍,不如做点后退,可能会退到个空点地方,那时再UTurn。

 

3.3 根据障物障情况,走一步是一步

背后有障碍物。此时,原地UTurn,迟早会碰到障碍物。背后有障碍,又不能后退,怎么办?——用一个只有0.01(ROS_RID_PRESSURE_LINEAR_X)线速度,向左转或向右转。这种思路,只能说是转一次,可能会有新出路。那是向左还是向右?按以下优先级给速度。

  1. 前方,左侧没障碍、右侧有。——向左转,转30度。
  2. 前方,左侧有障碍、右侧没有。——向右转,转30度。
  3. 之前UTurn过,继续之前UTurn方向转30度,没问题。——继续之前UTurn方向转30度。
  4. 如果第一次findBestPath成功,用findBestPath算出的theta。
  5. 连第一次findBestPath都失败。——主观给一个给弥补夹的30度。

 

四、adjust_traj_backward

三种路况都会调用adjust_traj_backward,但此时或负速度(use_negative_vel_),或笔直(straight_ward_),或maybe_uturn_,它们只是把next_traj_backword_置为false。也就是说,对上面二、三做出的调整,adjust_traj_backward不会再做修改。

 

4.1 为什么要adjust_traj_backward

原因1:前向移动,只能是一个小速度时

这种情况类比倒车。因为速度很小,认为再向前走的话,可能已走不通了,不如后退,同时转个小角度,这角度会让减少夹角。

有个问题,如何判断小速度?——没用速度值,而是用这速度能移动出的距离。如果移动出的距离小于0.09米(dist_threshold),认为这个速度就是小速度。

原因2:前面顶到障碍物了

既然前面碰到障碍物,机器人自然得后退。代码用front_pressure=true表示这种情况。

原因3:须要二次后退

二次后退指的是经过一次后退,下一次继续后退。让看两种场景。一是前面顶着障碍物时,已经成功向后移动了一次,但只移动一次还是有点危险,须要有二次后退。二是出了小速度,而且夹角有点大,在[70, 110]之间,认为有二次后退能更快减少夹角。

next_traj_backword_=true表示此个adjust_traj_backward是处在二次后退中。

在二次后退时,两次theta判断都没法得到一个有效速度后,它不是使用之前findBestPath得到的小速度,而是用一个linear.x为0、theta能减少夹角的速度。这么做的原因是为避免前后拉扯。设想下此时机器人前面正顶着障碍物。

  1. 用adjust_traj_backward执行一次后退,同时让next_traj_backword_=true。
  2. 因为next_traj_backword_=true,进入二次后退时的adjust_traj_backward。但两次theta判断失败。如果就用上小速度的话,这个小速度极可能操作机器人向前移动。
  3. 步骤1的向后、步骤2的向前,导致机器人出现了前后拉扯。
  4. 为避免前后拉扯,在步骤2时,虽然两次theta判断失败,但还是使用一个只有角速度的速度。因为有步骤1的后退,此时应该已脱离和障碍物接触,机器人再经过这个速度拐弯后,可能再向前就不会碰到障碍物了。

二次后退时,不是继续后退,就是原地转一个能减少夹角的角度。

 

4.2 后退速度

adjust_traj_backward后退时,可认为线速度是个固定值,像-0.12,角速度可能是两种。一是转出的角度能弥合夹角,二是0,即径直后退。在这两次theta判断中,得出第一个可用速度就是要用于操作机器人后退的速度。

线速度固定选-0.12米/秒。有种情况会例外,发现前面顶着障碍物时,除-0.12外,还要再判断-0.1、-0.08、-0.06,这么做的目的是先摆脱前面障碍物。

如果出现两次theta判断都没法得到一个有效速度,则使用之前findBestPath得到的小速度。当然,二次后退时除外。

全部评论: 0

    写评论: