1. hdmap文件夹

1.1 adapter文件夹功能介绍

入口为opendrive_adapter.cc(严格来说不叫入口,这部分代码只是API,供其他模块调用)。opendrive_adapter调用xml_parser下的各种xxx_xml_parser类的方法parse()将高精地图(.xml格式文件)解析为xxxInternal格式。后调用proto_origanizer类中的方法将xxxInternal格式的数据解析为ProtoData格式的数据。

xxxInternal数据格式在common_define.h中定义,以RoadInternal为例子:

using PbRoad = apollo::hdmap::Road;...struct RoadInternal {std::string id;PbRoad road;bool in_junction;std::string junction_id;std::string type;std::vector<RoadSectionInternal> sections;std::vector<TrafficLightInternal> traffic_lights;// std::vector<RSUInternal> rsus;std::vector<StopSignInternal> stop_signs;std::vector<YieldSignInternal> yield_signs;std::vector<PbCrosswalk> crosswalks;std::vector<PbClearArea> clear_areas;std::vector<PbSpeedBump> speed_bumps;std::vector<StopLineInternal> stop_lines;std::vector<PbParkingSpace> parking_spaces;std::vector<PbPNCJunction> pnc_junctions;RoadInternal() : in_junction(false) { junction_id = ""; }
};

ProtoData数据格式定义在proto_origanizer.h中:

struct ProtoData {PbHeader header;std::unordered_map<std::string, PbLane> pb_lanes;std::unordered_map<std::string, PbRoad> pb_roads;std::unordered_map<std::string, PbCrosswalk> pb_crosswalks;std::unordered_map<std::string, PbClearArea> pb_clear_areas;std::unordered_map<std::string, PbSpeedBump> pb_speed_bumps;std::unordered_map<std::string, PbJunction> pb_junction;std::unordered_map<std::string, PbSignal> pb_signals;std::unordered_map<std::string, PbStopSign> pb_stop_signs;std::unordered_map<std::string, PbYieldSign> pb_yield_signs;std::unordered_map<std::string, PbOverlap> pb_overlaps;std::unordered_map<std::string, PbJunction> pb_junctions;std::unordered_map<std::string, StopLineInternal> pb_stop_lines;std::unordered_map<std::string, PbParkingSpace> pb_parking_spaces;std::unordered_map<std::string, PbPNCJunction> pb_pnc_junctions;std::unordered_map<std::string, PbRSU> pb_rsus;
};

入口函数为OpendriveAdapter::LoadData(),通过调用RoadsXmlParser::Parse()来将xml文件中与road相关的标签信息存入RoadInternal结构中,涉及RoadInternal的id、road的id、junction_id、type等信息。通过顺便调用LanesXmlParser::Parse()来填入sections的相关信息。最后调用Parse_road_objects()和Parse_road_signals()来将RoadInternal中包含的traffic_lights、...pnc_junctions信息进行填充。

