百度Apollo5.0规划模块代码学习(五)开放空间回退决策分析

1 流程图

1.1 开放空间倒车决策流程图

在这里插入图片描述

1.2 无碰撞轨迹判断流程图

在这里插入图片描述

2 代码分析

代码分析如下:

加载配置文件,

OpenSpaceFallbackDecider::OpenSpaceFallbackDecider(const TaskConfig& config)
    : Decider(config) {}

对于二次型公式:ax^2+bx+c=0,返回较小的解。非常正常的解法。

bool OpenSpaceFallbackDecider::QuardraticFormulaLowerSolution(const double a,
                                                              const double b,
                                                              const double c,
                                                              double* sol) {
  // quardratic formula: ax^2 + bx + c = 0, return lower solution
  // TODO(QiL): use const from common::math
  const double kEpsilon = 1e-6;
  *sol = 0.0;
  if (std::abs(a) < kEpsilon) {
    return false;
  }

  double tmp = b * b - 4 * a * c;
  if (tmp < kEpsilon) {
    return false;
  }
  double sol1 = (-b + std::sqrt(tmp)) / (2.0 * a);
  double sol2 = (-b - std::sqrt(tmp)) / (2.0 * a);

  *sol = std::abs(std::min(sol1, sol2));
  ADEBUG << "QuardraticFormulaLowerSolution finished with sol: " << *sol
         << "sol1: " << sol1 << ", sol2: " << sol2 << "a: " << a << "b: " << b
         << "c: " << c;
  return true;
}

对于开放空间自动泊车的具体处理算法,具体代码如下:

Status OpenSpaceFallbackDecider::Process(Frame* frame)

创建预测环境,输入为障碍物信息,输出为预测的环境矩形边界。

  std::vector<std::vector<common::math::Box2d>> predicted_bounding_rectangles;
  size_t first_collision_index = 0;
  size_t fallback_start_index = 0;

  BuildPredictedEnvironment(frame->obstacles(), predicted_bounding_rectangles);

建立预测环境的代码如下:
首先删除二维矩形中的所有元素,相对时间设置为0。
判断开放空间预测时间段是否大于0,如果是,则对于所有障碍物,如果障碍物不是虚拟的,则需要获取障碍物在此时间的轨迹点,边界,并保存边界信息为二维矩形。然后获取下一个障碍物的轨迹点和边界并分别存放。

void OpenSpaceFallbackDecider::BuildPredictedEnvironment(
    const std::vector<const Obstacle*>& obstacles,
    std::vector<std::vector<common::math::Box2d>>&
        predicted_bounding_rectangles) {
  predicted_bounding_rectangles.clear();
  double relative_time = 0.0;
  while (relative_time < config_.open_space_fallback_decider_config()
                             .open_space_prediction_time_period()) {
    std::vector<Box2d> predicted_env;
    for (const Obstacle* obstacle : obstacles) {
      if (!obstacle->IsVirtual()) {
        TrajectoryPoint point = obstacle->GetPointAtTime(relative_time);
        Box2d box = obstacle->GetBoundingBox(point);
        predicted_env.push_back(std::move(box));
      }
    }
    predicted_bounding_rectangles.emplace_back(std::move(predicted_env));
    relative_time += FLAGS_trajectory_time_resolution;
  }
}

判断是否是无碰撞轨迹,代码如下:

if (!IsCollisionFreeTrajectory(
          frame->open_space_info().chosen_paritioned_trajectory(),
          predicted_bounding_rectangles, &fallback_start_index,
          &first_collision_index))

是否是无碰撞轨迹代码:
输入:选择的轨道和档位位置(轨迹档位队),障碍物边界,回退/开始索引,首次碰撞索引
首先获取车辆的配置信息,车辆的长度和宽度,轨迹,轨迹点的个数。
之后查找轨迹点下界点,即轨迹开始点。(具体代码在之后)。

