添加链接
link管理
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接
本文详细介绍了在Apollo自动驾驶框架中设计十字路口左转算法的过程,包括路径规划、决策逻辑以及场景管理。规划模块基于场景划分,通过Scenario、Stage和Task进行任务拆分与执行。在十字路口场景中,如交通灯保护,算法会涉及多个阶段和任务,如接近交通灯、路口巡航等,确保安全左转。 摘要由CSDN通过智能技术生成

如何设计一个十字路口左转的算法,包括路径规划与决策两个部分

本文将以apollo为例设计一个十字路口左转的算法,包含从规划模块的输入、输出,具体的几个主要代码模块的讲述,还有细节的十字路口左转的算法。

1、十字路口左转算法在apollo框架的位置

planning模块的整体框架
上面的图片是apollo 的planning模块的整体框架,十字路口左转算法是众多scenario的一种。
1、planning 的输入输出
在这里插入图片描述
在Apollo CyberRT框架下,输出输出由Reader和Writer构成。CyberRT框架定义了两种模式,分别为消息触发和时间触发,而planning 中采用的消息触发,因此要接到特定的上游消息后,才会进入内部主逻辑,消息触发的上游消息,localview定义在common文件里.
planning接受的Reader输入包括traffic_light,routing,pad,relative_map, story-telling;接受的Process()入参为Prediction,Localization,Chassis等。
planning的输出就比较简单,主要是给ADCTrajectory数据,包含里一条带时间。速度的轨迹点集。
在这里插入图片描述
apollo的主框架分为两个线程,子线程ReferenceLinePrivider 以20HZ的频率运行,用于计算planning中最重要的数据结构reference_line;主线程则是基于场景划分的思路,多数场景下是采用基于ReferenceLine的规划算法,对于泊车相关场景,则利用openspace算法。

2、planning中的场景管理

apollo中的规划里的一个重要思想就是基于场景划分来调用不同的task处理,而其中如何进行场景分配便是实现该思想的核心。下面的图就是scenario_manager的具体流程逻辑,可以看到scenario_manager会从Observe(frame)获取reference_line所遇到的第一个overlap的类型,从SenarioDispatch(frame)获取对有场景的判断(这里的场景会是依次判断的:ParkandGo,intersection,Pullover,ValetParking,Deadend等)。然后scenario_manager_Update()会开始scenario、stage、task这三个。
(具体来说,scenario代表当前所处的场景,包括正常的路上行驶场景、停车场景、红绿灯路口场景等。stage则是在当前场景下的阶段,例如在红绿灯路口场景下,stage可以分为等待绿灯、行驶中等。task则是在当前阶段下的任务,例如在等待绿灯阶段下,task可以分为等待时间到达、检测绿灯等)
在这里插入图片描述
这里重点介绍十字路口场景
首先,根据先前计算的地图第一个遇到的overlap来确定大类型是包含交通标识的交叉口,还是其他交叉口。其次,若是包含交通标识的交叉口,还细分为stop_sign、traffic_light以及yield_sign.
在这里插入图片描述

3、规划模块里对scenario,stage,task的理解

apollo在每个panning 周期首先决策当前处于哪个场景scenario下面的哪个状态stage当中,当确认好stage之后,便会调用这个stage的Process()函数来执行具体的规划逻辑。
stage::Process();主要逻辑是根据配置文件,来依次执行每一个注册的task的Execute()函数,从而把具体的规划任务分散到每个task当中。
stage不属于某个特定的scenario,task也不属于某个特定的stage,这些任务通过配置文件进行配置,这样便保证了整个规划模块的解耦和可扩展性
在这里插入图片描述
每个stage都要做速度决策,速度优化,路径决策,路径优化等task

4、intersection的具体执行

因为intersection有很多种情况,比如在trafiic_sign的scenario下就有protected,unprotected_left_turn,unprotected_right_turn三种情况;还有bare_intersection/unprotected,stop_sign/unprotcted这两种情况
在这里插入图片描述
以traffic_sign下protected场景为例,分析apollo的代码
在protected场景下可以看到有几个代码文件,一个是stage_approach,一个是stage_intersection_cruise,一个是traffic_light_protected_scenario;

首先我们看stage_approach

