赞
踩
参考线是根据routing规划的路线,生成一系列参考轨迹,提供给规划算法做为参考,从而生成最终的规划轨迹。
为什么要提供参考呢?因为道路是结构化道路,在没有参考的情况下,需要通过搜索算法来查找路线,这种场景在机器人路径规划中比较普遍,机器人在一个开放空间只要没有障碍物它就可以行走,而车不一样,车是在道路上行驶的,在提供参考的情况下,节省了查找的时间和复杂度,降低了算法的难度,这也就是参考线的意义。
ReferenceLine和ReferenceLineInfo的关系?
ReferenceLine提供的是轨迹信息,而ReferenceLineInfo在ReferenceLine的基础上新添加了决策信息。
参考线信息,在参考线的基础添加了决策信息,ST图等。
参考线中的点(ReferencePoint)
参考线中的点继承至hdmap::MapPathPoint,而hdmap::MapPathPoint又继承至common::math::Vec2d,也就是说参考线中的点实际上包含了路径点的信息,它有原来路径点中的朝向和坐标信息,同时还新增加了曲率信息,通过下图我们可以清楚的看出上述关系。
参考线(ReferenceLine)
理解了参考线中的点之后,我们再看参考线的数据结构。
std::vector<SpeedLimit> speed_limit_; // 速度限制
std::vector<ReferencePoint> reference_points_; // 参考线的点
hdmap::Path map_path_; // 路径
uint32_t priority_ = 0; // 优先级
其中速度限制主要标明参考线中哪些段有速度限制,因为是一个数组,因此一个参考线中可以有多段不同的限速。优先级则表示了当前参考线的优先级,用于后面有多个参考线的时候进行挑选。
参考线中的点也是一个数组,也就是说参考线是由参考点组成的,而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()))) {
...
}
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);
}
}
缝合参考线(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.
接下来我们分析下代码。
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; }
分割参考线(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
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。