bool OpenSpaceFallbackDecider::IsCollisionFreeTrajectory(
    const TrajGearPair& trajectory_gear_pair,
    const std::vector<std::vector<common::math::Box2d>>&
        predicted_bounding_rectangles,
    size_t* current_index, size_t* first_collision_index) {
  // prediction time resolution: FLAGS_trajectory_time_resolution
  const auto& vehicle_config =
      common::VehicleConfigHelper::Instance()->GetConfig();
  double ego_length = vehicle_config.vehicle_param().length();
  double ego_width = vehicle_config.vehicle_param().width();
  auto trajectory_pb = trajectory_gear_pair.first;
  const size_t point_size = trajectory_pb.NumOfPoints();

  *current_index = trajectory_pb.QueryLowerBoundPoint(0.0);

对于所有轨迹点,做如下操作:
求出轨迹点和在该点的航向角;
获取中心点、航向、长度和宽度的构造函数,中心点为轨迹点,长度和宽度分别为车的长度和宽度,航向为矩形朝向。
移动距离=车长/2-车后边缘到中心距离。
将在x轴,y轴上的移动距离保存为二维向量,并按照该向量移动车的矩形框。

  for (size_t i = *current_index; i < point_size; ++i) {
    const auto& trajectory_point = trajectory_pb.TrajectoryPointAt(i);
    double ego_theta = trajectory_point.path_point().theta();
    Box2d ego_box(
        {trajectory_point.path_point().x(), trajectory_point.path_point().y()},
        ego_theta, ego_length, ego_width);
    double shift_distance =
        ego_length / 2.0 - vehicle_config.vehicle_param().back_edge_to_center();
    Vec2d shift_vec{shift_distance * std::cos(ego_theta),
                    shift_distance * std::sin(ego_theta)};
    ego_box.Shift(shift_vec);

令预测范围为所有障碍物的个数。
对于所有障碍物执行以下操作:
对于障碍物所有矩形,如果车的矩形框和障碍物的矩形框有重叠部分,则输出提示信息,并获取车的坐标,如果轨迹点的相对时间减去点的位置与采样时间的乘积开放空间碰撞缓冲时间,则输出第一次碰撞的指标。

    size_t predicted_time_horizon = predicted_bounding_rectangles.size();
    for (size_t j = 0; j < predicted_time_horizon; j++) {
      for (const auto& obstacle_box : predicted_bounding_rectangles[j]) {
        if (ego_box.HasOverlap(obstacle_box)) {
          ADEBUG << "HasOverlap(obstacle_box) [" << i << "]";
          const auto& vehicle_state = frame_->vehicle_state();
          Vec2d vehicle_vec({vehicle_state.x(), vehicle_state.y()});
          // remove points in previous trajectory
          if (std::abs(trajectory_point.relative_time() -
                       static_cast<double>(j) *
                           FLAGS_trajectory_time_resolution) <
                  config_.open_space_fallback_decider_config()
                      .open_space_fallback_collision_time_buffer() &&
              trajectory_point.relative_time() > 0.0) {
            ADEBUG << "first_collision_index: [" << i << "]";
            *first_collision_index = i;
            return false;
          }
        }
      }
    }
  }

  return true;
}

查询轨迹的开始点。如果相对时间大于时间序列的最后一个时间点(即时间超出),则返回错误。
求出序列中相对时间的下一个时间点的序列迭代器,之后返回该迭代器指向的轨迹点和开始轨迹点之间的点的个数。

size_t DiscretizedTrajectory::QueryLowerBoundPoint(const double relative_time,
                                                   const double epsilon) const {
  CHECK(!empty());

  if (relative_time >= back().relative_time()) {
    return size() - 1;
  }
  auto func = [&epsilon](const TrajectoryPoint& tp,
                         const double relative_time) {
    return tp.relative_time() + epsilon < relative_time;
  };
  auto it_lower = std::lower_bound(begin(), end(), relative_time, func);
  return std::distance(begin(), it_lower);
}

设定回退标志位:真
在安全距离内,根据当前分配轨迹生成回退轨迹,车速降至零
设定未来的碰撞点,回退开始点,回退开始点的车速。

// change flag
    frame_->mutable_open_space_info()->set_fallback_flag(true);

    // generate fallback trajectory base on current partition trajectory
    // vehicle speed is decreased to zero inside safety distance
    TrajGearPair fallback_trajectory_pair_candidate =
        frame->open_space_info().chosen_paritioned_trajectory();
    // auto* ptr_fallback_trajectory_pair =
    // frame_->mutable_open_space_info()->mutable_fallback_trajectory();
    const auto future_collision_point =
        fallback_trajectory_pair_candidate.first[first_collision_index];
        / Fallback starts from current location but with vehicle velocity
    auto fallback_start_point =
        fallback_trajectory_pair_candidate.first[fallback_start_index];
    const auto& vehicle_state =
        apollo::common::VehicleStateProvider::Instance()->vehicle_state();
    fallback_start_point.set_v(vehicle_state.linear_velocity());

    *(frame_->mutable_open_space_info()->mutable_future_collision_point()) =
        future_collision_point;

