当前位置:   article > 正文

百度Apollo学习:参考线(ReferenceLine)生成算法和源码介绍_参考线拼接

参考线拼接

百度Apollo学习:参考线(ReferenceLine)生成算法和源码介绍

参考线是根据routing规划的路线,生成一系列参考轨迹,提供给规划算法做为参考,从而生成最终的规划轨迹。

image

附赠自动驾驶学习资料和量产经验:链接

为什么要提供参考呢?因为道路是结构化道路,在没有参考的情况下,需要通过搜索算法来查找路线,这种场景在机器人路径规划中比较普遍,机器人在一个开放空间只要没有障碍物它就可以行走,而车不一样,车是在道路上行驶的,在提供参考的情况下,节省了查找的时间和复杂度,降低了算法的难度,这也就是参考线的意义。

ReferenceLine和ReferenceLineInfo的关系?

ReferenceLine提供的是轨迹信息,而ReferenceLineInfo在ReferenceLine的基础上新添加了决策信息。

参考线(ReferenceLineInfo)

参考线信息,在参考线的基础添加了决策信息,ST图等。

参考线中的点(ReferencePoint)

参考线中的点继承至hdmap::MapPathPoint,而hdmap::MapPathPoint又继承至common::math::Vec2d,也就是说参考线中的点实际上包含了路径点的信息,它有原来路径点中的朝向和坐标信息,同时还新增加了曲率信息,通过下图我们可以清楚的看出上述关系。

image

参考线(ReferenceLine)

理解了参考线中的点之后,我们再看参考线的数据结构。

  std::vector<SpeedLimit> speed_limit_;  // 速度限制
  std::vector<ReferencePoint> reference_points_;  // 参考线的点
  hdmap::Path map_path_;  // 路径
  uint32_t priority_ = 0;  // 优先级
  • 1
  • 2
  • 3
  • 4

其中速度限制主要标明参考线中哪些段有速度限制,因为是一个数组,因此一个参考线中可以有多段不同的限速。优先级则表示了当前参考线的优先级,用于后面有多个参考线的时候进行挑选。

参考线中的点也是一个数组,也就是说参考线是由参考点组成的,而map_path_则是最不好理解的,实际上map_path_就是地图中参考线,把参考线中的点转换到地图中,因此map_path_中的点和参考点数组的大小是一致的。

除此之外,参考线还提供了一些方法,通过这些方法我们可以拼接参考线,也可以判断参考线所在位置的路的宽度,以及是否在路上等信息。我们先分析这些方法的功能实现,然后再介绍哪些场景需要用到这些功能。

构造函数

我们可以看到有2种方式来生成ReferenceLine,可以通过一组参考点来生成,也可以通过地图路径来生成,这2者实际上是等价的,下面我们开始分析。

1. 通过一组参考点生成,reference_points_直接拷贝赋值了,然后再用reference_points生成hdmap::MapPathPoint,最后保存到map_path_。

