Apollo:参考线

您所在的位置:网站首页 Apollo软件平台组成 Apollo:参考线

Apollo:参考线

2023-11-01 17:17| 来源: 网络整理| 查看: 265

Apollo项目的源码可以从github上获取:ApolloAuto/apollo。 本文中贴出的源码取自2019年2月7日的版本(版本:3.5) 概述 什么是参考线 就是高精地图所提供的道路的中心线,在此基础上做平滑得到的一条线。它是理想状态下没有障碍物的一条线。要保障平滑,所以在运动的时候,汽车不会横向摆动

在这里插入图片描述

参考线可以简单理解为候选路径 导航规划的路线

在这里插入图片描述 导航规划的路线一般由三个部分组成:Routing、参考线以及轨迹。

Routing: 全局路径规划的结果,一般规划出来的长度为几十公里甚至上百公里,若没有障碍物,车辆将会沿着这条路径一直行驶。若有障碍物,则会由Planning模块发布回Routing模块进行重新规划。参考线: 决策规划模块根据车辆的实时位置进行计算。参考线的计算依赖于Routing的结果,但同时需要车辆周围的动态信息(障碍物、交通规则)。参考线相当于Routing结果里局部数据(车辆当前位置的一段Routing),距离通常只有几百米。参考线可能会有多条。轨迹: 是规划决策模块的最终输出结果。轨迹的输入是参考线。轨迹不仅包含车辆的路径信息,也包括车辆的动态信息(速度、加速度等)。 为什么需要参考线

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

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

为什么不直接使用routing?

导航路径不平滑导航路径太长

这会带来什么后果

不平滑可能导致车辆形式不平稳

过长的导航路线:

不利于坐标转换:路径越长,离散的点越多,又需要遍历点找到距离最短的点:匹配点,才能计算(s,l)坐标系下的s,这个计算量就很大过长的路径,障碍物的投影可能不唯一:如图绿色导航路径一般不是平滑的路线,不利于后面的控制

解决方法:在全局路径上截取一小段路径做平滑,平滑后的线就是参考线(参考线就是s轴要做投影的)

参考线是解决方案,解决导航路径过长,不平滑的问题 在这里插入图片描述

在这里插入图片描述

参考线在整个Planning模块中所处的位置

在这里插入图片描述 在这里插入图片描述 决策规划模块负责生成车辆的行驶轨迹。要做到这一点,决策规划模块需要从宏观到局部经过三个层次来进行决策。

第一个层次是Routing的搜索结果。Routing模块的输入是若干个按顺序需要达到的途经点(也可能只有一个起点和一个终点)。Routing模块根据地图的拓扑结构搜索出可达的完整路径来,这个路线的长度可能是几公里甚至几百公里。因此这个是最为宏观的数据。另外,Routing的搜索结果是相对固定的。在没有障碍物的情况下,车辆会一直沿着原先获取到的Routing路线行驶。只有当车辆行驶出了原先规划的路线之外(例如:为了避障),才会重新发送请求给Routing模块,以重新计算路线。

第二个层次就是参考线。决策规划魔抗会实时根据车辆的具体位置来计算参考线。参考线的计算会以Routing的路线为基础。但同时,参考线会考虑车辆周围的动态信息。比如:障碍物,交通规则灯。参考线是包含车辆所在位置周边一定的范围,通常是几百米的长度。相较于Routing结果,它是较为局部的数据。

第三个层次是轨迹。轨迹是决策规划魔抗的最终输出结果。它的依据是参考线。在同一时刻,参考线可能会有多条。比如:在变道的时候,自车所在车道和目标车道都会有一条参考线。而轨迹,是在所有可能的结果中,综合决策和优化的结果,最终的唯一结果。因此它是更为具体和局部的数据。轨迹不仅仅包含了车辆的路线,还包含了车辆行驶这条路线时的详细状态。例如:车辆的方向,速度,加速度等等。

ReferenceLine 是整个规划算法的基础,在apollo中起到了关键的承上启下的作用。,规划的目的就是使车辆按照ReferenceLine行驶。