设置最小停车距离=0.5回退开始点车速的平方/4;
(s=0.5
at^2
=0.5
a*(v/a)^2 由于最大加速度为4,所以
=0.5*v^2/4)
停车距离:如果倒车,则碰撞点-开始点,最大为0,1为缓冲距离,前进档,计算方式类似。
设定车的最大加速度和最大减速度。

    // min stop distance: (max_acc)
    double min_stop_distance =
        0.5 * fallback_start_point.v() * fallback_start_point.v() / 4.0;

    // TODO(QiL): move 1.0 to configs
    double stop_distance =
        fallback_trajectory_pair_candidate.second == canbus::Chassis::GEAR_DRIVE
            ? std::max(future_collision_point.path_point().s() -
                           fallback_start_point.path_point().s() - 1.0,
                       0.0)
            : std::min(future_collision_point.path_point().s() -
                           fallback_start_point.path_point().s() + 1.0,
                       0.0);

    ADEBUG << "stop distance : " << stop_distance;
    // const auto& vehicle_config =
    //     common::VehicleConfigHelper::Instance()->GetConfig();
    const double vehicle_max_acc = 4.0;   // vehicle_config.max_acceleration();
    const double vehicle_max_dec = -4.0;  // vehicle_config.max_deceleration();

    double stop_deceleration = 0.0;

根据停车总距离求加速度值(R档为负)
计算方法为:
s=0.5at^2 =0.5a*(v/a)^2 =0.5*v/a

    if (fallback_trajectory_pair_candidate.second ==
        canbus::Chassis::GEAR_REVERSE) {
      stop_deceleration =
          std::min(fallback_start_point.v() * fallback_start_point.v() /
                       (2.0 * (stop_distance + 1e-6)),
                   vehicle_max_acc);
      stop_distance = std::min(-1 * min_stop_distance, stop_distance);
    } else {
      stop_deceleration =
          std::max(-fallback_start_point.v() * fallback_start_point.v() /
                       (2.0 * (stop_distance + 1e-6)),
                   vehicle_max_dec);
      stop_distance = std::max(min_stop_distance, stop_distance);
    }

按距离搜索所选轨迹中的停止索引

    size_t stop_index = fallback_start_index;

    for (size_t i = fallback_start_index;
         i < fallback_trajectory_pair_candidate.first.NumOfPoints(); ++i) {
      if (std::abs(
              fallback_trajectory_pair_candidate.first[i].path_point().s()) >=
          std::abs(fallback_start_point.path_point().s() + stop_distance)) {
        stop_index = i;
        break;
      }
    }

在回退开始索引之前,对轨迹中的车速和停车加速度进行设置。

    for (size_t i = 0; i < fallback_start_index; ++i) {
      fallback_trajectory_pair_candidate.first[i].set_v(
          fallback_start_point.v());
      fallback_trajectory_pair_candidate.first[i].set_a(stop_deceleration);
    }

回退开始索引是否就是停车索引。
如果是,则:
将回退初始车速设置为0,加速度设定为最大值。
在停止索引后删除所有轨迹点
附加相同位置但速度为零的轨迹点

    // TODO(QiL): refine the logic and remove redundant code, change 0.5 to from
    // loading optimizer configs

    // If stop_index == fallback_start_index;
    if (fallback_start_index == stop_index) {
      // 1. Set fallback start speed to 0, accleration to max accleration.
      AINFO << "Stop distance within safety buffer, stop now!";
      fallback_start_point.set_v(0.0);
      fallback_start_point.set_a(0.0);
      fallback_trajectory_pair_candidate.first[stop_index].set_v(0.0);
      fallback_trajectory_pair_candidate.first[stop_index].set_a(0.0);

      // 2. Trim all trajectory points after stop index
      fallback_trajectory_pair_candidate.first.erase(
          fallback_trajectory_pair_candidate.first.begin() + stop_index + 1,
          fallback_trajectory_pair_candidate.first.end());

      // 3. AppendTrajectoryPoint with same location but zero velocity
      for (int i = 0; i < 20; ++i) {
        common::TrajectoryPoint trajectory_point(
            fallback_trajectory_pair_candidate.first[stop_index]);
        trajectory_point.set_relative_time(
            i * 0.5 + 0.5 +
            fallback_trajectory_pair_candidate.first[stop_index]
                .relative_time());
        fallback_trajectory_pair_candidate.first.AppendTrajectoryPoint(
            trajectory_point);
      }

      *(frame_->mutable_open_space_info()->mutable_fallback_trajectory()) =
          fallback_trajectory_pair_candidate;

      return Status::OK();
    }