ReferenceLine::ReferenceLine(
    const std::vector<ReferencePoint>& reference_points)
    : reference_points_(reference_points),
      map_path_(std::move(std::vector<hdmap::MapPathPoint>(
          reference_points.begin(), reference_points.end()))) {
    ...
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

2. 通过地图路径生成参考线。遍历路径中的点,然后取`lane_waypoints`中的第一个点,保存到参考点的数组中。

ReferenceLine::ReferenceLine(const MapPath& hdmap_path)
    : map_path_(hdmap_path) {
  for (const auto& point : hdmap_path.path_points()) {
    const auto& lane_waypoint = point.lane_waypoints()[0];
    reference_points_.emplace_back(
        hdmap::MapPathPoint(point, point.heading(), lane_waypoint), 0.0, 0.0);
  }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

缝合参考线(Stitch)

缝合参考线是把2段参考线连接起来,代码中也给出了下面2种情况。并且每次拼接的时候,会尽可能多的采用自身的参考线。

   * Example 1
   * this:   |--------A-----x-----B------|
   * other:                 |-----C------x--------D-------|
   * Result: |------A-----x-----B------x--------D-------|
   * In the above example, A-B is current reference line, and C-D is the other
   * reference line. If part B and part C matches, we update current reference
   * line to A-B-D.
   *
   * Example 2
   * this:                  |-----A------x--------B-------|
   * other:  |--------C-----x-----D------|
   * Result: |--------C-----x-----A------x--------B-------|
   * In the above example, A-B is current reference line, and C-D is the other
   * reference line. If part A and part D matches, we update current reference
   * line to C-A-B.
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

接下来我们分析下代码。

bool ReferenceLine::Stitch(const ReferenceLine& other) {
  // 1. 找到起点的交点
  auto first_point = reference_points_.front();
  common::SLPoint first_sl;
  if (!other.XYToSL(first_point, &first_sl)) {
    AWARN << "Failed to project the first point to the other reference line.";
    return false;
  }
  bool first_join = first_sl.s() > 0 && first_sl.s() < other.Length();
  // 2. 找到终点的交点
  auto last_point = reference_points_.back();
  common::SLPoint last_sl;
  if (!other.XYToSL(last_point, &last_sl)) {
    AWARN << "Failed to project the last point to the other reference line.";
    return false;
  }
  bool last_join = last_sl.s() > 0 && last_sl.s() < other.Length();
  // 3. 如果起点和终点都没有交点,则退出
  if (!first_join && !last_join) {
    AERROR << "These reference lines are not connected.";
    return false;
  }

  // 累积s值
  const auto& accumulated_s = other.map_path().accumulated_s();
  // 参考点
  const auto& other_points = other.reference_points();
  auto lower = accumulated_s.begin();
  static constexpr double kStitchingError = 1e-1;

  if (first_join) {
    // 4. 如果横向偏移大于0.1m,则退出
    if (first_sl.l() > kStitchingError) {
      AERROR << "lateral stitching error on first join of reference line too "
                "big, stitching fails";
      return false;
    }
    lower = std::lower_bound(accumulated_s.begin(), accumulated_s.end(),
                             first_sl.s());
    // 4.1 因为this的起点在other之后,插入other的起点到this的起点
    size_t start_i = std::distance(accumulated_s.begin(), lower);
    reference_points_.insert(reference_points_.begin(), other_points.begin(),
                             other_points.begin() + start_i);
  }
  if (last_join) {
    // 5.1 如果横向偏移大于0.1m,则退出
    if (last_sl.l() > kStitchingError) {
      AERROR << "lateral stitching error on first join of reference line too "
                "big, stitching fails";
      return false;
    }
    // 5.2 因为this的终点小于other的终点,把other终点拼接到参考线的终点
    auto upper = std::upper_bound(lower, accumulated_s.end(), last_sl.s());
    auto end_i = std::distance(accumulated_s.begin(), upper);
    reference_points_.insert(reference_points_.end(),
                             other_points.begin() + end_i, other_points.end());
  }
  map_path_ = MapPath(std::move(std::vector<hdmap::MapPathPoint>(
      reference_points_.begin(), reference_points_.end())));
  return true;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61

分割参考线(Segment)

分割参考线的方法是根据起点s,向前和向后的查看距离把参考线进行分割。 有2个方法,我们只看其中一个就可以了。

  // 根据s值获取参考点(会根据s进行插值)
  ReferencePoint GetReferencePoint(const double s) const;  
  // 根据x,y找到最近的点,并且进行插值
  ReferencePoint GetReferencePoint(const double x, const double y) const;  

  // PathPoint转换为FrenetFramePoint
  common::FrenetFramePoint GetFrenetPoint(
      const common::PathPoint& path_point) const;
  
  // 
  std::pair<std::array<double, 3>, std::array<double, 3>> ToFrenetFrame(
      const common::Traj
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/爱喝兽奶帝天荒/article/detail/899722
推荐阅读
  

闽ICP备14008679号