20double ToMPS(
double speed) {
return speed * 1000.0 / 3600.0; }
21bool IsReferenceLane(
int lane_id) {
return lane_id == 0; }
29 const std::string& road_id,
30 std::vector<RoadSectionInternal>* sections) {
31 CHECK_NOTNULL(sections);
32 const auto lanes_node = xml_node.FirstChildElement(
"lanes");
33 CHECK_NOTNULL(lanes_node);
34 const tinyxml2::XMLElement* sub_node =
35 lanes_node->FirstChildElement(
"laneSection");
36 CHECK_NOTNULL(sub_node);
38 size_t section_cnt = 0;
41 std::string section_id = std::to_string(++section_cnt);
42 section_internal.
id = section_id;
43 section_internal.
section.mutable_id()->set_id(section_id);
47 section_internal.
section.mutable_boundary()->mutable_outer_polygon()));
48 sections->push_back(section_internal);
50 sub_node = sub_node->NextSiblingElement(
"laneSection");
53 CHECK_NE(sections->size(), 0U);
58Status LanesXmlParser::ParseSectionBoundary(
60 CHECK_NOTNULL(boundary);
62 auto boundaries_node = xml_node.FirstChildElement(
"boundaries");
63 if (boundaries_node ==
nullptr) {
64 std::string err_msg =
"Error parse boundaries";
68 auto sub_node = boundaries_node->FirstChildElement(
"boundary");
75 if (checker != tinyxml2::XML_SUCCESS) {
76 std::string err_msg =
"Error parse boundary type";
81 boundary_edge->set_type(boundary_type);
83 sub_node = sub_node->NextSiblingElement(
"boundary");
89Status LanesXmlParser::ToPbBoundaryType(
const std::string& type,
91 CHECK_NOTNULL(boundary_type);
95 if (upper_type ==
"LEFTBOUNDARY") {
97 }
else if (upper_type ==
"RIGHTBOUNDARY") {
106Status LanesXmlParser::ParseLaneSection(
const tinyxml2::XMLElement& xml_node,
107 std::vector<LaneInternal>* lanes) {
108 CHECK_NOTNULL(lanes);
111 const tinyxml2::XMLElement* sub_node = xml_node.FirstChildElement(
"left");
113 sub_node = sub_node->FirstChildElement(
"lane");
115 LaneInternal lane_internal;
117 *(lane_internal.lane.mutable_left_boundary()) =
118 lane_internal.lane.right_boundary();
119 lane_internal.lane.clear_right_boundary();
120 if (lanes->size() > 0) {
121 PbLane& left_neighbor_lane = lanes->back().lane;
122 *(left_neighbor_lane.mutable_right_boundary()) =
125 lanes->push_back(lane_internal);
126 sub_node = sub_node->NextSiblingElement(
"lane");
131 LaneInternal reference_lane_internal;
132 sub_node = xml_node.FirstChildElement(
"center");
133 CHECK_NOTNULL(sub_node);
134 sub_node = sub_node->FirstChildElement(
"lane");
135 CHECK_NOTNULL(sub_node);
137 *(reference_lane_internal.lane.mutable_left_boundary()) =
138 reference_lane_internal.lane.right_boundary();
139 if (lanes->size() > 0) {
140 PbLane& left_neighbor_lane = lanes->back().lane;
141 *(left_neighbor_lane.mutable_right_boundary()) =
146 sub_node = xml_node.FirstChildElement(
"right");
148 sub_node = sub_node->FirstChildElement(
"lane");
149 PbLane* left_neighbor_lane = &reference_lane_internal.lane;
152 LaneInternal lane_internal;
154 *(lane_internal.lane.mutable_left_boundary()) =
155 left_neighbor_lane->right_boundary();
156 lanes->push_back(lane_internal);
157 left_neighbor_lane = &lanes->back().lane;
158 sub_node = sub_node->NextSiblingElement(
"lane");
164Status LanesXmlParser::ParseLane(
const tinyxml2::XMLElement& xml_node,
165 LaneInternal* lane_internal) {
166 CHECK_NOTNULL(lane_internal);
168 PbLane* lane = &lane_internal->lane;
171 int checker = xml_node.QueryIntAttribute(
"id", &
id);
172 if (checker != tinyxml2::XML_SUCCESS) {
173 std::string err_msg =
"Error parse lane id";
178 if (checker != tinyxml2::XML_SUCCESS) {
179 std::string err_msg =
"Error parse lane uid";
182 lane->mutable_id()->set_id(lane_id);
185 std::string lane_type;
187 if (checker != tinyxml2::XML_SUCCESS) {
188 std::string err_msg =
"Error parse lane type.";
192 Status success = ToPbLaneType(lane_type, &pb_lane_type);
194 std::string err_msg =
"Error convert lane type to pb lane type.";
197 lane->set_type(pb_lane_type);
200 const tinyxml2::XMLElement* sub_node = xml_node.FirstChildElement(
"border");
203 ACHECK(lane_boundary !=
nullptr);
207 std::string err_msg =
"Error parse lane border";
210 lane_boundary->set_length(
213 bool is_virtual =
false;
214 std::string virtual_border =
"FALSE";
217 if (checker == tinyxml2::XML_SUCCESS) {
218 if (virtual_border ==
"TRUE") {
222 lane_boundary->set_virtual_(is_virtual);
227 sub_node = sub_node->FirstChildElement(
"borderType");
232 success = ParseLaneBorderMark(*sub_node, &boundary_type);
234 std::string err_msg =
"Error parse lane border type";
237 double s_offset = 0.0;
238 checker = sub_node->QueryDoubleAttribute(
"sOffset", &s_offset);
239 if (checker != tinyxml2::XML_SUCCESS) {
240 std::string err_msg =
"Error parse lane boundary type offset.";
243 auto lane_boundary_type = lane_boundary->add_boundary_type();
244 lane_boundary_type->set_s(s_offset);
245 lane_boundary_type->add_types(boundary_type);
246 sub_node = sub_node->NextSiblingElement(
"borderType");
250 if (IsReferenceLane(
id)) {
255 std::string turn_type;
258 if (checker != tinyxml2::XML_SUCCESS) {
259 std::string err_msg =
"Error parse lane turn type.";
263 success = ToPbTurnType(turn_type, &pb_turn_type);
265 std::string err_msg =
"Error convert turn type to pb turn type.";
268 lane->set_turn(pb_turn_type);
274 sub_node = xml_node.FirstChildElement(
"link");
276 ParseLaneLink(*sub_node, lane);
289 ParseObjectOverlapGroup(xml_node, &lane_internal->overlap_objects);
291 ParseSignalOverlapGroup(xml_node, &lane_internal->overlap_signals);
293 ParseJunctionOverlapGroup(xml_node, &lane_internal->overlap_junctions);
295 ParseLaneOverlapGroup(xml_node, &lane_internal->overlap_lanes);
300Status LanesXmlParser::ParseDirection(
const tinyxml2::XMLElement& xml_node,
303 std::string direction;
306 if (checker != tinyxml2::XML_SUCCESS) {
307 std::string err_msg =
"Error parse lane direction.";
311 Status success = ToPbDirection(direction, &pb_lane_direction);
313 std::string err_msg =
"Error convert direction to pb direction";
316 lane->set_direction(pb_lane_direction);
321Status LanesXmlParser::ParseCenterCurve(
const tinyxml2::XMLElement& xml_node,
324 auto sub_node = xml_node.FirstChildElement(
"centerLine");
326 std::string err_msg =
"Error parse lane center curve";
330 PbCurve* center_curve = lane->mutable_central_curve();
333 std::string err_msg =
"Error parse lane center curve";
342Status LanesXmlParser::ParseSpeed(
const tinyxml2::XMLElement& xml_node,
344 double max_speed = 0.0;
345 auto sub_node = xml_node.FirstChildElement(
"speed");
347 int checker = sub_node->QueryDoubleAttribute(
"max", &max_speed);
348 if (checker != tinyxml2::XML_SUCCESS) {
349 std::string err_msg =
"Error parse lane speed attribute";
352 lane->set_speed_limit(ToMPS(max_speed));
358Status LanesXmlParser::ParseSampleAssociates(
359 const tinyxml2::XMLElement& xml_node,
PbLane* lane) {
361 auto sub_node = xml_node.FirstChildElement(
"sampleAssociates");
362 if (sub_node ==
nullptr) {
363 std::string err_msg =
"Error parse sample associates";
366 sub_node = sub_node->FirstChildElement(
"sampleAssociate");
367 if (sub_node ==
nullptr) {
368 std::string err_msg =
"Error parse sample associate";
373 double left_width = 0.0;
374 double right_width = 0.0;
376 int checker = sub_node->QueryDoubleAttribute(
"sOffset", &s);
377 checker += sub_node->QueryDoubleAttribute(
"leftWidth", &left_width);
378 checker += sub_node->QueryDoubleAttribute(
"rightWidth", &right_width);
379 if (checker != tinyxml2::XML_SUCCESS) {
380 std::string err_msg =
"Error parse lane sample associate attribute";
384 auto left_sample = lane->add_left_sample();
385 left_sample->set_s(s);
386 left_sample->set_width(left_width);
388 auto right_sample = lane->add_right_sample();
389 right_sample->set_s(s);
390 right_sample->set_width(right_width);
392 sub_node = sub_node->NextSiblingElement(
"sampleAssociate");
398Status LanesXmlParser::ParseSingleSideRoadSampleAssociates(
399 const tinyxml2::XMLElement& xml_node,
bool bleft,
PbLane* lane) {
402 auto sub_node = xml_node.FirstChildElement(
403 bleft ?
"leftRoadSampleAssociations" :
"rightRoadSampleAssociations");
404 if (sub_node ==
nullptr) {
405 std::string err_msg =
"Error parse road sample associations";
408 sub_node = sub_node->FirstChildElement(
"sampleAssociation");
409 if (sub_node ==
nullptr) {
410 std::string err_msg =
"Error parse road sample association";
416 int checker = sub_node->QueryDoubleAttribute(
"sOffset", &s);
417 checker += sub_node->QueryDoubleAttribute(
"width", &width);
418 if (checker != tinyxml2::XML_SUCCESS) {
419 std::string err_msg =
"Error parse road sample association attribute";
424 bleft ? lane->add_left_road_sample() : lane->add_right_road_sample();
425 road_sample->set_s(s);
426 road_sample->set_width(width);
428 sub_node = sub_node->NextSiblingElement(
"sampleAssociation");
433Status LanesXmlParser::ParseLeftRoadSampleAssociates(
434 const tinyxml2::XMLElement& xml_node,
PbLane* lane) {
437 return ParseSingleSideRoadSampleAssociates(xml_node,
true, lane);
440Status LanesXmlParser::ParseRightRoadSampleAssociates(
441 const tinyxml2::XMLElement& xml_node,
PbLane* lane) {
444 return ParseSingleSideRoadSampleAssociates(xml_node,
false, lane);
447Status LanesXmlParser::ParseRoadSampleAssociates(
448 const tinyxml2::XMLElement& xml_node,
PbLane* lane) {
451 auto sub_node = xml_node.FirstChildElement(
"roadSampleAssociations");
452 if (sub_node ==
nullptr) {
456 sub_node = sub_node->FirstChildElement(
"sampleAssociation");
457 if (sub_node ==
nullptr) {
458 std::string err_msg =
"Error parse road sample association";
463 double left_width = 0.0;
464 double right_width = 0.0;
466 int checker = sub_node->QueryDoubleAttribute(
"sOffset", &s);
467 checker += sub_node->QueryDoubleAttribute(
"leftWidth", &left_width);
468 checker += sub_node->QueryDoubleAttribute(
"rightWidth", &right_width);
469 if (checker != tinyxml2::XML_SUCCESS) {
470 std::string err_msg =
"Error parse road sample association attribute";
474 auto left_road_sample = lane->add_left_road_sample();
475 left_road_sample->set_s(s);
476 left_road_sample->set_width(left_width);
478 auto right_road_sample = lane->add_right_road_sample();
479 right_road_sample->set_s(s);
480 right_road_sample->set_width(right_width);
482 sub_node = sub_node->NextSiblingElement(
"sampleAssociation");
489Status LanesXmlParser::ParseObjectOverlapGroup(
490 const tinyxml2::XMLElement& xml_node,
491 std::vector<OverlapWithLane>* object_overlaps) {
492 CHECK_NOTNULL(object_overlaps);
494 auto object_overlap = xml_node.FirstChildElement(
"objectOverlapGroup");
495 if (object_overlap) {
496 auto sub_node = object_overlap->FirstChildElement(
"objectReference");
498 std::string object_id;
499 double start_s = 0.0;
503 checker += sub_node->QueryDoubleAttribute(
"startOffset", &start_s);
504 checker += sub_node->QueryDoubleAttribute(
"endOffset", &end_s);
505 if (checker != tinyxml2::XML_SUCCESS) {
506 std::string err_msg =
"Error parse lane object overlap";
510 bool is_merge =
false;
511 checker = sub_node->QueryBoolAttribute(
"isMerge", &is_merge);
512 if (checker != tinyxml2::XML_SUCCESS) {
516 OverlapWithLane overlap_with_lane;
517 overlap_with_lane.object_id = object_id;
518 overlap_with_lane.start_s = start_s;
519 overlap_with_lane.end_s = end_s;
520 overlap_with_lane.is_merge = is_merge;
523 ParseRegionOverlap(*sub_node, &overlap_with_lane.region_overlaps));
525 if (overlap_with_lane.region_overlaps.size() > 0) {
527 *sub_node,
"regionOverlapId", &overlap_with_lane.region_overlap_id);
530 object_overlaps->push_back(overlap_with_lane);
532 sub_node = sub_node->NextSiblingElement(
"objectReference");
538Status LanesXmlParser::ParseSignalOverlapGroup(
539 const tinyxml2::XMLElement& xml_node,
540 std::vector<OverlapWithLane>* signal_overlaps) {
541 CHECK_NOTNULL(signal_overlaps);
543 auto signal_overlap = xml_node.FirstChildElement(
"signalOverlapGroup");
544 if (signal_overlap) {
545 auto sub_node = signal_overlap->FirstChildElement(
"signalReference");
547 std::string object_id;
548 double start_s = 0.0;
552 checker += sub_node->QueryDoubleAttribute(
"startOffset", &start_s);
553 checker += sub_node->QueryDoubleAttribute(
"endOffset", &end_s);
554 if (checker != tinyxml2::XML_SUCCESS) {
555 std::string err_msg =
"Error parse lane signal overlap";
559 bool is_merge =
false;
560 checker = sub_node->QueryBoolAttribute(
"isMerge", &is_merge);
561 if (checker != tinyxml2::XML_SUCCESS) {
565 OverlapWithLane overlap_with_lane;
566 overlap_with_lane.object_id = object_id;
567 overlap_with_lane.start_s = start_s;
568 overlap_with_lane.end_s = end_s;
569 overlap_with_lane.is_merge = is_merge;
571 signal_overlaps->push_back(overlap_with_lane);
573 sub_node = sub_node->NextSiblingElement(
"signalReference");
579Status LanesXmlParser::ParseJunctionOverlapGroup(
580 const tinyxml2::XMLElement& xml_node,
581 std::vector<OverlapWithLane>* junction_overlaps) {
582 CHECK_NOTNULL(junction_overlaps);
584 auto overlap_group = xml_node.FirstChildElement(
"junctionOverlapGroup");
586 auto sub_node = overlap_group->FirstChildElement(
"junctionReference");
588 std::string object_id;
589 double start_s = 0.0;
593 checker += sub_node->QueryDoubleAttribute(
"startOffset", &start_s);
594 checker += sub_node->QueryDoubleAttribute(
"endOffset", &end_s);
595 if (checker != tinyxml2::XML_SUCCESS) {
596 std::string err_msg =
"Error parse lane junction overlap";
600 bool is_merge =
false;
601 checker = sub_node->QueryBoolAttribute(
"isMerge", &is_merge);
602 if (checker != tinyxml2::XML_SUCCESS) {
606 OverlapWithLane overlap_with_lane;
607 overlap_with_lane.object_id = object_id;
608 overlap_with_lane.start_s = start_s;
609 overlap_with_lane.end_s = end_s;
610 overlap_with_lane.is_merge = is_merge;
612 junction_overlaps->push_back(overlap_with_lane);
614 sub_node = sub_node->NextSiblingElement(
"junctionReference");
620Status LanesXmlParser::ParseLaneOverlapGroup(
621 const tinyxml2::XMLElement& xml_node,
622 std::vector<OverlapWithLane>* lane_overlaps) {
623 CHECK_NOTNULL(lane_overlaps);
625 auto overlap_node = xml_node.FirstChildElement(
"laneOverlapGroup");
627 auto sub_node = overlap_node->FirstChildElement(
"laneReference");
630 double start_s = 0.0;
634 checker += sub_node->QueryDoubleAttribute(
"startOffset", &start_s);
635 checker += sub_node->QueryDoubleAttribute(
"endOffset", &end_s);
636 if (checker != tinyxml2::XML_SUCCESS) {
637 std::string err_msg =
"Error parse lane lane overlap";
641 bool is_merge =
false;
642 checker = sub_node->QueryBoolAttribute(
"isMerge", &is_merge);
643 if (checker != tinyxml2::XML_SUCCESS) {
647 OverlapWithLane overlap_with_lane;
648 overlap_with_lane.object_id = lane_id;
649 overlap_with_lane.start_s = start_s;
650 overlap_with_lane.end_s = end_s;
651 overlap_with_lane.is_merge = is_merge;
653 lane_overlaps->push_back(overlap_with_lane);
655 sub_node = sub_node->NextSiblingElement(
"laneReference");
662Status LanesXmlParser::ToPbLaneType(
const std::string& type,
664 CHECK_NOTNULL(lane_type);
668 if (upper_str ==
"NONE") {
670 }
else if (upper_str ==
"DRIVING") {
672 }
else if (upper_str ==
"BIKING") {
674 }
else if (upper_str ==
"PARKING") {
676 }
else if (upper_str ==
"SHOULDER") {
678 }
else if (upper_str ==
"SIDEWALK") {
681 std::string err_msg =
"Error or unsupport lane type:" + type;
688Status LanesXmlParser::ToPbTurnType(
const std::string& type,
690 CHECK_NOTNULL(pb_turn_type);
694 if (upper_str ==
"NOTURN") {
696 }
else if (upper_str ==
"LEFTTURN") {
698 }
else if (upper_str ==
"RIGHTTURN") {
700 }
else if (upper_str ==
"UTURN") {
703 std::string err_msg =
"Error or unsupport turn type:" + type;
710Status LanesXmlParser::ToPbDirection(
const std::string& type,
712 CHECK_NOTNULL(pb_direction);
716 if (upper_str ==
"FORWARD") {
718 }
else if (upper_str ==
"BACKWARD") {
720 }
else if (upper_str ==
"BIDIRECTION") {
723 std::string err_msg =
"Error or unsupport dirction:" + type;
730void LanesXmlParser::ParseLaneLink(
const tinyxml2::XMLElement& xml_node,
734 const tinyxml2::XMLElement* sub_node =
735 xml_node.FirstChildElement(
"predecessor");
740 if (checker == tinyxml2::XML_SUCCESS) {
741 PbID* pb_lane_id = lane->add_predecessor_id();
742 pb_lane_id->set_id(lane_id);
744 sub_node = sub_node->NextSiblingElement(
"predecessor");
747 sub_node = xml_node.FirstChildElement(
"successor");
752 if (checker == tinyxml2::XML_SUCCESS) {
753 PbID* pb_lane_id = lane->add_successor_id();
754 pb_lane_id->set_id(lane_id);
756 sub_node = sub_node->NextSiblingElement(
"successor");
759 sub_node = xml_node.FirstChildElement(
"neighbor");
762 std::string direction;
769 if (checker == tinyxml2::XML_SUCCESS) {
770 if (side ==
"left") {
771 if (direction ==
"same") {
772 lane->add_left_neighbor_forward_lane_id()->set_id(lane_id);
774 lane->add_left_neighbor_reverse_lane_id()->set_id(lane_id);
776 }
else if (side ==
"right") {
777 if (direction ==
"same") {
778 lane->add_right_neighbor_forward_lane_id()->set_id(lane_id);
780 lane->add_right_neighbor_reverse_lane_id()->set_id(lane_id);
784 sub_node = sub_node->NextSiblingElement(
"neighbor");
787 sub_node = xml_node.FirstChildElement(
"selfReverse");
792 if (checker == tinyxml2::XML_SUCCESS) {
793 lane->add_self_reverse_lane_id()->set_id(lane_id);
795 sub_node = sub_node->NextSiblingElement(
"selfReverse");
799Status LanesXmlParser::ParseLaneBorderMark(
800 const tinyxml2::XMLElement& xml_node,
802 CHECK_NOTNULL(boundary_type);
809 if (checker != tinyxml2::XML_SUCCESS) {
810 std::string err_msg =
"Error to parse lane border mark";
814 Status success = ToPbLaneMarkType(type, color, boundary_type);
816 std::string err_msg =
"fail to convert to pb lane border mark";
823Status LanesXmlParser::ToPbLaneMarkType(
const std::string& type,
824 const std::string& color,
826 CHECK_NOTNULL(boundary_type);
831 if (upper_type ==
"CURB") {
836 if (upper_type ==
"NONE") {
841 if (upper_color ==
"YELLOW") {
842 if (upper_type ==
"SOLID") {
844 }
else if (upper_type ==
"BROKEN") {
847 std::string err_msg =
"Error or unsupport lane boundary type";
850 }
else if (upper_color ==
"WHITE") {
851 if (upper_type ==
"SOLID") {
853 }
else if (upper_type ==
"BROKEN") {
856 std::string err_msg =
"Error or unsupport lane boundary type";
860 std::string err_msg =
"Error or unsupport lane boundary color.";
867Status LanesXmlParser::ParseRegionOverlap(
868 const tinyxml2::XMLElement& xml_node,
869 std::vector<PbRegionOverlap>* region_overlaps) {
870 CHECK_NOTNULL(region_overlaps);
872 auto region_overlap_node = xml_node.FirstChildElement(
"regionOverlap");
873 while (region_overlap_node !=
nullptr) {
876 std::string region_overlap_id;
878 "id", ®ion_overlap_id);
879 if (checker != tinyxml2::XML_SUCCESS) {
880 std::string err_msg =
"Error to parse region overlap id";
884 region_overlap.mutable_id()->set_id(region_overlap_id);
886 auto outline_node = region_overlap_node->FirstChildElement(
"outline");
887 while (outline_node !=
nullptr) {
889 *outline_node, region_overlap.add_polygon()));
890 outline_node = outline_node->NextSiblingElement(
"outline");
893 region_overlap_node =
894 region_overlap_node->NextSiblingElement(
"regionOverlap");
896 region_overlaps->emplace_back(region_overlap);
A general class to denote the return status of an API call.
static Status OK()
generate a success status.
static Status Parse(const tinyxml2::XMLElement &xml_node, const std::string &road_id, std::vector< RoadSectionInternal > *sections)
static std::string ToUpper(const std::string &s)
static double CurveLength(const PbCurve &curve)
static tinyxml2::XMLError QueryStringAttribute(const tinyxml2::XMLElement &xml_node, const std::string &name, std::string *value)
static Status ParseCurve(const tinyxml2::XMLElement &xml_node, PbCurve *curve)
static Status ParseOutline(const tinyxml2::XMLElement &xml_node, PbPolygon *polygon)
#define RETURN_IF_ERROR(expr)
uint32_t width
Width of point cloud
apollo::hdmap::BoundaryEdge_Type PbBoundaryEdgeType
apollo::hdmap::Lane_LaneType PbLaneType
apollo::hdmap::Curve PbCurve
apollo::hdmap::RegionOverlapInfo PbRegionOverlap
apollo::hdmap::LaneBoundary PbLaneBoundary
apollo::hdmap::Lane_LaneDirection PbLaneDirection
apollo::hdmap::Lane PbLane
apollo::hdmap::LaneBoundaryType_Type PbLaneBoundaryTypeType
apollo::hdmap::Lane_LaneTurn PbTurnType
apollo::hdmap::BoundaryEdge PbBoundaryEdge
optional LaneBoundary left_boundary
std::vector< LaneInternal > lanes