如果回退初始索引小于停止索引,则对于轨迹中所有的轨迹点:
建立方程:ax^2 + bx + c = 0,其中a=停车减速度,b=2回退开始点车速,
c=-2
回退点走过的距离,求得的解为相对时间。
即为:s=o.5at^2 + bt + c
如果能够求得该时间且走过的距离小于停车距离,则
车速=回退估计开始点车速+停车减速度*相对时间
对车速进行限制。
设置加速度为停车减速度。

    for (size_t i = fallback_start_index; i <= stop_index; ++i) {
      double new_relative_time = 0.0;
      double temp_v = 0.0;
      double c =
          -2.0 * fallback_trajectory_pair_candidate.first[i].path_point().s();

      if (QuardraticFormulaLowerSolution(stop_deceleration,
                                         2.0 * fallback_start_point.v(), c,
                                         &new_relative_time) &&
          std::abs(
              fallback_trajectory_pair_candidate.first[i].path_point().s()) <=
              std::abs(stop_distance)) {
        ADEBUG << "new_relative_time" << new_relative_time;
        temp_v =
            fallback_start_point.v() + stop_deceleration * new_relative_time;
        // speed limit
        if (std::abs(temp_v) < 1.0) {
          fallback_trajectory_pair_candidate.first[i].set_v(temp_v);
        } else {
          fallback_trajectory_pair_candidate.first[i].set_v(
              temp_v / std::abs(temp_v) * 1.0);
        }
        fallback_trajectory_pair_candidate.first[i].set_a(stop_deceleration);

        fallback_trajectory_pair_candidate.first[i].set_relative_time(
            new_relative_time);
      }

否则,提示方程无解,
索引如果不等于0,则
更新轨迹点为上一时刻轨迹点,将车速,加速度设置为0,更新时间戳;
否则,更新车速,加速度为0,不更新时间戳。

 else {
        AINFO << "QuardraticFormulaLowerSolution solving failed, stop "
                 "immediately!";

        if (i != 0) {
          fallback_trajectory_pair_candidate.first[i]
              .mutable_path_point()
              ->CopyFrom(
                  fallback_trajectory_pair_candidate.first[i - 1].path_point());
          fallback_trajectory_pair_candidate.first[i].set_v(0.0);
          fallback_trajectory_pair_candidate.first[i].set_a(0.0);
          fallback_trajectory_pair_candidate.first[i].set_relative_time(
              fallback_trajectory_pair_candidate.first[i - 1].relative_time() +
              0.5);
        } else {
          fallback_trajectory_pair_candidate.first[i].set_v(0.0);
          fallback_trajectory_pair_candidate.first[i].set_a(0.0);
        }
      }
    }

将停车索引之后的轨迹点擦除。

   // 2. Erase afterwards
    fallback_trajectory_pair_candidate.first.erase(
        fallback_trajectory_pair_candidate.first.begin() + stop_index + 1,
        fallback_trajectory_pair_candidate.first.end());

附加相同位置但速度为零的轨迹点

    // 3. AppendTrajectoryPoint with same location but zero velocity
    for (int i = 0; i < 20; ++i) {
      common::TrajectoryPoint trajectory_point(
          fallback_trajectory_pair_candidate.first[stop_index]);
      trajectory_point.set_relative_time(
          i * 0.5 + 0.5 +
          fallback_trajectory_pair_candidate.first[stop_index].relative_time());
      fallback_trajectory_pair_candidate.first.AppendTrajectoryPoint(
          trajectory_point);
    }

