百度apollo自动驾驶planning代码学习-Apollo\modules\planning\common\PathDecision类代码详解

70 篇文章 225 订阅
42 篇文章 7 订阅

概述

*跳过Apollo\modules\planning\common\PathDecision类,其主要针对非结构化道路,如泊车等?开放空间信息类,目前只专注于onlaneplanning

PathDecision类是apollo planning模块下modules\planning\common\path_decision.cc/.h实现

从类名来看,应该是路径决策类。

从代码来看PathDecision类主要是实现:

储存/增加障碍物类对象到障碍物列表;
增加针对某个障碍物横纵向决策;
设置某个障碍物里的ST边界;
将针对目标物体的停车决策与主停车决策融合;(主停车决策可能是针对车道终点,道路终点停止线等,针对目标的停车决策是临时的)

后续结合其他代码一起看,可能会对一些细节的概念理解更加清楚。

path_decision.h

#pragma once

#include <limits>
#include <string>

#include "modules/planning/common/indexed_list.h"
#include "modules/planning/common/obstacle.h"
#include "modules/planning/proto/decision.pb.h"

namespace apollo {
namespace planning {

/**
 * @class PathDecision 路径决策类
 *
 * @brief 路径决策类在一条路径上表示了所有障碍物
 */
class PathDecision {
 public:
  //默认构造函数
  PathDecision() = default;

  //增加一个障碍物对象,在类数据成员障碍物列表obstacles_里增加一个障碍物对象
  Obstacle *AddObstacle(const Obstacle &obstacle);

  //返回类数据成员,障碍物列表,里面储存着id和障碍物对象的映射关系,按对储存
  const IndexedList<std::string, Obstacle> &obstacles() const;

  //增加横向决策,输入参数是tag字符串,障碍物id,给定目标决策类型
  //ObjectDecisionType类由modules\planning\proto\decision.proto定义生成的message类,包括 ignore/stop/follow/yield/...,对目标物体的决策类型
  //其实就是把输入参数的决策类型,增加到这个id的障碍物对象的数据成员决策列表里
  bool AddLateralDecision(const std::string &tag, const std::string &object_id,
                          const ObjectDecisionType &decision);
  bool AddLongitudinalDecision(const std::string &tag,
                               const std::string &object_id,
                               const ObjectDecisionType &decision);
//根据输入的障碍物id,去类成员障碍物列表中跟据id返回对应的障碍物对象,不可修改?
  const Obstacle *Find(const std::string &object_id) const;

//根据输入的感知障碍物id(感知id难道和障碍物Id不一样?)去类数据成员障碍物列表中根据输入参数的感知id去返回相应的感知障碍物对象
  const perception::PerceptionObstacle *FindPerceptionObstacle(
      const std::string &perception_obstacle_id) const;

//根据输入的障碍物id,去类成员障碍物列表中跟据id返回对应的障碍物对象,可修改?
  Obstacle *Find(const std::string &object_id);

//设置ST边界,根据输入的障碍物Id,用这个障碍物去修改自车的ST边界,修改后的边界存放在boundary
  void SetSTBoundary(const std::string &id, const STBoundary &boundary);
  
  //擦除ST边界
  void EraseStBoundaries();
  
  //返回类数据成员
  //主停止类 是由modules\planning\proto\decision.proto定义的message类生成
  //里面主要包含停止点,停止原因,停止航向角等信息
  MainStop main_stop() const { return main_stop_; }
  //返回类数据成员 停止参考线s
  double stop_reference_line_s() const { return stop_reference_line_s_; }
  //将对于障碍物做出的停车决策与主停止决策混合?
  bool MergeWithMainStop(const ObjectStop &obj_stop, const std::string &obj_id,
                         const ReferenceLine &ref_line,
                         const SLBoundary &adc_sl_boundary);

 private:
  //类成员 障碍物列表
  IndexedList<std::string, Obstacle> obstacles_;
  //主停止类对象
  MainStop main_stop_;
  //停止的参考线的s初始化为一个非常大的数,就是double表示的最大的数
  double stop_reference_line_s_ = std::numeric_limits<double>::max();
};

}  // namespace planning
}  // namespace apollo

path_decision.cc

#include "modules/planning/common/path_decision.h"

#include "modules/common/configs/vehicle_config_helper.h"
#include "modules/common/util/util.h"
#include "modules/perception/proto/perception_obstacle.pb.h"