std::vector<RoadInternal> roads;status = RoadsXmlParser::Parse(*root_node, &roads);if (!status.ok()) {AERROR << "fail to parse opendrive road, " << status.error_message();return false;}...
Status RoadsXmlParser::Parse(const tinyxml2::XMLElement& xml_node,std::vector<RoadInternal>* roads) {CHECK_NOTNULL(roads);auto road_node = xml_node.FirstChildElement("road");while (road_node) {// road attributesstd::string id;std::string junction_id;int checker = UtilXmlParser::QueryStringAttribute(*road_node, "id", &id);checker += UtilXmlParser::QueryStringAttribute(*road_node, "junction",&junction_id);if (checker != tinyxml2::XML_SUCCESS) {std::string err_msg = "Error parsing road attributes";return Status(apollo::common::ErrorCode::HDMAP_DATA_ERROR, err_msg);}RoadInternal road_internal;road_internal.id = id;road_internal.road.mutable_id()->set_id(id);if (IsRoadBelongToJunction(junction_id)) {road_internal.road.mutable_junction_id()->set_id(junction_id);}std::string type;checker = UtilXmlParser::QueryStringAttribute(*road_node, "type", &type);if (checker != tinyxml2::XML_SUCCESS) {// forward compatibility with old datatype = "CITYROAD";}PbRoadType pb_road_type;RETURN_IF_ERROR(to_pb_road_type(type, &pb_road_type));road_internal.road.set_type(pb_road_type);// lanesRETURN_IF_ERROR(LanesXmlParser::Parse(*road_node, road_internal.id,&road_internal.sections));// objectsParse_road_objects(*road_node, &road_internal);// signalsParse_road_signals(*road_node, &road_internal);roads->push_back(road_internal);road_node = road_node->NextSiblingElement("road");}return Status::OK();
}...
void RoadsXmlParser::Parse_road_objects(const tinyxml2::XMLElement& xml_node,RoadInternal* road_info) {CHECK_NOTNULL(road_info);// objectsauto sub_node = xml_node.FirstChildElement("objects");if (sub_node != nullptr) {// stop lineObjectsXmlParser::ParseStopLines(*sub_node, &road_info->stop_lines);// crosswalksObjectsXmlParser::ParseCrosswalks(*sub_node, &road_info->crosswalks);// clearareasObjectsXmlParser::ParseClearAreas(*sub_node, &road_info->clear_areas);// speed_bumpsObjectsXmlParser::ParseSpeedBumps(*sub_node, &road_info->speed_bumps);// parking_spacesObjectsXmlParser::ParseParkingSpaces(*sub_node, &road_info->parking_spaces);// pnc_junctionsObjectsXmlParser::ParsePNCJunctions(*sub_node, &road_info->pnc_junctions);}
}

在成功将xml中的road相关标签信息存入RoadInternal数据结构后,opendrive_adapter::LoadData()在最后调用proto_organizer.GetRoadElements(&roads);来将RoadInternal的数据解析为ProtoData数据格式,用哈希表的方式来对lane、road、crossroad等地图元素进行管理。如下面代码所示,通过遍历每个RoadInternal对pb_lanes、pb_roads、pb_crosswalks等ProtoData中定义的unordered_map对象进行赋值。

void ProtoOrganizer::GetRoadElements(std::vector<RoadInternal>* roads) {for (auto& road_internal : *roads) {// lanesfor (auto& section_internal : road_internal.sections) {for (auto& lane_internal : section_internal.lanes) {std::string lane_id = lane_internal.lane.id().id();proto_data_.pb_lanes[lane_id] = lane_internal.lane;section_internal.section.add_lane_id()->set_id(lane_id);}(*road_internal.road.add_section()) = section_internal.section;proto_data_.pb_roads[road_internal.id] = road_internal.road;}// crosswalksfor (auto& crosswalk : road_internal.crosswalks) {proto_data_.pb_crosswalks[crosswalk.id().id()] = crosswalk;}// parking_spacesfor (auto& parking_space : road_internal.parking_spaces) {proto_data_.pb_parking_spaces[parking_space.id().id()] = parking_space;}// clear areasfor (auto& clear_area : road_internal.clear_areas) {proto_data_.pb_clear_areas[clear_area.id().id()] = clear_area;}// speed_bumpfor (auto& speed_bump : road_internal.speed_bumps) {proto_data_.pb_speed_bumps[speed_bump.id().id()] = speed_bump;}// stop linesfor (auto& stop_line_internal : road_internal.stop_lines) {proto_data_.pb_stop_lines[stop_line_internal.id] = stop_line_internal;}// traffic_lightsfor (auto& traffic_light_internal : road_internal.traffic_lights) {auto& traffic_light = traffic_light_internal.traffic_light;for (auto stop_line_id : traffic_light_internal.stop_line_ids) {CHECK_GT(proto_data_.pb_stop_lines.count(stop_line_id), 0U);auto& stop_line_curve = proto_data_.pb_stop_lines[stop_line_id].curve;(*traffic_light.add_stop_line()) = stop_line_curve;}proto_data_.pb_signals[traffic_light.id().id()] = traffic_light;}// stop signsfor (auto& stop_sign_internal : road_internal.stop_signs) {auto& stop_sign = stop_sign_internal.stop_sign;for (auto stop_line_id : stop_sign_internal.stop_line_ids) {CHECK_GT(proto_data_.pb_stop_lines.count(stop_line_id), 0U);auto& stop_line_curve = proto_data_.pb_stop_lines[stop_line_id].curve;(*stop_sign.add_stop_line()) = stop_line_curve;}proto_data_.pb_stop_signs[stop_sign.id().id()] = stop_sign;}// yield signsfor (auto& yield_sign_internal : road_internal.yield_signs) {auto& yield_sign = yield_sign_internal.yield_sign;for (auto stop_line_id : yield_sign_internal.stop_line_ids) {CHECK_GT(proto_data_.pb_stop_lines.count(stop_line_id), 0U);auto& stop_line_curve = proto_data_.pb_stop_lines[stop_line_id].curve;(*yield_sign.add_stop_line()) = stop_line_curve;}proto_data_.pb_yield_signs[yield_sign.id().id()] = yield_sign;}// pnc junctionsfor (auto& pnc_junction : road_internal.pnc_junctions) {proto_data_.pb_pnc_junctions[pnc_junction.id().id()] = pnc_junction;}}
}

最后调用proto_organizer.OutputData(pb_map)来可以打印出各个道路元素的个数。pb_map为apollo::hdmap::Map类型的对象。

总结:

上面以从xml获取road相关信息举例,总体思路为将xml信息解析为xxxInternal格式,然后再将xxxInternal数据格式转化为ProtoData格式,统一用哈希表来对所有map元素进行管理。为啥经过这个中间步骤不是很懂,可能是方便代码管理吧,一下子将xml元素直接全部转化为ProtoData结构的信息可能代码会很混乱。

1.2 剩余文件功能介绍(hdmap_common、 hdmap_impl、 hdmap_util和hdmap)

上图中的类基本都是地图元素管理的API,由其他模块调用。其中, hdmap_util和hdmap两个文件基本都是接口函数,真正干活的代码在hdmap_impl和hdmap_common中。

hdmap_common.h和hdmap_common.c中,主要为每种道路元素所具备API,以道路元素Lane为例,在hdmap_common.h中定义了LaneInfo类,在此类中定义了某个lane所具备的相关成员函数,例如获取该lane的heading、segments、该lane上所有的singal 以及其他重叠区域等方法。

class LaneInfo {public:explicit LaneInfo(const Lane &lane);const Id &id() const { return lane_.id(); }const Id &road_id() const { return road_id_; }const Id &section_id() const { return section_id_; }const Lane &lane() const { return lane_; }const std::vector<apollo::common::math::Vec2d> &points() const {return points_;}const std::vector<apollo::common::math::Vec2d> &unit_directions() const {return unit_directions_;}double Heading(const double s) const;double Curvature(const double s) const;const std::vector<double> &headings() const { return headings_; }const std::vector<apollo::common::math::LineSegment2d> &segments() const {return segments_;}const std::vector<double> &accumulate_s() const { return accumulated_s_; }const std::vector<OverlapInfoConstPtr> &overlaps() const { return overlaps_; }const std::vector<OverlapInfoConstPtr> &cross_lanes() const {return cross_lanes_;}const std::vector<OverlapInfoConstPtr> &signals() const { return signals_; }const std::vector<OverlapInfoConstPtr> &yield_signs() const {return yield_signs_;}const std::vector<OverlapInfoConstPtr> &stop_signs() const {return stop_signs_;}const std::vector<OverlapInfoConstPtr> &crosswalks() const {return crosswalks_;}const std::vector<OverlapInfoConstPtr> &junctions() const {return junctions_;}const std::vector<OverlapInfoConstPtr> &clear_areas() const {return clear_areas_;}const std::vector<OverlapInfoConstPtr> &speed_bumps() const {return speed_bumps_;}const std::vector<OverlapInfoConstPtr> &parking_spaces() const {return parking_spaces_;}const std::vector<OverlapInfoConstPtr> &pnc_junctions() const {return pnc_junctions_;}double total_length() const { return total_length_; }using SampledWidth = std::pair<double, double>;const std::vector<SampledWidth> &sampled_left_width() const {return sampled_left_width_;}const std::vector<SampledWidth> &sampled_right_width() const {return sampled_right_width_;}void GetWidth(const double s, double *left_width, double *right_width) const;double GetWidth(const double s) const;double GetEffectiveWidth(const double s) const;const std::vector<SampledWidth> &sampled_left_road_width() const {return sampled_left_road_width_;}const std::vector<SampledWidth> &sampled_right_road_width() const {return sampled_right_road_width_;}void GetRoadWidth(const double s, double *left_width,double *right_width) const;double GetRoadWidth(const double s) const;bool IsOnLane(const apollo::common::math::Vec2d &point) const;bool IsOnLane(const apollo::common::math::Box2d &box) const;apollo::common::PointENU GetSmoothPoint(double s) const;double DistanceTo(const apollo::common::math::Vec2d &point) const;double DistanceTo(const apollo::common::math::Vec2d &point,apollo::common::math::Vec2d *map_point, double *s_offset,int *s_offset_index) const;apollo::common::PointENU GetNearestPoint(const apollo::common::math::Vec2d &point, double *distance) const;bool GetProjection(const apollo::common::math::Vec2d &point,double *accumulate_s, double *lateral) const;private:friend class HDMapImpl;friend class RoadInfo;void Init();void PostProcess(const HDMapImpl &map_instance);void UpdateOverlaps(const HDMapImpl &map_instance);double GetWidthFromSample(const std::vector<LaneInfo::SampledWidth> &samples,const double s) const;void CreateKDTree();void set_road_id(const Id &road_id) { road_id_ = road_id; }void set_section_id(const Id &section_id) { section_id_ = section_id; }private:const Lane &lane_;std::vector<apollo::common::math::Vec2d> points_;std::vector<apollo::common::math::Vec2d> unit_directions_;std::vector<double> headings_;std::vector<apollo::common::math::LineSegment2d> segments_;std::vector<double> accumulated_s_;std::vector<std::string> overlap_ids_;std::vector<OverlapInfoConstPtr> overlaps_;std::vector<OverlapInfoConstPtr> cross_lanes_;std::vector<OverlapInfoConstPtr> signals_;std::vector<OverlapInfoConstPtr> yield_signs_;std::vector<OverlapInfoConstPtr> stop_signs_;std::vector<OverlapInfoConstPtr> crosswalks_;std::vector<OverlapInfoConstPtr> junctions_;std::vector<OverlapInfoConstPtr> clear_areas_;std::vector<OverlapInfoConstPtr> speed_bumps_;std::vector<OverlapInfoConstPtr> parking_spaces_;std::vector<OverlapInfoConstPtr> pnc_junctions_;double total_length_ = 0.0;std::vector<SampledWidth> sampled_left_width_;std::vector<SampledWidth> sampled_right_width_;std::vector<SampledWidth> sampled_left_road_width_;std::vector<SampledWidth> sampled_right_road_width_;std::vector<LaneSegmentBox> segment_box_list_;std::unique_ptr<LaneSegmentKDTree> lane_segment_kdtree_;Id road_id_;Id section_id_;
};
using LaneSegmentBox =ObjectWithAABox<LaneInfo, apollo::common::math::LineSegment2d>;
using LaneSegmentKDTree = apollo::common::math::AABoxKDTree2d<LaneSegmentBox>;

在hdmap_impl.h中则实现了HDMapImpl类,该类主要通过哈希表实现了对各种各种道路元素的管理,大多数成员函数为获取某个位置,一定范围内的道路元素有哪些。

Apollo Map模块解析相关推荐

  1. Apollo map模块地图、地图格式以及地图元素介绍

    Apollomap模块入门 一.map 生成流程 二.map 介绍 坐标 车道 其中重点介绍车道与路口部分. 道路Road 车道Lane 路口Junction 获取高精度地图元素 一.map 生成流程 ...

  2. 「Apollo」百度Apollo感知模块(perception)红绿灯检测代码完整+详细解析

    1 背景 最近在读apollo感知模块下的红绿灯检测,apollo框架思路清晰,风格规范,值得多读.直接上代码文件:trafficlights_perception_component.cc traf ...

  3. Apollo Routing模块源代码分析

    严正声明:本文系作者davidhopper原创,未经允许,严禁转载! Apollo Routing模块位于命名空间:apollo::routing,其作用在简单意义上可以理解为实现无人车软件系统内部的 ...

  4. Nginx 静态文件服务器搭建及autoindex模块解析

    ngx_http_autoindex_module ngx_http_autoindex_module模块处理以斜杠字符('/')结尾的请求,并生成目录列表. 当ngx_http_index_modu ...

  5. Apollo planning lane_change_decider解析

    PathReuseDecider 是lanefollow 场景下,所调用的第 1 个 task,它的作用主要是对车辆换道状态进行管理,即对车辆换道状态(IN_CHANGE_LANE 换道中.CHANG ...

  6. cuDNN 功能模块解析

    cuDNN 功能模块解析 Abstract 本cuDNN 8.0.4开发人员指南概述了cuDNN功能,如可自定义的数据布局.支持灵活的dimension ordering,striding,4D张量的 ...

  7. 实现一个webpack模块解析器

    最近在学习 webpack源码,由于源码比较复杂,就先梳理了一下整体流程,就参考官网的例子,手写一个最基本的 webpack 模块解析器. 代码很少,github地址:手写webpack模块解析器 整 ...

  8. python中json模块_Python使用内置json模块解析json格式数据的方法

    本文实例讲述了Python使用内置json模块解析json格式数据的方法.分享给大家供大家参考,具体如下: Python中解析json字符串非常简单,直接用内置的json模块就可以,不需要安装额外的模 ...

  9. TypeScript 素描 - 模块解析、声明合并

    模块解析 模块解析有两种方式 相对方式  也就是以/或 ./或-/开头的,比如import jq  from "/jq" 非相对方式  比如 import model  from ...

最新文章

  1. 剑指offer_第17题_树的子结构_Python
  2. ZooKeeper伪分布式集群安装及使用
  3. 那些年我们一起玩DIY总结出的经验——网络篇
  4. #ifdef ...#else...#endif等条件编译用法
  5. 操作系统:连续分配、分页和分段三种存储分配机制的优缺点
  6. String内容不能改变的理解 String的值不能修改的理解
  7. aspcms各版本漏洞0day集合
  8. 内存分析_Redis内存爆炸增长?你需要知道这一套Redis内存分析方法
  9. 36 岁程序员应聘被公司领导直接拒绝;字节跳动:公司暂不具备上市条件;财务软件 bug 致数百人被错误定罪|极客头条...
  10. 阿里:“马云从未转让和退出”;华为三星和解;拼多多回应传闻 | 极客头条...
  11. 使用cronolog 分割Tomcat日志 Apache日志
  12. 2018百度之星程序设计大赛 - 资格赛 P1006三原色图(MST,并查集)
  13. Android动态加载字节码
  14. Stata数据处理:清洗CFPS数据库
  15. ​【火星传媒报道】李笑来归来:不做韭菜的生意
  16. Apple Compressor 4.4.4 中文特别版 Mac 电影视频后期制作工具
  17. 记一次对PUBG吃鸡外挂病毒的反制过程
  18. 美国如何保护关键信息基础设施
  19. 蓝牙map协议源码解析
  20. 【tableau】4个基本图表

热门文章

  1. Word 中如何标记修订?如何去掉修订标记只显示最终状态?
  2. 怎样把文字调成竖排_如何把横向文字变竖排文字?
  3. 重磅!华为更新职业认证架构刷新和重认证规则
  4. ISIC-2017 和 PH2 皮肤镜图像分割数据集
  5. FPGA数字信号处理(六)直接型IIR滤波器Verilog设计
  6. 详解Spire.PDF中的坐标体系及应用
  7. Android文件浏览器的开发
  8. 深度学习硬件架构简述
  9. 计算机病毒对计算机应用的影响,计算机应用技术对信息化的影响-计算机病毒论文-计算机论文(8页)-原创力文档...
  10. RDBMS相关概念和注意事项(一)