如果无碰撞,则设置回退失败。

else {
    frame_->mutable_open_space_info()->set_fallback_flag(false);
  }
  • 6
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 答1: Apollo 5.0是百度自动驾驶平台的一个重要版本,而百度OpenDrive格式规范则是一种用于描述自动驾驶车辆行驶环境的标准化文件格式。这种格式规范定义了自动驾驶车辆在行驶路线、车道、路标、信号灯等方面的细节信息,并且可被车辆感知系统、规划系统、控制系统等多个系统共同使用。 Apollo 5.0采用了百度OpenDrive格式规范作为自动驾驶车辆行驶环境描述的标准,具有对其他标准的兼容性和可扩展性,能够支持大规模自动驾驶车辆的部署和应用。该规范定义了自动驾驶车辆所需的各种路网信息,包括道路的几何形状、车道宽度、半径、坡度、限速等,以及路边设施、路标、交通信号灯等信息。同时,该规范可将多个道路、车道组合成逻辑路径,以识别不同的驾驶情境。 总的来说,百度OpenDrive格式规范对于建立自动驾驶车辆的全面、可靠的驾驶环境提供了不可或缺的支持,让自动驾驶车辆更加精准、安全地进行行驶。而Apollo 5.0则使得这种规范得以更好地应用于实际场景中,为自动驾驶技术的未来发展奠定了坚实的基础。 ### 答2: Apollo 5.0是百度自动驾驶平台的一次升级,带来了许多新的功能和变化。其中一个重要的变化是百度在开放自己的高精度地图数据的同时,也推出了一套自己的地图格式规范——OpenDrive,以帮助其他自动驾驶技术的开发者更好地使用这些地图数据。 OpenDrive是一种XML格式的文件,它包含了道路的拓扑结构、道路的几何形状、道路标志等详细信息。它的设计初衷是为了满足自动驾驶领域中对高精度地图数据的需要,其规范与其他类似格式相比,有以下几个优点: 一、标准化程度高:OpenDrive的编写方式比较统一,可以确保不同地图数据之间的兼容性,这是目前自动驾驶技术的一个瓶颈。 二、信息丰富度高:OpenDrive提供了很多详细的信息,比如道路的形状、标识、限速等等,这些信息对于自动驾驶来说非常重要。 三、易于更新:OpenDrive提供了一个易于编写和更新的接口,开发者可以针对不同场景自由定制地图数据,这样可以确保地图数据的及时性和准确性。 在实际应用中,使用OpenDrive格式可以帮助自动驾驶车辆更加准确、安全地行驶。同时,由于其开放性,其他的卫星地图供应商也可以兼容这种格式,这将为自动驾驶产业的可持续发展提供更多可能性。 总之,OpenDrive是一个非常有前途的高精度地图格式规范,正努力为自动驾驶技术的发展提供服务。百度的推出为自动驾驶领域打开了一个新的局面,可以预见,在OpenDrive和其他类似规范的不断演进和发展下,自动驾驶产业将迎来更加广阔的发展空间。 ### 答3: Apollo5.0是由百度开发的一种自动驾驶系统,而Opendrive格式规范则是存储和传输道路信息的一种标准。百度将其引入到Apollo5.0中,以便自动驾驶车辆能够更好地理解和适应道路环境。 这种格式规范主要包含有关道路结构、车道线、交通标志和路口等信息。Opendrive规范将这些信息组织成层级结构,并使用XML文件来描述。这些文件可以从高精度地图供应商或通过百度的车辆探索器应用程序生成。 在Apollo5.0中,Opendrive格式规范被用来存储、传输和处理道路信息。通过收集和处理这些信息,自动驾驶车辆可以获得更准确的定位和环境感知,从而更好地规划和实施行车路线。 值得注意的是,Opendrive规范是公开可用的,因此它可以轻松地与其它厂商、城市规划者和智能交通系统开发者协作和共享。这样一来,整个行业将能够更好地理解和适应自动驾驶技术,并将其应用到更多的场景中。 总的来说,将Opendrive格式规范引入到Apollo5.0中是一种创新性的举措,它为当前和未来的自动驾驶技术发展铺平了道路。通过采用这种规范,我们可以更好地理解和应对道路环境,进而实现更安全、更高效和更智能的出行体验。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值