参考线是根据车辆位置相对局部的一个数据,它包含了车辆前后一定范围内的路径信息。在车辆行驶过程中,Planning会在每一个计算周期中生成ReferenceLine。

然后在这个ReferenceLine上进行后面的处理。例如:交通规则逻辑,障碍物投影,路径优化,速度决策等等。可以说,参考线贯穿了整个Planning模块的实现。

关系

在这里插入图片描述 从这幅图中可以看出,这里涉及到三个模块:

routing模块:生成全局路径规划pnc map模块:负责读取和处理routing搜索结果planning模块:根据routing结果和车辆实时状态(包括周边环境)生成参考线和轨迹

在Planning模块中有以下三个数据结构将是本文关注的重点:

ReferenceLine: 原始参考线,源码位于planning/reference_line/目录下。根据Routing的搜索结果生成。 ReferenceLineInfo: 源码位于planning/common/目录下。参考线信息,在参考线的基础添加了决策信息,ST图等。Planning实现中,逻辑计算的基础数据结构,很多操作都会在这个数据结构上进行(例如:交通规则逻辑,障碍物投影,路径优化,速度决策等)。ReferenceLine和ReferenceLineInfo的关系?可以建立理解为ReferenceLine提供的是轨迹信息,而ReferenceLineInfo在ReferenceLine的基础上新添加了决策信息。 Trajectory:下文中我们将看到,有好几个结构用来描述轨迹。它们在不同的场合下使用。这其中,ADCTrajectory是Planning模块的输出。它是Planning模块一次计算循环中,处理了所有逻辑的最终结果,包含了车辆行驶需要的所有信息。因此,这个数据将直接影响到自动驾驶车辆的行车行为。 数据结构 Apollo:参考线上的点ReferencePointApollo:参考线ReferenceLine是如何定义的Apollo:参考线提供者ReferenceLineProvider 平滑器(ReferenceLineSmoother) 为什么需要做平滑 直接通过RouteSegments生成的ReferenceLine可能是不平滑的。如果直接让车辆沿着不平滑的路线行驶可能造成车辆方向的抖动或者大幅变化,这对乘坐体验来说非常不好。因此,原始的路线数据需要经过算法的平滑。 一共有几种平滑器

具体的逻辑由下面这个方法完成:

/ modules/planning/reference_line/reference_line_provider.cc bool ReferenceLineProvider::SmoothReferenceLine( const ReferenceLine &raw_reference_line, ReferenceLine *reference_line) { if (!FLAGS_enable_smooth_reference_line) { *reference_line = raw_reference_line; return true; } // generate anchor points: std::vector anchor_points; GetAnchorPoints(raw_reference_line, &anchor_points); smoother_->SetAnchorPoints(anchor_points); if (!smoother_->Smooth(raw_reference_line, reference_line)) { AERROR common::PathPoint path_point; double lateral_bound = 0.0; double longitudinal_bound = 0.0; // enforce smoother to strictly follow this reference point bool enforced = false; }; class ReferenceLineSmoother { public: explicit ReferenceLineSmoother(const ReferenceLineSmootherConfig& config) : config_(config) {} // 虚函数,设置锚点 virtual void SetAnchorPoints( const std::vector& achor_points) = 0; // 虚函数,平滑参考线 virtual bool Smooth(const ReferenceLine&, ReferenceLine* const) = 0; virtual ~ReferenceLineSmoother() = default; protected: ReferenceLineSmootherConfig config_; };

在这里插入图片描述 常见的参考线平滑方式有:离散点的平滑(Apollo采用)、螺旋线的平滑以及样条曲线的平滑。

在实现中,Smoother用到了下面两个开源库:

Ipopt ProjectEigen 具体使用哪一个平滑器

具体使用哪一个平滑器由ReferenceLineProvider在初始化的时候读取配置文件来决定:

CHECK(common::util::GetProtoFromFile(FLAGS_smoother_config_filename, &smoother_config_)) smoother_.reset(new SpiralReferenceLineSmoother(smoother_config_)); } else if (smoother_config_.has_cos_theta()) { smoother_.reset(new CosThetaReferenceLineSmoother(smoother_config_)); } else { CHECK(false) ① common::SpeedPoint speed_point; if (!speed_data_.EvaluateByTime(cur_rel_time, &speed_point)) { AERROR ② AERROR trajectory_pb->add_lane_id()->CopyFrom(id); ③ } trajectory_pb->set_trajectory_type(best_ref_info->trajectory_type()); if (FLAGS_enable_rss_info) { trajectory_pb->mutable_rss_info()->CopyFrom(best_ref_info->rss_info()); } best_ref_info->ExportDecision(trajectory_pb->mutable_decision()); ... last_publishable_trajectory_.reset(new PublishableTrajectory( current_time_stamp, best_ref_info->trajectory())); ④ ... if (FLAGS_enable_stitch_last_trajectory) { last_publishable_trajectory_->PrependTrajectoryPoints( std::vector(stitching_trajectory.begin(), stitching_trajectory.end() - 1)); } last_publishable_trajectory_->PopulateTrajectoryProtobuf(trajectory_pb); ⑤ best_ref_info->ExportEngageAdvice(trajectory_pb->mutable_engage_advice()); return status; }