namespace apollo {
namespace planning {
//在路径决策类数据成员障碍物列表里增加一个障碍物对象
Obstacle *PathDecision::AddObstacle(const Obstacle &obstacle) {
  return obstacles_.Add(obstacle.Id(), obstacle);
}

//返回PathDecision类的数据成员障碍物列表
const IndexedObstacles &PathDecision::obstacles() const { return obstacles_; }
//去PathDecision类的数据成员障碍物列表里根据给定的id返回相应的障碍物对象,返回的对象可以修改
Obstacle *PathDecision::Find(const std::string &object_id) {
  return obstacles_.Find(object_id);
}

//去PathDecision类的数据成员障碍物列表里根据给定的id返回相应的障碍物对象,返回的对象不可以修改
const Obstacle *PathDecision::Find(const std::string &object_id) const {
  return obstacles_.Find(object_id);
}

//去障碍物列表里寻找和给定的感知障碍物id相同的感知障碍物对象,难道感知障碍物id和障碍物id不同?
const perception::PerceptionObstacle *PathDecision::FindPerceptionObstacle(
    const std::string &perception_obstacle_id) const {
  for (const auto *obstacle : obstacles_.Items()) {
    if (std::to_string(obstacle->Perception().id()) == perception_obstacle_id) {
      return &(obstacle->Perception());
    }
  }

  return nullptr;
}

//根据给定的障碍物id,去障碍物列表里找到障碍物对象,并用这个障碍物对象去访问其自身的障碍物类的成员函数set_path_st_boundary,根据输入参数给定的ST边界去设置障碍物的类成员path_st_boundary_路径st边界
void PathDecision::SetSTBoundary(const std::string &id,
                                 const STBoundary &boundary) {
  auto *obstacle = obstacles_.Find(id);

  if (!obstacle) {
    AERROR << "Failed to find obstacle : " << id;
    return;
  } else {
    obstacle->set_path_st_boundary(boundary);
  }
}

//从类里储存的障碍物列表获取给定id的障碍物对象,然后针对这个障碍物对象增加一个横向的决策,增加的横向决策的tag和决策都是由输入参数传入
//目标决策类型包括:stop/follow/yield/...
bool PathDecision::AddLateralDecision(const std::string &tag,
                                      const std::string &object_id,
                                      const ObjectDecisionType &decision) {
  auto *obstacle = obstacles_.Find(object_id);
  if (!obstacle) {
    AERROR << "failed to find obstacle";
    return false;
  }
  obstacle->AddLateralDecision(tag, decision);
  return true;
}

//擦除ST边界,遍历PathDecision类数据成员障碍物列表,清空每个障碍物对象里储存的ST边界
void PathDecision::EraseStBoundaries() {
  for (const auto *obstacle : obstacles_.Items()) {
    auto *obstacle_ptr = obstacles_.Find(obstacle->Id());
    obstacle_ptr->EraseStBoundary();
  }
}

//针对给定的障碍物Id对应的障碍物对象,障碍物对象增加一个纵向决策,纵向决策的目标决策类型也是由输入参数decision给定
bool PathDecision::AddLongitudinalDecision(const std::string &tag,
                                           const std::string &object_id,
                                           const ObjectDecisionType &decision) {
  auto *obstacle = obstacles_.Find(object_id);
  if (!obstacle) {
    AERROR << "failed to find obstacle";
    return false;
  }
  obstacle->AddLongitudinalDecision(tag, decision);
  return true;
}

//将输入参数的针对目标的停止与主停止决策融合
//输入参数目标停止类对象,待融合的
//输入参数 目标障碍物id
//输入参数 参考线类对象
//输入参数 自车的sl边界
bool PathDecision::MergeWithMainStop(const ObjectStop &obj_stop,
                                     const std::string &obj_id,
                                     const ReferenceLine &reference_line,
                                     const SLBoundary &adc_sl_boundary) {
  //获取目标停止类的停止点
  common::PointENU stop_point = obj_stop.stop_point();
  //定义一个停止线sl坐标
  common::SLPoint stop_line_sl;
  //输入参数的参考线访问其成员函数,将停止点的xy坐标转化为停止点的SL坐标
  //SL坐标都是相对参考线的横纵向,即frenet系
  reference_line.XYToSL(stop_point, &stop_line_sl);

  //获取停止点sl坐标的frenet系纵坐标s
  double stop_line_s = stop_line_sl.s();
  //如果目标停止点的s坐标小于0或目标停止点的s比道路参考线的长度还要长那么就忽略这个物体,直接返回false
  if (stop_line_s < 0.0 || stop_line_s > reference_line.Length()) {
    AERROR << "Ignore object:" << obj_id << " fence route_s[" << stop_line_s
           << "] not in range[0, " << reference_line.Length() << "]";
    return false;
  }

  //检查停止点纵坐标s vs 自车s,如果目标停止点s比主停止更远的话忽略,直接返回
  const auto &vehicle_config = common::VehicleConfigHelper::GetConfig();
  stop_line_s = std::fmax(
      stop_line_s, adc_sl_boundary.end_s() -
                       vehicle_config.vehicle_param().front_edge_to_center());

  if (stop_line_s >= stop_reference_line_s_) {
    ADEBUG << "stop point is farther than current main stop point.";
    return false;
  }

//如果上面都没返回,那么就用针对目标对象的停止点代替主停止点
//重新设置主停止点,heading,停止原因等
  main_stop_.Clear();
  main_stop_.set_reason_code(obj_stop.reason_code());
  main_stop_.set_reason("stop by " + obj_id);
  main_stop_.mutable_stop_point()->set_x(obj_stop.stop_point().x());
  main_stop_.mutable_stop_point()->set_y(obj_stop.stop_point().y());
  main_stop_.set_stop_heading(obj_stop.stop_heading());
  stop_reference_line_s_ = stop_line_s;

  ADEBUG << " main stop obstacle id:" << obj_id
         << " stop_line_s:" << stop_line_s << " stop_point: ("
         << obj_stop.stop_point().x() << obj_stop.stop_point().y()
         << " ) stop_heading: " << obj_stop.stop_heading();
  return true;
}

}  // namespace planning
}  // namespace apollo

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
### 回答1: Apollo Planning是一个自动驾驶规划模块,它负责生成自动驾驶车辆的行驶路线和行驶轨迹。该模块的代码主要包括以下几个部分: 1. 地图数据处理:该部分代码主要负责处理地图数据,包括地图的加载、解析和存储等。 2. 车辆状态估计:该部分代码主要负责估计车辆的状态,包括车辆的位置、速度、加速度等。 3. 障碍物检测:该部分代码主要负责检测车辆周围的障碍物,包括车辆前方的障碍物、车辆后方的障碍物等。 4. 路径规划:该部分代码主要负责生成车辆的行驶路线,包括起点、终点、途经点等。 5. 轨迹规划:该部分代码主要负责生成车辆的行驶轨迹,包括车辆的速度、加速度、转向角度等。 总的来说,Apollo Planning代码解读需要对自动驾驶技术有一定的了解,需要熟悉相关的算法和数据结构。同时,还需要对C++编程语言有一定的掌握,能够理解和修改代码。 ### 回答2: Apollo PlanningApollo平台中的一部分,是一种规划算法,用于生成具有速度、加速度、路径跟踪、动态碰撞检测等约束条件的行驶路径。本文将对Apollo Planning中的代码进行解读。 Apollo Planning的核心代码包括两个部分:路径规划器和速度规划器。其中路径规划器的主要任务是在路网中寻找一条从起点到终点的路径,而速度规划器的主要任务则是为规划出的路径生成相应的速度规划和轨迹。 路径规划器中采用的主要算法是基于A*算法的全局规划器和基于Dijkstra算法的局部规划器。全局规划器用于从起点到终点寻找全局路径,而局部规划器则用于在全局路径的基础上进行优化,以生成最终的路径。 在速度规划器中,采用了二次规划、线性插值和基于速度和加速度约束的时间分配等算法,用于根据路网上提供的速度信息和预计的路况等因素生成规划速度和轨迹。 除此之外,还应用了动态碰撞检测算法,用于在行驶过程中实时检测障碍物,并调整行驶路径以避免碰撞。 总之,Apollo Planning代码实现了较为完善的路径规划和速度规划功能,并且综合应用了多种算法和约束条件,使得车辆行驶更加安全、稳定。 ### 回答3: Apollo Planning 代码百度自动驾驶平台 Apollo 中用于路径规划的组件。通过对代码的解读,我们可以了解到路径规划背后的一系列算法和原理。 首先,Apollo Planning 首先需要载入地图信息,以确定行驶的区域和道路网络。这些地图信息包括道路形状、道路宽度、车道数量、速度限制和限制规则等。 然后,Apollo Planning 根据车辆当前位置和目的地位置,通过 A*算法或 Dijkstra 算法等规划出车辆行驶的路径。这一过程中,Apollo Planning 需要考虑各种限制条件,如道路的长度、转弯半径、速度限制、停止标志和交通信号灯等。 接下来,Apollo Planning 将规划出的路径转换为轨迹,以让车辆根据轨迹规划进行动作。这一过程需要考虑车辆的动力学特性,比如加速度、最大速度限制和最大转弯速度等。 在最终生成的行驶轨迹中,需要包含一些基础信息,如轨迹的时间戳、各个点的速度和加速度信息等。这些信息有助于车辆在运行过程中准确地遵守路径规划,并在行驶中做出适时的调整。 总之,Apollo Planning 的核心功能是确定车辆行驶的路线、行驶轨迹和行驶速度等。该组件通过高效的算法和细致的条件考虑,实现自动驾驶车辆的稳定、安全和高效的路径规划。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

wujiangzhu_xjtu

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值