namespace apollo {
namespace planning {
namespace scenario {
namespace traffic_light {
struct TrafficLightProtectedContext;
class TrafficLightProtectedStageApproach : public Stage {
 public:
  TrafficLightProtectedStageApproach(
      const ScenarioConfig::StageConfig& config,
      const std::shared_ptr<DependencyInjector>& injector)
      : Stage(config, injector) {}
 private:
  Stage::StageStatus Process(const common::TrajectoryPoint& planning_init_point,
                             Frame* frame) override;
  TrafficLightProtectedContext* GetContext() {
    return GetContextAs<TrafficLightProtectedContext>();
 private:
  Stage::StageStatus FinishStage();
 private:
  ScenarioTrafficLightProtectedConfig scenario_config_;
}  // namespace traffic_light
}  // namespace scenario
}  // namespace planning
}  // namespace apollo

这段代码是Apollo Auto中的一个交通灯保护场景的实现。TrafficLightProtectedStageApproach类是该场景中的一个阶段,用于处理车辆接近交通灯的情况。Process函数是TrafficLightProtectedStageApproach类的一个成员函数,用于处理车辆接近交通灯的情况。FinishStage函数是TrafficLightProtectedStageApproach类的另一个成员函数,用于完成该阶段。TrafficLightProtectedContext结构体是TrafficLightProtectedStageApproach类中使用的一个结构体。

然后看stage_intersection_cruise

namespace apollo {
namespace planning {
namespace scenario {
namespace traffic_light {
struct TrafficLightProtectedContext;
class TrafficLightProtectedStageIntersectionCruise : public Stage {
 public:
  TrafficLightProtectedStageIntersectionCruise(
      const ScenarioConfig::StageConfig& config,
      const std::shared_ptr<DependencyInjector>& injector)
      : Stage(config, injector) {}
 private:
  Stage::StageStatus Process(const common::TrajectoryPoint& planning_init_point,
                             Frame* frame) override;
  TrafficLightProtectedContext* GetContext() {
    return GetContextAs<TrafficLightProtectedContext>();
  Stage::StageStatus FinishStage();
 private:
  ScenarioTrafficLightProtectedConfig scenario_config_;
  StageIntersectionCruiseImpl stage_impl_;
}  // namespace traffic_light
}  // namespace scenario
}  // namespace planning
}  // namespace apollo

这段代码是Apollo Auto中的一个交通灯保护场景的实现。TrafficLightProtectedStageIntersectionCruise类是该场景中的一个阶段,用于处理车辆在交通灯保护下通过路口的情况。Process函数是TrafficLightProtectedStageIntersectionCruise类的一个成员函数,用于处理车辆在交通灯保护下通过路口的情况。FinishStage函数是TrafficLightProtectedStageIntersectionCruise类的另一个成员函数,用于完成该阶段。TrafficLightProtectedContext结构体是TrafficLightProtectedStageIntersectionCruise类中使用的一个结构体。

最后看traffic_light_protected_scenario;

namespace apollo {
namespace planning {
namespace scenario {
namespace traffic_light {
// stage context
struct TrafficLightProtectedContext {
  ScenarioTrafficLightProtectedConfig scenario_config;
  std::vector<std::string> current_traffic_light_overlap_ids;
class TrafficLightProtectedScenario : public Scenario {
 public:
  TrafficLightProtectedScenario(
      const ScenarioConfig& config, const ScenarioContext* context,
      const std::shared_ptr<DependencyInjector>& injector)
      : Scenario(config, context, injector) {}
  void Init() override;
  std::unique_ptr<Stage> CreateStage(
      const ScenarioConfig::StageConfig& stage_config,
      const std::shared_ptr<DependencyInjector>& injector);
  TrafficLightProtectedContext* GetContext() { return &context_; }
 private:
  static void RegisterStages();
  bool GetScenarioConfig();
 private:
  static apollo::common::util::Factory<
      StageType, Stage,
      Stage* (*)(const ScenarioConfig::StageConfig& stage_config,
                 const std::shared_ptr<DependencyInjector>& injector)>
      s_stage_factory_;
  bool init_ = false;
  TrafficLightProtectedContext context_;
}  // namespace traffic_light
}  // namespace scenario
}  // namespace planning
}  // namespace apollo

这段代码是Apollo Auto中的一个交通灯保护场景的实现。TrafficLightProtectedScenario类是该场景的一个实现,用于处理车辆在交通灯保护下通过路口的情况。TrafficLightProtectedContext结构体是TrafficLightProtectedScenario类中使用的一个结构体,用于存储场景中的一些信息。CreateStage函数是TrafficLightProtectedScenario类的一个成员函数,用于创建场景中的阶段。Init函数是TrafficLightProtectedScenario类的另一个成员函数,用于初始化场景。
这段代码是TrafficLightProtectedScenario类的实现,它包括了初始化函数Init()和RegisterStages()函数。Init()函数初始化了场景,并且获取了当前交通灯的信息。RegisterStages()函数注册了两个阶段:TRAFFIC_LIGHT_PROTECTED_APPROACH和TRAFFIC_LIGHT_PROTECTED_INTERSECTION_CRUISE。

这个代码片段中,traffic_light_status是一个planning_status结构体中的traffic_light成员变量,它包含了当前交通灯的信息。如果当前交通灯的id为空,那么就会输出错误信息并返回。如果当前交通灯的id不为空,那么就会将当前交通灯的id存储到context_.current_traffic_light_overlap_ids中。
这个代码片段中还使用了HDMapUtil::BaseMap().GetSignalById()函数来获取交通灯的信息。HDMapUtil是一个工具类,它提供了一些与HDMap相关的函数。GetSignalById()函数可以根据交通灯的id获取交通灯的信息。

5以一个stage为例分析stge如何注册task,以及一个场景如何工作

task的注册发生在的注册发生在stage对象的简历阶段,stage的构造函数继承了stage类的构造函数,在建立对象时读取配置文件,并对当前stage包含的task进行注册;
stage的构造函数对stage的构造函数进行继承;
stage的构造函数读取配置文件,并且注册每个task,并保存在全局变量task_list_中;
Process()函数执行主要的规划逻辑,另外一个重要的函数是PlanOnReferenceLine(),在这个函数中实现了对每个task的依次调用
下面的图是task的被调用的逻辑
在这里插入图片描述

6、交规决策的运行逻辑

HWP 功能仅针对高度结构化道路设计,限制使用环境为严格限制出入、有明确的隔离设置区分对向交通、无立体或水平交叉路口、无交通灯等设施的高速公路或城市快速路(不包含出、入匝道功能); HWP 功能能够识别可以依法取得牌照,合法上高速公路行驶的普通乘用车、商用车等车辆目标;对于其他类型的障碍物,HWP 功能会尽可能的按照安全性策略进行规避并发出警报,但受限于车载感知能力,对于无法识别(路面坑洼等)、近距离识别(石块、临时施工等)或突发情况(山区落石等),HWP 功能仍存在无响应或响应不及时的风险。
目前Apollo已经更新到6.0,整体架构和功能都已经很成熟了,Apollo开源无疑极大的提高了自动驾驶行业的整体水平,所以对于研究自动驾驶的人来说,apollo可以说是入场券,最近应该是我比较轻松的时间,准备系统的学习一下Apollo的代码和思想,过完年去新公司应该会比较忙了。 1. Apollo与ROS Apollo项目基于ROS,但是对其进行了改造,主要包括下面三个方面: 通信性能优化:将通过共享内存来减少数据拷贝,以提升通信性能。 去中心化网络拓扑:Apollo...
自动驾驶落地感知算法是指在自动驾驶系统中用于感知车辆周围环境的算法。这些算法通过使用传感器数据,如摄像头、激光雷达和雷达等,来识别、检测和跟踪道路上的障碍物、交通标志、车道线等,并将这些信息提供给决策和规划模块,以实现自动驾驶车辆的安全行驶。感知算法的主要目标是提供准确、实时的环境感知结果,并能够适应不同的道路和交通场景。例如,判断直线相交、点和三角形关系、三点求曲率等几何问题可能会在自动驾驶感知算法中应用。这些算法的发展和优化是实现可靠自动驾驶技术的关键之一。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [自动驾驶感知算法实战11——多传感器融合感知方案详解](https://blog.csdn.net/Charmve/article/details/127989581)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] - *2* *3* [自动驾驶算法/规划决策控制算法面经汇总、学习路线、面经心得](https://blog.csdn.net/qq_41667348/article/details/127514574)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]
CSDN-Ada助手: 非常感谢博主的第六篇文章,对于自动驾驶面试的总结真的很有帮助。恭喜博主一直坚持创作,分享自己的经验给大家。希望博主能够继续写下去,分享更多的面试经验和技巧。也许可以考虑写一些关于技术实践或者行业趋势的文章,让我们更深入地了解自动驾驶技术的发展。再次感谢博主的分享和努力! CSDN 会根据你创作的博客的质量,给予优秀的博主博客红包奖励。请关注 https://bbs.csdn.net/forums/csdnnews?typeId=116148&utm_source=csdn_ai_ada_blog_reply6 看奖励名单。