这段代码中的几个点说明如下:

planner_->Plan是执行每个Planner的主体算法逻辑。在有多个ReferenceLineInfo的情况下,选取最合适的一条。记录ReferenceLineInfo包含的lane id。将轨迹的数据格式转换成PublishableTrajectory类型并记录到last_publishable_trajectory_中。导出成最终格式:ADCTrajectory。Apollo 3.5已经改用新的框架Cyber RT,最终轨迹的发出是在Cyber Component的实现PlanningComponent发出。相关代码如下: ADCTrajectory adc_trajectory_pb; planning_base_->RunOnce(local_view_, &adc_trajectory_pb); auto start_time = adc_trajectory_pb.header().timestamp_sec(); common::util::FillHeader(node_->Name(), &adc_trajectory_pb); // modify trajectory relative time due to the timestamp change in header const double dt = start_time - adc_trajectory_pb.header().timestamp_sec(); for (auto& p : *adc_trajectory_pb.mutable_trajectory_point()) { p.set_relative_time(p.relative_time() + dt); } planning_writer_->Write(std::make_shared(adc_trajectory_pb));

至此,决策规划模块的任务就完成了。接下来就是由控制模块按照这里发出的轨迹来控制车辆的行驶。

参考 apollo介绍之参考线(二十七)万字讲解Apollo,全网Apollo资料整理和学习 Apollo Planning模块源代码分析apollo介绍之参考线(二十七):没有看完,有点吃力Apollo星火计划学习笔记——参考线平滑算法解析及实现(以U型弯道场景仿真调试为例)

在车辆行驶过程中,必不可少的就是判断自车以及障碍物所处的位置。这就很自然的需要将物体投影到参考线上来进行计算。对于这些内容,可以浏览下面这些接口的实现。这些逻辑基本上是点和位置的计算,这里就不展开了。

ReferencePoint GetReferencePoint(const double s) const; common::FrenetFramePoint GetFrenetPoint( const common::PathPoint& path_point) const; std::vector GetReferencePoints(double start_s, double end_s) const; size_t GetNearestReferenceIndex(const double s) const; ReferencePoint GetNearestReferencePoint(const common::math::Vec2d& xy) const; std::vector GetLaneSegments(const double start_s, const double end_s) const; ReferencePoint GetNearestReferencePoint(const double s) const; ReferencePoint GetReferencePoint(const double x, const double y) const; bool GetApproximateSLBoundary(const common::math::Box2d& box, const double start_s, const double end_s, SLBoundary* const sl_boundary) const; bool GetSLBoundary(const common::math::Box2d& box, SLBoundary* const sl_boundary) const; bool GetSLBoundary(const hdmap::Polygon& polygon, SLBoundary* const sl_boundary) const;

StdPlanning已经改名为OnLanePlanning。



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3