Restructured code

This commit is contained in:
Marc Garcia Puig 2019-03-12 19:05:16 +01:00 committed by nsubiron
parent e9d22073c7
commit 5949f2b9e2
36 changed files with 609 additions and 2178 deletions

View File

@ -7,7 +7,7 @@
#include "carla/client/Map.h"
#include "carla/client/Waypoint.h"
#include "carla/opendrive/OpenDrive.h"
#include "carla/opendrive/OpenDriveParser.h"
#include "carla/road/Map.h"
#include "carla/road/WaypointGenerator.h"
@ -18,7 +18,7 @@ namespace client {
static auto MakeMap(const std::string &opendrive_contents) {
auto stream = std::istringstream(opendrive_contents);
return opendrive::OpenDrive::Load(stream);
return opendrive::OpenDriveParser::Load(stream.str());
}
Map::Map(rpc::MapInfo description)

View File

@ -1,474 +0,0 @@
// Copyright (c) 2017 Computer Vision Center (CVC) at the Universitat Autonoma
// de Barcelona (UAB).
//
// This work is licensed under the terms of the MIT license.
// For a copy, see <https://opensource.org/licenses/MIT>.
#include "OpenDrive.h"
#include "carla/road/MapBuilder.h"
#include "carla/Debug.h"
namespace carla {
namespace opendrive {
static void fnc_generate_roads_data(
opendrive::types::OpenDriveData &openDriveRoad,
std::map<int, opendrive::types::RoadInformation *> &out_roads) {
for (size_t i = 0; i < openDriveRoad.roads.size(); ++i) {
out_roads[openDriveRoad.roads[i].attributes.id] = &openDriveRoad.roads[i];
}
}
static void fnc_generate_junctions_data(
opendrive::types::OpenDriveData &openDriveRoad,
std::map<int, std::map<int, std::vector<carla::road::lane_junction_t>>> &out_data) {
for (size_t i = 0; i < openDriveRoad.junctions.size(); ++i) {
for (size_t j = 0; j < openDriveRoad.junctions[i].connections.size(); ++j) {
carla::road::lane_junction_t junctionData;
const int junctionID = openDriveRoad.junctions[i].attributes.id;
const int incommingRoad = openDriveRoad.junctions[i].connections[j].attributes.incoming_road;
const int connectingRoad = openDriveRoad.junctions[i].connections[j].attributes.connecting_road;
junctionData.incomming_road = incommingRoad;
junctionData.connection_road = connectingRoad;
junctionData.contact_point = openDriveRoad.junctions[i].connections[j].attributes.contact_point;
for (size_t k = 0; k < openDriveRoad.junctions[i].connections[j].links.size(); ++k) {
junctionData.from_lane.emplace_back(openDriveRoad.junctions[i].connections[j].links[k].from);
junctionData.to_lane.emplace_back(openDriveRoad.junctions[i].connections[j].links[k].to);
}
out_data[junctionID][incommingRoad].emplace_back(junctionData);
}
}
}
// HACK(Andrei):
static int fnc_get_first_driving_line(opendrive::types::RoadInformation *roadInfo, int id = 0) {
if (roadInfo == nullptr) {
return 0;
}
for (auto itSec = roadInfo->lanes.lane_sections.rbegin();
itSec != roadInfo->lanes.lane_sections.rend() - 1;
++itSec) {
for (auto itLane = itSec->left.begin(); itLane != itSec->left.end(); ++itLane) {
if (itLane->attributes.type == "driving" && itLane->attributes.id == id) {
id = itLane->link ? itLane->link->predecessor_id : 0;
break;
}
}
}
return id;
}
SharedPtr<road::Map> OpenDrive::Load(
const std::string &file,
XmlInputType inputType,
std::string *out_error) {
carla::opendrive::types::OpenDriveData open_drive_road;
OpenDriveParser::Parse(file.c_str(), open_drive_road, inputType, out_error);
carla::road::MapBuilder mapBuilder;
if (open_drive_road.roads.empty()) {
// TODO(Andrei): Log some type of warning
return mapBuilder.Build();
}
mapBuilder.SetGeoReference(open_drive_road.geoReference);
mapBuilder.SetTrafficGroupData(open_drive_road.trafficlightgroups);
mapBuilder.SetTrafficSignData(open_drive_road.trafficsigns);
// Generate road and junction information
using road_data_t = std::map<int, carla::opendrive::types::RoadInformation *>;
using junction_data_t = std::map<int, std::map<int, std::vector<carla::road::lane_junction_t>>>;
road_data_t road_data;
junction_data_t junctions_data;
// generates a map<road_id, opendrive::types::RoadInformation>
fnc_generate_roads_data(open_drive_road, road_data);
// generates a map<junction_id, opendrive::types::RoadInformation>
fnc_generate_junctions_data(open_drive_road, junctions_data);
// Transforma data for the MapBuilder
for (road_data_t::iterator it = road_data.begin(); it != road_data.end(); ++it) {
carla::road::element::RoadSegmentDefinition road_segment(it->first);
carla::road::element::RoadInfoLane *RoadInfoLanes =
road_segment.MakeInfo<carla::road::element::RoadInfoLane>();
carla::road::element::RoadGeneralInfo *RoadGeneralInfo =
road_segment.MakeInfo<carla::road::element::RoadGeneralInfo>();
RoadGeneralInfo->SetJunctionId(it->second->attributes.junction);
for (auto &&lane_offset : it->second->lanes.lane_offset) {
// @todo: delete this old method
RoadGeneralInfo->SetLanesOffset(lane_offset.s, lane_offset.a);
// new method
road_segment.MakeInfo<carla::road::element::RoadInfoLaneOffset>(
lane_offset.s,
lane_offset.a,
lane_offset.b,
lane_offset.c,
lane_offset.d
);
}
for (auto &&elevation : it->second->road_profiles.elevation_profile) {
road_segment.MakeInfo<carla::road::element::RoadElevationInfo>(
elevation.start_position,
elevation.start_position,
elevation.elevation,
elevation.slope,
elevation.vertical_curvature,
elevation.curvature_change);
}
std::unordered_map<int, int> left_lanes_go_to_successor, left_lanes_go_to_predecessor;
// std::unordered_map<int, int> center_lanes_go_to_successor, center_lanes_go_to_predecessor;
std::unordered_map<int, int> right_lanes_go_to_successor, right_lanes_go_to_predecessor;
for (auto &&left_lanes : it->second->lanes.lane_sections[0].left) {
if (left_lanes.link != nullptr) {
if (left_lanes.attributes.type != "driving") {
continue;
}
if (left_lanes.link->successor_id != 0) {
left_lanes_go_to_successor[left_lanes.attributes.id] = left_lanes.link->successor_id;
}
left_lanes_go_to_predecessor[left_lanes.attributes.id] = left_lanes.link->predecessor_id;
if (left_lanes.link->predecessor_id != 0) {
}
}
}
// for (auto &&center_lanes : it->second->lanes.lane_sections[0].center) {
// if (center_lanes.link != nullptr) {
// if (center_lanes.link->successor_id != 0) {
// center_lanes_go_to_successor[center_lanes.attributes.id] = center_lanes.link->successor_id;
// }
// if (center_lanes.link->predecessor_id != 0) {
// center_lanes_go_to_predecessor[center_lanes.attributes.id] = center_lanes.link->predecessor_id;
// }
// }
// }
for (auto &&right_lanes : it->second->lanes.lane_sections[0].right) {
if (right_lanes.link != nullptr) {
if (right_lanes.attributes.type != "driving") {
continue;
}
if (right_lanes.link->successor_id != 0) {
right_lanes_go_to_successor[right_lanes.attributes.id] = right_lanes.link->successor_id;
}
if (right_lanes.link->predecessor_id != 0) {
right_lanes_go_to_predecessor[right_lanes.attributes.id] = right_lanes.link->predecessor_id;
}
}
}
if (it->second->lanes.lane_sections.size() > 1) {
for (auto itLaneSec = it->second->lanes.lane_sections.begin() + 1;
itLaneSec != it->second->lanes.lane_sections.end();
++itLaneSec) {
for (auto &&itLanes : itLaneSec->left) {
for (auto &&itTest : left_lanes_go_to_successor) {
if (itTest.second == itLanes.attributes.id && itLanes.link) {
itTest.second = itLanes.link->successor_id;
}
}
}
}
// for (auto itLaneSec = it->second->lanes.lane_sections.begin() + 1;
// itLaneSec != it->second->lanes.lane_sections.end();
// ++itLaneSec) {
// for (auto &&itLanes : itLaneSec->center) {
// for (auto &&itTest : center_lanes_go_to_successor) {
// if (itTest.second == itLanes.attributes.id && itLanes.link) {
// itTest.second = itLanes.link->successor_id;
// }
// }
// }
// }
for (auto itLaneSec = it->second->lanes.lane_sections.begin() + 1;
itLaneSec != it->second->lanes.lane_sections.end();
++itLaneSec) {
for (auto &&itLanes : itLaneSec->right) {
for (auto &&itTest : right_lanes_go_to_successor) {
if (itTest.second == itLanes.attributes.id && itLanes.link) {
itTest.second = itLanes.link->successor_id;
}
}
}
}
}
/////////////////////////////////////////////////////////////////////////
std::vector<carla::opendrive::types::LaneInfo> *lanesLeft =
&it->second->lanes.lane_sections.front().left;
std::vector<carla::opendrive::types::LaneInfo> *lanesRight =
&it->second->lanes.lane_sections.front().right;
for (size_t i = 0; i < lanesLeft->size(); ++i) {
RoadInfoLanes->addLaneInfo(lanesLeft->at(i).attributes.id,
lanesLeft->at(i).lane_width[0].width,
lanesLeft->at(i).attributes.type);
}
for (size_t i = 0; i < lanesRight->size(); ++i) {
RoadInfoLanes->addLaneInfo(lanesRight->at(i).attributes.id,
lanesRight->at(i).lane_width[0].width,
lanesRight->at(i).attributes.type);
}
if (it->second->road_link.successor != nullptr) {
if (it->second->road_link.successor->element_type == "junction") {
std::vector<carla::road::lane_junction_t> &options =
junctions_data[it->second->road_link.successor->id][it->first];
for (size_t i = 0; i < options.size(); ++i) {
road_segment.AddSuccessorID(options[i].connection_road, options[i].contact_point == "start");
for (size_t j = 0; j < options[i].from_lane.size(); ++j) {
bool is_end = options[i].contact_point == "end";
int to_lane = options[i].to_lane[j];
if (is_end) {
to_lane = fnc_get_first_driving_line(road_data[options[i].connection_road], to_lane);
}
road_segment.AddNextLaneInfo(options[i].from_lane[j], to_lane, options[i].connection_road);
}
}
} else {
bool is_start = it->second->road_link.successor->contact_point == "start";
road_segment.AddSuccessorID(it->second->road_link.successor->id, is_start);
for (auto &&lanes : right_lanes_go_to_successor) {
road_segment.AddNextLaneInfo(lanes.first, lanes.second, it->second->road_link.successor->id);
}
for (auto &&lanes : left_lanes_go_to_successor) {
road_segment.AddNextLaneInfo(lanes.first, lanes.second, it->second->road_link.successor->id);
}
}
}
if (it->second->road_link.predecessor != nullptr) {
if (it->second->road_link.predecessor->element_type == "junction") {
std::vector<carla::road::lane_junction_t> &options =
junctions_data[it->second->road_link.predecessor->id][it->first];
for (size_t i = 0; i < options.size(); ++i) {
road_segment.AddPredecessorID(options[i].connection_road, options[i].contact_point == "start");
for (size_t j = 0; j < options[i].from_lane.size(); ++j) {
bool is_end = options[i].contact_point == "end";
int to_lane = options[i].to_lane[j];
if (is_end) {
to_lane = fnc_get_first_driving_line(road_data[options[i].connection_road], to_lane);
}
road_segment.AddPrevLaneInfo(options[i].from_lane[j], to_lane, options[i].connection_road);
}
}
} else {
bool is_start = it->second->road_link.predecessor->contact_point == "start";
road_segment.AddPredecessorID(it->second->road_link.predecessor->id, is_start);
for (auto &&lanes : right_lanes_go_to_predecessor) {
road_segment.AddPrevLaneInfo(lanes.first, lanes.second, it->second->road_link.predecessor->id);
}
for (auto &&lanes : left_lanes_go_to_predecessor) {
road_segment.AddPrevLaneInfo(lanes.first, lanes.second, it->second->road_link.predecessor->id);
}
}
}
// Add lane change information
for (auto &&lane_section : it->second->lanes.lane_sections) {
// Lambda to convert from string to enum LaneChange
auto string_2_lane_change_enum = [](auto lane_change)->
carla::road::element::RoadInfoMarkRecord::LaneChange {
if (lane_change == "increase") {
return carla::road::element::RoadInfoMarkRecord::LaneChange::Increase;
}
else if (lane_change == "decrease") {
return carla::road::element::RoadInfoMarkRecord::LaneChange::Decrease;
}
else if (lane_change == "both") {
return carla::road::element::RoadInfoMarkRecord::LaneChange::Both;
}
else {
return carla::road::element::RoadInfoMarkRecord::LaneChange::None;
}
};
const auto lane_sec_s_offset = lane_section.start_position;
// Create a new RoadInfoMarkRecord for each lane section. Each RoadInfoMarkRecord
// will contain the actual distance from the start of the RoadSegment
for (auto &&lane_section_left : lane_section.left) {
// parse all left lane road marks
for (auto &&road_marker : lane_section_left.road_marker) {
road_segment.MakeInfo<carla::road::element::RoadInfoMarkRecord>(
lane_sec_s_offset + road_marker.soffset,
lane_section_left.attributes.id,
road_marker.type,
road_marker.weigth,
road_marker.color,
road_marker.material,
road_marker.width,
string_2_lane_change_enum(road_marker.lane_change),
// @todo: "carla/opendrive/types.h" must be extended to parse the height
0.0);
}
// parse all left lane width
for (auto &&lane_width : lane_section_left.lane_width) {
road_segment.MakeInfo<carla::road::element::RoadInfoLaneWidth>(
lane_sec_s_offset + lane_width.soffset, // s
lane_section_left.attributes.id, // lane_id
lane_width.width, // a
lane_width.slope, // b
lane_width.vertical_curvature, // c
lane_width.curvature_change); // d
}
}
// @todo: there must be only one central lane, so maybe use [0]
for (auto &&lane_section_center : lane_section.center) {
// parse all center lane road marks
for (auto &&road_marker : lane_section_center.road_marker) {
road_segment.MakeInfo<carla::road::element::RoadInfoMarkRecord>(
lane_sec_s_offset + road_marker.soffset,
lane_section_center.attributes.id,
road_marker.type,
road_marker.weigth,
road_marker.color,
road_marker.material,
road_marker.width,
string_2_lane_change_enum(road_marker.lane_change),
// @todo: "carla/opendrive/types.h" must be extended to parse the height
0.0);
}
// parse all center lane width
for (auto &&lane_width : lane_section_center.lane_width) {
road_segment.MakeInfo<carla::road::element::RoadInfoLaneWidth>(
lane_sec_s_offset + lane_width.soffset, // s
lane_section_center.attributes.id, // lane_id
lane_width.width, // a
lane_width.slope, // b
lane_width.vertical_curvature, // c
lane_width.curvature_change); // d
}
}
for (auto &&lane_section_right : lane_section.right) {
// parse all right lane road marks
for (auto &&road_marker : lane_section_right.road_marker) {
road_segment.MakeInfo<carla::road::element::RoadInfoMarkRecord>(
lane_sec_s_offset + road_marker.soffset,
lane_section_right.attributes.id,
road_marker.type,
road_marker.weigth,
road_marker.color,
road_marker.material,
road_marker.width,
string_2_lane_change_enum(road_marker.lane_change),
// @todo: "carla/opendrive/types.h" must be extended to parse the height
0.0);
}
// parse all right lane width
for (auto &&lane_width : lane_section_right.lane_width) {
road_segment.MakeInfo<carla::road::element::RoadInfoLaneWidth>(
lane_sec_s_offset + lane_width.soffset, // s
lane_section_right.attributes.id, // lane_id
lane_width.width, // a
lane_width.slope, // b
lane_width.vertical_curvature, // c
lane_width.curvature_change); // d
}
}
}
// Add geometry information
for (size_t i = 0; i < it->second->geometry_attributes.size(); ++i) {
geom::Location loc;
loc.x = it->second->geometry_attributes[i]->start_position_x;
loc.y = -it->second->geometry_attributes[i]->start_position_y;
switch (it->second->geometry_attributes[i]->type) {
case carla::opendrive::types::GeometryType::ARC: {
carla::opendrive::types::GeometryAttributesArc *arc =
(carla::opendrive::types::GeometryAttributesArc *) it->second->geometry_attributes[i].get();
road_segment.MakeGeometry<carla::road::element::GeometryArc>(arc->start_position,
arc->length,
-arc->heading,
loc,
arc->curvature);
break;
}
case carla::opendrive::types::GeometryType::LINE: {
carla::opendrive::types::GeometryAttributesLine *line =
(carla::opendrive::types::GeometryAttributesLine *) it->second->geometry_attributes[i].get();
road_segment.MakeGeometry<carla::road::element::GeometryLine>(line->start_position,
line->length,
-line->heading,
loc);
break;
}
case carla::opendrive::types::GeometryType::SPIRAL: {
carla::opendrive::types::GeometryAttributesSpiral *spiral =
(carla::opendrive::types::GeometryAttributesSpiral *) it->second->geometry_attributes[i].get();
road_segment.MakeGeometry<carla::road::element::GeometrySpiral>(spiral->start_position,
spiral->length,
-spiral->heading,
loc,
spiral->curve_start,
spiral->curve_end);
break;
}
default: {
break;
}
}
}
mapBuilder.AddRoadSegmentDefinition(road_segment);
}
return mapBuilder.Build();
}
SharedPtr<road::Map> OpenDrive::Load(std::istream &input, std::string *out_error) {
std::string fileContent;
std::string line;
while (std::getline(input, line)) {
fileContent.append(line);
}
return Load(fileContent, XmlInputType::CONTENT, out_error);
}
} // namespace opendrive
} // namespace carla

View File

@ -0,0 +1,52 @@
// Copyright (c) 2017 Computer Vision Center (CVC) at the Universitat Autonoma
// de Barcelona (UAB).
//
// This work is licensed under the terms of the MIT license.
// For a copy, see <https://opensource.org/licenses/MIT>.
#include "carla/opendrive/OpenDriveParser.h"
#include "carla/Logging.h"
#include "carla/road/MapBuilder.h"
#include "carla/opendrive/parser/GeoReferenceParser.h"
#include "carla/opendrive/parser/GeometryParser.h"
#include "carla/opendrive/parser/JunctionParser.h"
#include "carla/opendrive/parser/LaneParser.h"
#include "carla/opendrive/parser/ProfilesParser.h"
#include "carla/opendrive/parser/RoadLinkParser.h"
#include "carla/opendrive/parser/TrafficGroupParser.h"
#include "carla/opendrive/parser/TrafficSignParser.h"
#include "carla/opendrive/parser/TrafficSignalsParser.h"
#include "carla/opendrive/pugixml/pugixml.hpp"
namespace carla {
namespace opendrive {
SharedPtr<road::Map> OpenDriveParser::Load(const std::string &opendrive) {
pugi::xml_document xml;
pugi::xml_parse_result parse_result = xml.load_string(opendrive.c_str());
if (parse_result == false) {
log_error("unable to parse the XML string");
return {};
}
carla::road::MapBuilder map_builder;
// GeoReferenceParser::Parse(xml, map_builder):
parser::GeometryParser::Parse(xml, map_builder);
parser::JunctionParser::Parse(xml, map_builder);
parser::LaneParser::Parse(xml, map_builder);
parser::ProfilesParser::Parse(xml, map_builder);
parser::RoadLinkParser::Parse(xml, map_builder);
parser::TrafficGroupParser::Parse(xml, map_builder);
parser::TrafficSignParser::Parse(xml, map_builder);
parser::TrafficSignalsParser::Parse(xml, map_builder);
return map_builder.Build();
}
} // namespace opendrive
} // namespace carla

View File

@ -8,28 +8,17 @@
#include "carla/Memory.h"
#include "carla/road/Map.h"
#include "parser/OpenDriveParser.h"
#include <istream>
#include <ostream>
#include <string>
namespace carla {
namespace opendrive {
class OpenDrive {
class OpenDriveParser {
public:
static SharedPtr<road::Map> Load(
std::istream &input,
std::string *out_error = nullptr);
static SharedPtr<road::Map> Load(const std::string &opendrive);
static SharedPtr<road::Map> Load(
const std::string &xml,
XmlInputType inputType,
std::string *out_error = nullptr);
static void Dump(const road::Map &map, std::ostream &output);
};
} // namespace opendrive

View File

@ -18,6 +18,7 @@ namespace parser {
public:
static geom::GeoLocation Parse(const std::string &geo_reference_string);
};
} // parser

View File

@ -4,70 +4,26 @@
// This work is licensed under the terms of the MIT license.
// For a copy, see <https://opensource.org/licenses/MIT>.
#include "GeometryParser.h"
#include "carla/opendrive/parser/GeometryParser.h"
#include <cassert>
#include "carla/opendrive/pugixml/pugixml.hpp"
#define ODP_ASSERT(x, ...) assert(x)
#define ODP_UNUSED(x) (void) (x)
#include "carla/road/MapBuilder.h"
void carla::opendrive::parser::GeometryParser::ParseArc(
const pugi::xml_node &xmlNode,
carla::opendrive::types::GeometryAttributesArc *out_geometry_arc) {
out_geometry_arc->type = opendrive::types::GeometryType::ARC;
out_geometry_arc->curvature = std::stod(xmlNode.attribute("curvature").value());
}
namespace carla {
namespace opendrive {
namespace parser {
void carla::opendrive::parser::GeometryParser::ParseLine(
const pugi::xml_node &xmlNode,
carla::opendrive::types::GeometryAttributesLine *out_geometry_line) {
ODP_UNUSED(xmlNode);
out_geometry_line->type = opendrive::types::GeometryType::LINE;
}
void ParseArc() {}
void carla::opendrive::parser::GeometryParser::ParseSpiral(
const pugi::xml_node &xmlNode,
carla::opendrive::types::GeometryAttributesSpiral *out_geometry_spiral) {
out_geometry_spiral->type = opendrive::types::GeometryType::SPIRAL;
out_geometry_spiral->curve_end = std::stod(xmlNode.attribute("curvEnd").value());
out_geometry_spiral->curve_start = std::stod(xmlNode.attribute("curvStart").value());
}
void ParseLine() {}
void carla::opendrive::parser::GeometryParser::Parse(
const pugi::xml_node &xmlNode,
std::vector<std::unique_ptr<carla::opendrive::types::GeometryAttributes>> &out_geometry_attributes) {
carla::opendrive::parser::GeometryParser gometry_parser;
void ParseSpiral() {}
for (pugi::xml_node roadGeometry = xmlNode.child("geometry");
roadGeometry;
roadGeometry = roadGeometry.next_sibling("geometry")) {
std::unique_ptr<opendrive::types::GeometryAttributes> geometry_attributes;
std::string firstChildName(roadGeometry.first_child().name());
void GeometryParser::Parse(
const pugi::xml_document &/* xml */,
carla::road::MapBuilder &/* map_builder */) {}
if (firstChildName == "arc") {
geometry_attributes = std::make_unique<opendrive::types::GeometryAttributesArc>();
gometry_parser.ParseArc(roadGeometry.first_child(),
static_cast<opendrive::types::GeometryAttributesArc *>(geometry_attributes.get()));
} else if (firstChildName == "line") {
geometry_attributes = std::make_unique<opendrive::types::GeometryAttributesLine>();
gometry_parser.ParseLine(roadGeometry.first_child(),
static_cast<opendrive::types::GeometryAttributesLine *>(geometry_attributes.get()));
} else if (firstChildName == "spiral") {
geometry_attributes = std::make_unique<opendrive::types::GeometryAttributesSpiral>();
gometry_parser.ParseSpiral(roadGeometry.first_child(),
static_cast<opendrive::types::GeometryAttributesSpiral *>(geometry_attributes.get()));
} else {
ODP_ASSERT(false, "Geometry type unknown");
}
geometry_attributes->start_position = std::stod(roadGeometry.attribute("s").value());
geometry_attributes->start_position_x = std::stod(roadGeometry.attribute("x").value());
geometry_attributes->start_position_y = std::stod(roadGeometry.attribute("y").value());
geometry_attributes->heading = std::stod(roadGeometry.attribute("hdg").value());
geometry_attributes->length = std::stod(roadGeometry.attribute("length").value());
out_geometry_attributes.emplace_back(std::move(geometry_attributes));
}
}
} // namespace parser
} // namespace opendrive
} // namespace carla

View File

@ -6,36 +6,28 @@
#pragma once
#include "../types.h"
#include "./pugixml/pugixml.hpp"
namespace pugi {
class xml_document;
} // namespace pugi
namespace carla {
namespace road {
class MapBuilder;
} // namespace road
namespace opendrive {
namespace parser {
class GeometryParser {
private:
void ParseArc(
const pugi::xml_node &xmlNode,
carla::opendrive::types::GeometryAttributesArc *out_geometry_arc);
void ParseLine(
const pugi::xml_node &xmlNode,
carla::opendrive::types::GeometryAttributesLine *out_geometry_line);
void ParseSpiral(
const pugi::xml_node &xmlNode,
carla::opendrive::types::GeometryAttributesSpiral *out_geometry_spiral);
public:
static void Parse(
const pugi::xml_node &xmlNode,
std::vector<std::unique_ptr<carla::opendrive::types::GeometryAttributes>> &out_geometry_attributes);
const pugi::xml_document &xml,
carla::road::MapBuilder &map_builder);
};
}
}
}
} // namespace parser
} // namespace opendrive
} // namespace carla

View File

@ -4,52 +4,20 @@
// This work is licensed under the terms of the MIT license.
// For a copy, see <https://opensource.org/licenses/MIT>.
#include "JunctionParser.h"
#include "carla/opendrive/parser/JunctionParser.h"
void carla::opendrive::parser::JunctionParser::Parse(
const pugi::xml_node &xmlNode,
std::vector<carla::opendrive::types::Junction> &out_junction) {
carla::opendrive::parser::JunctionParser parser;
carla::opendrive::types::Junction junction;
#include "carla/opendrive/pugixml/pugixml.hpp"
junction.attributes.id = std::atoi(xmlNode.attribute("id").value());
junction.attributes.name = xmlNode.attribute("name").value();
#include "carla/road/MapBuilder.h"
parser.ParseConnection(xmlNode, junction.connections);
out_junction.emplace_back(junction);
}
namespace carla {
namespace opendrive {
namespace parser {
void carla::opendrive::parser::JunctionParser::ParseConnection(
const pugi::xml_node &xmlNode,
std::vector<carla::opendrive::types::JunctionConnection> &out_connections) {
for (pugi::xml_node junctionConnection = xmlNode.child("connection");
junctionConnection;
junctionConnection = junctionConnection.next_sibling("connection")) {
carla::opendrive::types::JunctionConnection jConnection;
void JunctionParser::Parse(
const pugi::xml_document &/* xml */,
carla::road::MapBuilder &/* map_builder */) {}
jConnection.attributes.id = std::atoi(junctionConnection.attribute("id").value());
jConnection.attributes.contact_point = junctionConnection.attribute("contactPoint").value();
jConnection.attributes.incoming_road = std::atoi(junctionConnection.attribute("incomingRoad").value());
jConnection.attributes.connecting_road =
std::atoi(junctionConnection.attribute("connectingRoad").value());
ParseLaneLink(junctionConnection, jConnection.links);
out_connections.emplace_back(jConnection);
}
}
void carla::opendrive::parser::JunctionParser::ParseLaneLink(
const pugi::xml_node &xmlNode,
std::vector<carla::opendrive::types::JunctionLaneLink> &out_lane_link) {
for (pugi::xml_node junctionLaneLink = xmlNode.child("laneLink");
junctionLaneLink;
junctionLaneLink = junctionLaneLink.next_sibling("laneLink")) {
carla::opendrive::types::JunctionLaneLink jLaneLink;
jLaneLink.from = std::atoi(junctionLaneLink.attribute("from").value());
jLaneLink.to = std::atoi(junctionLaneLink.attribute("to").value());
out_lane_link.emplace_back(jLaneLink);
}
}
} // namespace parser
} // namespace opendrive
} // namespace carla

View File

@ -6,32 +6,28 @@
#pragma once
#include "../types.h"
#include "./pugixml/pugixml.hpp"
namespace pugi {
class xml_document;
} // namespace pugi
namespace carla {
namespace road {
class MapBuilder;
} // namespace road
namespace opendrive {
namespace parser {
class JunctionParser {
private:
void ParseConnection(
const pugi::xml_node &xmlNode,
std::vector<carla::opendrive::types::JunctionConnection> &out_connections);
void ParseLaneLink(
const pugi::xml_node &xmlNode,
std::vector<carla::opendrive::types::JunctionLaneLink> &out_lane_link);
public:
static void Parse(
const pugi::xml_node &xmlNode,
std::vector<carla::opendrive::types::Junction> &out_junction);
const pugi::xml_document &xml,
carla::road::MapBuilder &map_builder);
};
}
}
}
} // namespace parser
} // namespace opendrive
} // namespace carla

View File

@ -4,167 +4,20 @@
// This work is licensed under the terms of the MIT license.
// For a copy, see <https://opensource.org/licenses/MIT>.
#include "LaneParser.h"
#include "carla/opendrive/parser/LaneParser.h"
#include "carla/opendrive/pugixml/pugixml.hpp"
#include "carla/road/MapBuilder.h"
namespace carla {
namespace opendrive {
namespace parser {
void LaneParser::ParseLane(
const pugi::xml_node &xmlNode,
std::vector<types::LaneInfo> &out_lane) {
for (pugi::xml_node lane = xmlNode.child("lane"); lane; lane = lane.next_sibling("lane")) {
types::LaneInfo currentLane;
currentLane.attributes.type = lane.attribute("type").value();
currentLane.attributes.level = lane.attribute("level").value();
currentLane.attributes.id = std::atoi(lane.attribute("id").value());
ParseLaneSpeed(lane, currentLane.lane_speed);
ParseLaneWidth(lane, currentLane.lane_width);
ParseLaneLink(lane.child("link"), currentLane.link);
ParseLaneRoadMark(lane, currentLane.road_marker);
out_lane.emplace_back(std::move(currentLane));
}
}
void LaneParser::ParseLaneWidth(
const pugi::xml_node &xmlNode,
std::vector<types::LaneWidth> &out_lane_width) {
for (pugi::xml_node laneWidth = xmlNode.child("width");
laneWidth;
laneWidth = laneWidth.next_sibling("width")) {
types::LaneWidth laneWidthInfo;
laneWidthInfo.soffset = std::stod(laneWidth.attribute("sOffset").value());
laneWidthInfo.width = std::stod(laneWidth.attribute("a").value());
laneWidthInfo.slope = std::stod(laneWidth.attribute("b").value());
laneWidthInfo.vertical_curvature = std::stod(laneWidth.attribute("c").value());
laneWidthInfo.curvature_change = std::stod(laneWidth.attribute("d").value());
out_lane_width.emplace_back(laneWidthInfo);
}
}
void LaneParser::ParseLaneLink(
const pugi::xml_node &xmlNode,
std::unique_ptr<types::LaneLink> &out_lane_link) {
const pugi::xml_node predecessorNode = xmlNode.child("predecessor");
const pugi::xml_node successorNode = xmlNode.child("successor");
out_lane_link =
(predecessorNode || successorNode) ? std::make_unique<opendrive::types::LaneLink>() : nullptr;
if (out_lane_link == nullptr) {
return;
}
out_lane_link->predecessor_id = predecessorNode ? std::atoi(predecessorNode.attribute("id").value()) : 0;
out_lane_link->successor_id = successorNode ? std::atoi(successorNode.attribute("id").value()) : 0;
}
void LaneParser::ParseLaneOffset(
const pugi::xml_node &xmlNode,
std::vector<types::LaneOffset> &out_lane_offset) {
types::LaneOffset lanesOffset;
lanesOffset.s = std::stod(xmlNode.attribute("s").value());
lanesOffset.a = std::stod(xmlNode.attribute("a").value());
lanesOffset.b = std::stod(xmlNode.attribute("b").value());
lanesOffset.c = std::stod(xmlNode.attribute("c").value());
lanesOffset.d = std::stod(xmlNode.attribute("d").value());
out_lane_offset.emplace_back(lanesOffset);
}
void LaneParser::ParseLaneRoadMark(
const pugi::xml_node &xmlNode,
std::vector<types::LaneRoadMark> &out_lane_mark) {
for (pugi::xml_node road_mark = xmlNode.child("roadMark");
road_mark; road_mark = road_mark.next_sibling("roadMark")) {
types::LaneRoadMark roadMarker;
if (road_mark.attribute("sOffset") != nullptr) {
roadMarker.soffset = std::stod(road_mark.attribute("sOffset").value());
}
if (road_mark.attribute("width") != nullptr) {
roadMarker.width = std::stod(road_mark.attribute("width").value());
}
if (road_mark.attribute("type") != nullptr) {
roadMarker.type = road_mark.attribute("type").value();
}
if (road_mark.attribute("weight") != nullptr) {
roadMarker.weigth = road_mark.attribute("weight").value();
}
if (road_mark.attribute("material") != nullptr) {
roadMarker.color = road_mark.attribute("material").value();
}
if (road_mark.attribute("color") != nullptr) {
roadMarker.color = road_mark.attribute("color").value();
}
if (road_mark.attribute("laneChange") != nullptr) {
roadMarker.lane_change = road_mark.attribute("laneChange").value();
}
out_lane_mark.emplace_back(roadMarker);
}
}
void LaneParser::ParseLaneSpeed(
const pugi::xml_node &xmlNode,
std::vector<types::LaneSpeed> &out_lane_speed) {
for (pugi::xml_node laneSpeed = xmlNode.child("speed");
laneSpeed;
laneSpeed = laneSpeed.next_sibling("speed")) {
types::LaneSpeed lane_speed = { 0.0, 0.0 };
lane_speed.soffset = std::stod(laneSpeed.attribute("sOffset").value());
lane_speed.max_speed = std::stod(laneSpeed.attribute("max").value());
out_lane_speed.emplace_back(lane_speed);
}
}
void LaneParser::Parse(
const pugi::xml_node &xmlNode,
types::Lanes &out_lanes) {
LaneParser laneParser;
const pugi::xml_document &/* xml */,
carla::road::MapBuilder &/* map_builder */) {}
for (pugi::xml_node laneSection = xmlNode.child("laneOffset");
laneSection;
laneSection = laneSection.next_sibling("laneOffset")) {
laneParser.ParseLaneOffset(laneSection, out_lanes.lane_offset);
}
for (pugi::xml_node laneSection = xmlNode.child("laneSection");
laneSection;
laneSection = laneSection.next_sibling("laneSection")) {
types::LaneSection laneSec;
laneSec.start_position = std::stod(laneSection.attribute("s").value());
pugi::xml_node lane = laneSection.child("left");
laneParser.ParseLane(lane, laneSec.left);
lane = laneSection.child("center");
laneParser.ParseLane(lane, laneSec.center);
lane = laneSection.child("right");
laneParser.ParseLane(lane, laneSec.right);
out_lanes.lane_sections.emplace_back(std::move(laneSec));
}
}
} // parser
} // opendrive
} // carla
} // namespace parser
} // namespace opendrive
} // namespace carla

View File

@ -6,48 +6,28 @@
#pragma once
#include "../types.h"
#include "./pugixml/pugixml.hpp"
namespace pugi {
class xml_document;
} // namespace pugi
namespace carla {
namespace road {
class MapBuilder;
} // namespace road
namespace opendrive {
namespace parser {
class LaneParser {
private:
void ParseLane(
const pugi::xml_node &xmlNode,
std::vector<types::LaneInfo> &out_lane);
void ParseLaneSpeed(
const pugi::xml_node &xmlNode,
std::vector<types::LaneSpeed> &out_lane_speed);
void ParseLaneLink(
const pugi::xml_node &xmlNode,
std::unique_ptr<types::LaneLink> &out_lane_link);
void ParseLaneOffset(
const pugi::xml_node &xmlNode,
std::vector<types::LaneOffset> &out_lane_offset);
void ParseLaneWidth(
const pugi::xml_node &xmlNode,
std::vector<types::LaneWidth> &out_lane_width);
void ParseLaneRoadMark(
const pugi::xml_node &xmlNode,
std::vector<types::LaneRoadMark> &out_lane_mark);
public:
static void Parse(
const pugi::xml_node &xmlNode,
types::Lanes &out_lanes);
const pugi::xml_document &xml,
carla::road::MapBuilder &map_builder);
};
} // parser
} // opendrive
} // carla
} // namespace parser
} // namespace opendrive
} // namespace carla

View File

@ -1,102 +0,0 @@
// Copyright (c) 2017 Computer Vision Center (CVC) at the Universitat Autonoma
// de Barcelona (UAB).
//
// This work is licensed under the terms of the MIT license.
// For a copy, see <https://opensource.org/licenses/MIT>.
#include "carla/opendrive/parser/OpenDriveParser.h"
#include "carla/geom/GeoLocation.h"
#include "carla/opendrive/parser/GeoReferenceParser.h"
#include "carla/opendrive/parser/GeometryParser.h"
#include "carla/opendrive/parser/JunctionParser.h"
#include "carla/opendrive/parser/LaneParser.h"
#include "carla/opendrive/parser/ProfilesParser.h"
#include "carla/opendrive/parser/RoadLinkParser.h"
#include "carla/opendrive/parser/TrafficGroupParser.h"
#include "carla/opendrive/parser/TrafficSignParser.h"
#include "carla/opendrive/parser/TrafficSignalsParser.h"
#include "./pugixml/pugixml.hpp"
bool OpenDriveParser::Parse(
const char *xml,
carla::opendrive::types::OpenDriveData &out_open_drive_data,
XmlInputType inputType,
std::string *out_error) {
namespace odp = carla::opendrive::parser;
pugi::xml_document xmlDoc;
pugi::xml_parse_result pugiParseResult;
switch (inputType) {
case XmlInputType::FILE: {
pugiParseResult = xmlDoc.load_file(xml);
} break;
case XmlInputType::CONTENT: {
pugiParseResult = xmlDoc.load_string(xml);
} break;
default: {
// TODO(Andrei): Log some kind of error
return false;
} break;
}
if (pugiParseResult == false) {
if (out_error != nullptr) {
*out_error = pugiParseResult.description();
}
return false;
}
for (pugi::xml_node road = xmlDoc.child("OpenDRIVE").child("road");
road;
road = road.next_sibling("road")) {
carla::opendrive::types::RoadInformation openDriveRoadInformation;
openDriveRoadInformation.attributes.name = road.attribute("name").value();
openDriveRoadInformation.attributes.id = std::atoi(road.attribute("id").value());
openDriveRoadInformation.attributes.length = std::stod(road.attribute("length").value());
openDriveRoadInformation.attributes.junction = std::atoi(road.attribute("junction").value());
///////////////////////////////////////////////////////////////////////////////
odp::ProfilesParser::Parse(road, openDriveRoadInformation.road_profiles);
odp::RoadLinkParser::Parse(road.child("link"), openDriveRoadInformation.road_link);
odp::TrafficSignalsParser::Parse(road.child("signals"),
openDriveRoadInformation.trafic_signals);
odp::LaneParser::Parse(road.child("lanes"), openDriveRoadInformation.lanes);
odp::GeometryParser::Parse(road.child("planView"),
openDriveRoadInformation.geometry_attributes);
out_open_drive_data.roads.emplace_back(std::move(openDriveRoadInformation));
}
for (pugi::xml_node junction = xmlDoc.child("OpenDRIVE").child("junction");
junction;
junction = junction.next_sibling("junction")) {
odp::JunctionParser::Parse(junction, out_open_drive_data.junctions);
}
for (pugi::xml_node tlgroup = xmlDoc.child("OpenDRIVE").child("tlGroup");
tlgroup;
tlgroup = tlgroup.next_sibling("tlGroup")) {
odp::TrafficGroupParser::Parse(tlgroup, out_open_drive_data.trafficlightgroups);
}
for (pugi::xml_node trafficsigns = xmlDoc.child("OpenDRIVE").child("trafficsign");
trafficsigns;
trafficsigns = trafficsigns.next_sibling("trafficsign")) {
odp::TrafficSignParser::Parse(trafficsigns, out_open_drive_data.trafficsigns);
}
out_open_drive_data.geoReference = odp::GeoReferenceParser::Parse(
xmlDoc.child("OpenDRIVE").child("header").child_value("geoReference"));
return true;
}

View File

@ -1,22 +0,0 @@
// Copyright (c) 2017 Computer Vision Center (CVC) at the Universitat Autonoma
// de Barcelona (UAB).
//
// This work is licensed under the terms of the MIT license.
// For a copy, see <https://opensource.org/licenses/MIT>.
#pragma once
#include "carla/opendrive/types.h"
enum class XmlInputType : int {
FILE,
CONTENT
};
struct OpenDriveParser {
static bool Parse(
const char *xml,
carla::opendrive::types::OpenDriveData &out_open_drive_data,
XmlInputType inputType,
std::string *out_error = nullptr);
};

View File

@ -4,49 +4,20 @@
// This work is licensed under the terms of the MIT license.
// For a copy, see <https://opensource.org/licenses/MIT>.
#include "ProfilesParser.h"
#include "carla/opendrive/parser/ProfilesParser.h"
void carla::opendrive::parser::ProfilesParser::ParseElevation(
const pugi::xml_node &xmlNode,
std::vector<carla::opendrive::types::ElevationProfile> &out_elevation_profile) {
for (pugi::xml_node laneSection = xmlNode.child("elevation");
laneSection;
laneSection = laneSection.next_sibling("elevation")) {
carla::opendrive::types::ElevationProfile elevationProfile;
#include "carla/opendrive/pugixml/pugixml.hpp"
elevationProfile.start_position = std::stod(laneSection.attribute("s").value());
elevationProfile.elevation = std::stod(laneSection.attribute("a").value());
elevationProfile.slope = std::stod(laneSection.attribute("b").value());
elevationProfile.vertical_curvature = std::stod(laneSection.attribute("c").value());
elevationProfile.curvature_change = std::stod(laneSection.attribute("d").value());
#include "carla/road/MapBuilder.h"
out_elevation_profile.emplace_back(elevationProfile);
}
}
namespace carla {
namespace opendrive {
namespace parser {
void carla::opendrive::parser::ProfilesParser::ParseLateral(
const pugi::xml_node &xmlNode,
std::vector<carla::opendrive::types::LateralProfile> &out_lateral_profile) {
for (pugi::xml_node laneSection = xmlNode.child("superelevation");
laneSection;
laneSection = laneSection.next_sibling("superelevation")) {
carla::opendrive::types::LateralProfile lateralProfile;
void ProfilesParser::Parse(
const pugi::xml_document &/* xml */,
carla::road::MapBuilder &/* map_builder */) {}
lateralProfile.start_position = std::stod(laneSection.attribute("s").value());
lateralProfile.elevation = std::stod(laneSection.attribute("a").value());
lateralProfile.slope = std::stod(laneSection.attribute("b").value());
lateralProfile.vertical_curvature = std::stod(laneSection.attribute("c").value());
lateralProfile.curvature_change = std::stod(laneSection.attribute("d").value());
out_lateral_profile.emplace_back(lateralProfile);
}
}
void carla::opendrive::parser::ProfilesParser::Parse(
const pugi::xml_node &xmlNode,
carla::opendrive::types::RoadProfiles &out_road_profiles) {
carla::opendrive::parser::ProfilesParser profilesParser;
profilesParser.ParseElevation(xmlNode.child("elevationProfile"), out_road_profiles.elevation_profile);
profilesParser.ParseLateral(xmlNode.child("lateralProfile"), out_road_profiles.lateral_profile);
}
} // namespace parser
} // namespace opendrive
} // namespace carla

View File

@ -6,32 +6,28 @@
#pragma once
#include "../types.h"
#include "./pugixml/pugixml.hpp"
namespace pugi {
class xml_document;
} // namespace pugi
namespace carla {
namespace road {
class MapBuilder;
} // namespace road
namespace opendrive {
namespace parser {
class ProfilesParser {
private:
void ParseElevation(
const pugi::xml_node &xmlNode,
std::vector<carla::opendrive::types::ElevationProfile> &out_elevation_profile);
void ParseLateral(
const pugi::xml_node &xmlNode,
std::vector<carla::opendrive::types::LateralProfile> &out_lateral_profile);
public:
static void Parse(
const pugi::xml_node &xmlNode,
carla::opendrive::types::RoadProfiles &out_road_profiles);
const pugi::xml_document &xml,
carla::road::MapBuilder &map_builder);
};
}
}
}
} // namespace parser
} // namespace opendrive
} // namespace carla

View File

@ -4,33 +4,20 @@
// This work is licensed under the terms of the MIT license.
// For a copy, see <https://opensource.org/licenses/MIT>.
#include "RoadLinkParser.h"
#include "carla/opendrive/parser/RoadLinkParser.h"
#include <cstdlib>
#include "carla/opendrive/pugixml/pugixml.hpp"
void carla::opendrive::parser::RoadLinkParser::ParseLink(
const pugi::xml_node &xmlNode,
carla::opendrive::types::RoadLinkInformation *out_link_information) {
out_link_information->id = std::atoi(xmlNode.attribute("elementId").value());
out_link_information->element_type = xmlNode.attribute("elementType").value();
out_link_information->contact_point = xmlNode.attribute("contactPoint").value();
}
#include "carla/road/MapBuilder.h"
void carla::opendrive::parser::RoadLinkParser::Parse(
const pugi::xml_node &xmlNode,
carla::opendrive::types::RoadLink &out_road_link) {
RoadLinkParser parser;
namespace carla {
namespace opendrive {
namespace parser {
const pugi::xml_node predecessorNode = xmlNode.child("predecessor");
const pugi::xml_node successorNode = xmlNode.child("successor");
void RoadLinkParser::Parse(
const pugi::xml_document &/* xml */,
carla::road::MapBuilder &/* map_builder */) {}
if (predecessorNode) {
out_road_link.predecessor = std::make_unique<carla::opendrive::types::RoadLinkInformation>();
parser.ParseLink(predecessorNode, out_road_link.predecessor.get());
}
if (successorNode) {
out_road_link.successor = std::make_unique<carla::opendrive::types::RoadLinkInformation>();
parser.ParseLink(successorNode, out_road_link.successor.get());
}
}
} // namespace parser
} // namespace opendrive
} // namespace carla

View File

@ -6,28 +6,28 @@
#pragma once
#include "../types.h"
#include "./pugixml/pugixml.hpp"
namespace pugi {
class xml_document;
} // namespace pugi
namespace carla {
namespace road {
class MapBuilder;
} // namespace road
namespace opendrive {
namespace parser {
class RoadLinkParser {
private:
void ParseLink(
const pugi::xml_node &xmlNode,
carla::opendrive::types::RoadLinkInformation *out_link_information);
public:
static void Parse(
const pugi::xml_node &xmlNode,
carla::opendrive::types::RoadLink &out_road_link);
const pugi::xml_document &xml,
carla::road::MapBuilder &map_builder);
};
}
}
}
} // namespace parser
} // namespace opendrive
} // namespace carla

View File

@ -4,62 +4,20 @@
// This work is licensed under the terms of the MIT license.
// For a copy, see <https://opensource.org/licenses/MIT>.
#include "TrafficGroupParser.h"
#include <iostream>
#include "carla/opendrive/parser/TrafficGroupParser.h"
void carla::opendrive::parser::TrafficGroupParser::Parse(
const pugi::xml_node &xmlNode,
std::vector<carla::opendrive::types::TrafficLightGroup> &out_trafficLights) {
carla::opendrive::parser::TrafficGroupParser parser;
carla::opendrive::types::TrafficLightGroup traffic_light_group;
#include "carla/opendrive/pugixml/pugixml.hpp"
traffic_light_group.red_time = std::atoi(xmlNode.attribute("redTime").value());
traffic_light_group.yellow_time = std::atoi(xmlNode.attribute("yellowTime").value());
traffic_light_group.green_time = std::atoi(xmlNode.attribute("greenTime").value());
#include "carla/road/MapBuilder.h"
parser.ParseTrafficLight(xmlNode, traffic_light_group.traffic_lights);
out_trafficLights.emplace_back(traffic_light_group);
}
namespace carla {
namespace opendrive {
namespace parser {
void carla::opendrive::parser::TrafficGroupParser::ParseTrafficLight(
const pugi::xml_node &xmlNode,
std::vector<carla::opendrive::types::TrafficLight> &out_trafficLight) {
void TrafficGroupParser::Parse(
const pugi::xml_document &/* xml */,
carla::road::MapBuilder &/* map_builder */) {}
for (pugi::xml_node trafficlight = xmlNode.child("trafficlight");
trafficlight;
trafficlight = trafficlight.next_sibling("trafficlight")) {
carla::opendrive::types::TrafficLight jTrafficlight;
jTrafficlight.x_pos = std::stod(trafficlight.attribute("xPos").value());
jTrafficlight.y_pos = std::stod(trafficlight.attribute("yPos").value());
jTrafficlight.z_pos = std::stod(trafficlight.attribute("zPos").value());
jTrafficlight.x_rot = std::stod(trafficlight.attribute("xRot").value());
jTrafficlight.y_rot = std::stod(trafficlight.attribute("yRot").value());
jTrafficlight.z_rot = std::stod(trafficlight.attribute("zRot").value());
ParseBoxAreas(trafficlight, jTrafficlight.box_areas);
out_trafficLight.emplace_back(jTrafficlight);
}
}
void carla::opendrive::parser::TrafficGroupParser::ParseBoxAreas(
const pugi::xml_node &xmlNode,
std::vector<carla::opendrive::types::BoxComponent> &out_boxcomponent) {
for (pugi::xml_node boxcomponent = xmlNode.child("tfBox");
boxcomponent;
boxcomponent = boxcomponent.next_sibling("tfBox")) {
carla::opendrive::types::BoxComponent jBoxComponent;
jBoxComponent.x_pos = std::stod(boxcomponent.attribute("xPos").value());
jBoxComponent.y_pos = std::stod(boxcomponent.attribute("yPos").value());
jBoxComponent.z_pos = std::stod(boxcomponent.attribute("zPos").value());
jBoxComponent.x_rot = std::stod(boxcomponent.attribute("xRot").value());
jBoxComponent.y_rot = std::stod(boxcomponent.attribute("yRot").value());
jBoxComponent.z_rot = std::stod(boxcomponent.attribute("zRot").value());
out_boxcomponent.emplace_back(jBoxComponent);
}
}
} // namespace parser
} // namespace opendrive
} // namespace carla

View File

@ -6,33 +6,28 @@
#pragma once
#include "../types.h"
#include "./pugixml/pugixml.hpp"
namespace pugi {
class xml_document;
} // namespace pugi
namespace carla {
namespace road {
class MapBuilder;
} // namespace road
namespace opendrive {
namespace parser {
class TrafficGroupParser {
private:
void ParseTrafficLight(
const pugi::xml_node &xmlNode,
std::vector<carla::opendrive::types::TrafficLight> &out_trafficLights);
void ParseBoxAreas(
const pugi::xml_node &xmlNode,
std::vector<carla::opendrive::types::BoxComponent> &out_boxareas);
public:
static void Parse(
const pugi::xml_node &xmlNode,
std::vector<carla::opendrive::types::TrafficLightGroup> &out_trafficlightgroup);
const pugi::xml_document &xml,
carla::road::MapBuilder &map_builder);
};
}
}
}
} // namespace parser
} // namespace opendrive
} // namespace carla

View File

@ -4,43 +4,20 @@
// This work is licensed under the terms of the MIT license.
// For a copy, see <https://opensource.org/licenses/MIT>.
#include "TrafficSignParser.h"
#include <iostream>
#include "carla/opendrive/parser/TrafficSignParser.h"
void carla::opendrive::parser::TrafficSignParser::Parse(
const pugi::xml_node &xmlNode,
std::vector<carla::opendrive::types::TrafficSign> &out_trafficsigns) {
carla::opendrive::parser::TrafficSignParser parser;
carla::opendrive::types::TrafficSign trafficsign;
#include "carla/opendrive/pugixml/pugixml.hpp"
trafficsign.speed = std::atoi(xmlNode.attribute("speed").value());
trafficsign.x_pos = std::stod(xmlNode.attribute("xPos").value());
trafficsign.y_pos = std::stod(xmlNode.attribute("yPos").value());
trafficsign.z_pos = std::stod(xmlNode.attribute("zPos").value());
trafficsign.x_rot = std::stod(xmlNode.attribute("xRot").value());
trafficsign.y_rot = std::stod(xmlNode.attribute("yRot").value());
trafficsign.z_rot = std::stod(xmlNode.attribute("zRot").value());
#include "carla/road/MapBuilder.h"
parser.ParseBoxAreas(xmlNode, trafficsign.box_areas);
out_trafficsigns.emplace_back(trafficsign);
}
namespace carla {
namespace opendrive {
namespace parser {
void carla::opendrive::parser::TrafficSignParser::ParseBoxAreas(
const pugi::xml_node &xmlNode,
std::vector<carla::opendrive::types::BoxComponent> &out_boxcomponent) {
for (pugi::xml_node boxcomponent = xmlNode.child("tsBox");
boxcomponent;
boxcomponent = boxcomponent.next_sibling("tsBox")) {
carla::opendrive::types::BoxComponent jBoxComponent;
void TrafficSignParser::Parse(
const pugi::xml_document &/* xml */,
carla::road::MapBuilder &/* map_builder */) {}
jBoxComponent.x_pos = std::stod(boxcomponent.attribute("xPos").value());
jBoxComponent.y_pos = std::stod(boxcomponent.attribute("yPos").value());
jBoxComponent.z_pos = std::stod(boxcomponent.attribute("zPos").value());
jBoxComponent.x_rot = std::stod(boxcomponent.attribute("xRot").value());
jBoxComponent.y_rot = std::stod(boxcomponent.attribute("yRot").value());
jBoxComponent.z_rot = std::stod(boxcomponent.attribute("zRot").value());
out_boxcomponent.emplace_back(jBoxComponent);
}
}
} // namespace parser
} // namespace opendrive
} // namespace carla

View File

@ -6,29 +6,28 @@
#pragma once
#include "../types.h"
#include "./pugixml/pugixml.hpp"
namespace pugi {
class xml_document;
} // namespace pugi
namespace carla {
namespace road {
class MapBuilder;
} // namespace road
namespace opendrive {
namespace parser {
class TrafficSignParser {
private:
void ParseBoxAreas(
const pugi::xml_node &xmlNode,
std::vector<carla::opendrive::types::BoxComponent> &out_boxareas);
public:
static void Parse(
const pugi::xml_node &xmlNode,
std::vector<carla::opendrive::types::TrafficSign> &out_trafficsigns);
const pugi::xml_document &xml,
carla::road::MapBuilder &map_builder);
};
}
}
}
} // namespace parser
} // namespace opendrive
} // namespace carla

View File

@ -4,30 +4,20 @@
// This work is licensed under the terms of the MIT license.
// For a copy, see <https://opensource.org/licenses/MIT>.
#include "TrafficSignalsParser.h"
#include "carla/opendrive/parser/TrafficSignalsParser.h"
void carla::opendrive::parser::TrafficSignalsParser::Parse(
const pugi::xml_node &xmlNode,
std::vector<carla::opendrive::types::TrafficSignalInformation> &out_traffic_signals) {
for (pugi::xml_node signal = xmlNode.child("signal"); signal; signal = signal.next_sibling("signal")) {
carla::opendrive::types::TrafficSignalInformation trafficSignalInformation;
#include "carla/opendrive/pugixml/pugixml.hpp"
trafficSignalInformation.id = std::atoi(signal.attribute("id").value());
#include "carla/road/MapBuilder.h"
trafficSignalInformation.start_position = std::stod(signal.attribute("s").value());
trafficSignalInformation.track_position = std::stod(signal.attribute("t").value());
namespace carla {
namespace opendrive {
namespace parser {
trafficSignalInformation.zoffset = std::stod(signal.attribute("zOffset").value());
trafficSignalInformation.value = std::stod(signal.attribute("value").value());
void TrafficSignalsParser::Parse(
const pugi::xml_document &/* xml */,
carla::road::MapBuilder &/* map_builder */) {}
trafficSignalInformation.name = signal.attribute("name").value();
trafficSignalInformation.dynamic = signal.attribute("dynamic").value();
trafficSignalInformation.orientation = signal.attribute("orientation").value();
trafficSignalInformation.type = signal.attribute("type").value();
trafficSignalInformation.subtype = signal.attribute("subtype").value();
trafficSignalInformation.country = signal.attribute("country").value();
out_traffic_signals.emplace_back(trafficSignalInformation);
}
}
} // namespace parser
} // namespace opendrive
} // namespace carla

View File

@ -6,11 +6,16 @@
#pragma once
#include "../types.h"
#include "./pugixml/pugixml.hpp"
namespace pugi {
class xml_document;
} // namespace pugi
namespace carla {
namespace road {
class MapBuilder;
} // namespace road
namespace opendrive {
namespace parser {
@ -18,10 +23,11 @@ namespace parser {
public:
static void Parse(
const pugi::xml_node &xmlNode,
std::vector<carla::opendrive::types::TrafficSignalInformation> &out_traffic_signals);
const pugi::xml_document &xml,
carla::road::MapBuilder &map_builder);
};
}
}
}
} // namespace parser
} // namespace opendrive
} // namespace carla

View File

@ -1,335 +0,0 @@
// Copyright (c) 2017 Computer Vision Center (CVC) at the Universitat Autonoma
// de Barcelona (UAB).
//
// This work is licensed under the terms of the MIT license.
// For a copy, see <https://opensource.org/licenses/MIT>.
#pragma once
#include "carla/geom/GeoLocation.h"
#include <memory>
#include <string>
#include <vector>
namespace carla {
namespace opendrive {
namespace types {
enum class GeometryType : unsigned int {
ARC,
LINE,
SPIRAL
};
struct GeometryAttributes {
GeometryType type; // geometry type
double length; // length of the road section
// [meters]
double start_position; // s-offset [meters]
double heading; // start orientation [radians]
double start_position_x; // [meters]
double start_position_y; // [meters]
};
struct GeometryAttributesArc : public GeometryAttributes {
double curvature;
};
struct GeometryAttributesLine : public GeometryAttributes {
// Nothing else here
};
struct GeometryAttributesSpiral : public GeometryAttributes {
double curve_start;
double curve_end;
};
/////////////////////////////////////////////////////////////////
struct LaneAttributes {
int id;
std::string type;
std::string level;
};
struct LaneWidth {
double soffset; // start position (s-offset)
// [meters]
double width; // a - width [meters]
double slope; // b
double vertical_curvature; // c
double curvature_change; // d
};
struct LaneRoadMark {
double soffset = 0.0;
double width = 0.0;
std::string type;
std::string weigth = "standard";
// See OpenDRIVE Format Specification, Rev. 1.4
// Doc No.: VI2014.107 (5.3.7.2.1.1.4 Road Mark Record)
std::string material = "standard";
std::string color = "white";
std::string lane_change = "none";
};
struct LaneOffset {
double s, a, b, c, d;
};
struct LaneSpeed {
double soffset; // start position(s - offset from the
// current lane section) [meters]
double max_speed; // maximum allowed speed [meters/second]
};
struct LaneLink {
int predecessor_id;
int successor_id;
};
struct LaneInfo {
std::vector<LaneSpeed> lane_speed;
LaneAttributes attributes;
std::vector<LaneWidth> lane_width;
std::vector<LaneRoadMark> road_marker;
std::unique_ptr<LaneLink> link;
};
struct LaneSection {
double start_position;
std::vector<LaneInfo> left, center, right;
};
struct Lanes {
std::vector<LaneOffset> lane_offset;
std::vector<LaneSection> lane_sections;
};
/////////////////////////////////////////////////////////////////
struct ElevationProfile {
double start_position; // (S) start position(s -
// offset)[meters]
double elevation; // (A) elevation [meters]
double slope; // (B)
double vertical_curvature; // (C)
double curvature_change; // (D)
};
struct LateralProfile {
double start_position; // (S) start position(s -
// offset)[meters]
double elevation; // (A) elevation [meters]
double slope; // (B)
double vertical_curvature; // (C)
double curvature_change; // (D)
};
struct RoadProfiles {
std::vector<ElevationProfile> elevation_profile;
std::vector<LateralProfile> lateral_profile;
};
/////////////////////////////////////////////////////////////////
struct TrafficSignalInformation {
int id;
double start_position; // s
double track_position; // t
double zoffset; // z offset from track level
double value; // value of the signal (e.g. speed,
// mass <20> depending on type)
std::string name; // name of the signal (e.g. gfx bead
// name)
std::string dynamic; // boolean identification whether
// signal is a dynamic
// signal(e.g.traffic light)
std::string orientation; // "+" = valid in positive track
// direction; "-" = valid in
// negative track direction; "none"
// = valid in both directions
std::string country; // country code of the signa
std::string type; // type identifier according to
// country code or "-1" / "none"
std::string subtype; // subtype identifier according to
// country code or "-1" / "none"
};
/////////////////////////////////////////////////////////////////
struct RoadAttributes {
std::string name;
int id, junction;
double length;
RoadAttributes() : id(-1),
junction(-1),
length(0.0) {}
};
struct RoadLinkInformation {
int id;
std::string element_type;
std::string contact_point;
RoadLinkInformation() : id(-1) {}
};
struct RoadLink {
std::unique_ptr<RoadLinkInformation> successor;
std::unique_ptr<RoadLinkInformation> predecessor;
};
struct RoadInformation {
RoadLink road_link;
RoadProfiles road_profiles;
RoadAttributes attributes;
Lanes lanes;
std::vector<TrafficSignalInformation> trafic_signals;
std::vector<std::unique_ptr<GeometryAttributes>> geometry_attributes;
};
/////////////////////////////////////////////////////////////////
struct JunctionAttribues {
int id;
std::string name;
JunctionAttribues() : id(-1) {}
};
struct JunctionConnectionAttributes {
int id;
int incoming_road;
int connecting_road;
std::string contact_point;
JunctionConnectionAttributes() : id(-1),
incoming_road(-1),
connecting_road(-1) {}
};
struct JunctionLaneLink {
int from;
int to;
JunctionLaneLink() : from(-1),
to(-1) {}
};
struct JunctionConnection {
JunctionConnectionAttributes attributes;
std::vector<JunctionLaneLink> links;
};
struct Junction {
JunctionAttribues attributes;
std::vector<JunctionConnection> connections;
};
struct BoxComponent {
union {
struct { double x_pos, y_pos, z_pos;
};
double pos[3];
};
union {
struct { double x_rot, y_rot, z_rot;
};
double rot[3];
};
double scale;
BoxComponent() : pos{0.0, 0.0, 0.0},
rot{0.0, 0.0, 0.0},
scale(1.0) {}
};
struct TrafficLight {
union {
struct { double x_pos, y_pos, z_pos;
};
double pos[3];
};
union {
struct { double x_rot, y_rot, z_rot;
};
double rot[3];
};
double scale;
std::vector<BoxComponent> box_areas;
TrafficLight() : pos{0.0, 0.0, 0.0},
rot{0.0, 0.0, 0.0},
scale(1.0) {}
};
struct TrafficLightGroup {
std::vector<TrafficLight> traffic_lights;
double red_time, yellow_time, green_time;
};
struct TrafficSign {
union {
struct { double x_pos, y_pos, z_pos;
};
double pos[3];
};
union {
struct { double x_rot, y_rot, z_rot;
};
double rot[3];
};
double scale;
int speed;
std::vector<BoxComponent> box_areas;
TrafficSign() : pos{0.0, 0.0, 0.0},
rot{0.0, 0.0, 0.0},
scale(1.0),
speed(30) {}
};
/////////////////////////////////////////////////////////////////
struct OpenDriveData {
geom::GeoLocation geoReference;
std::vector<RoadInformation> roads;
std::vector<Junction> junctions;
std::vector<TrafficLightGroup> trafficlightgroups;
std::vector<TrafficSign> trafficsigns;
};
struct Waypoint {
union {
struct { double x, y, z;
};
double v[3];
};
double heading, speed, width;
double distance_in_section;
Waypoint() : v{0.0, 0.0, 0.0},
heading(0.0),
speed(0.0),
width(0.0) {}
};
}
}
}

View File

@ -6,6 +6,9 @@
#include "carla/road/Map.h"
#include <stdexcept>
#include "carla/Exception.h"
#include "carla/road/element/LaneCrossingCalculator.h"
namespace carla {
@ -17,22 +20,24 @@ namespace road {
return Waypoint(shared_from_this(), loc);
}
boost::optional<Waypoint> Map::GetWaypoint(const geom::Location &loc) const {
Waypoint w = Waypoint(shared_from_this(), loc);
auto d = geom::Math::Distance2D(w.ComputeTransform().location, loc);
const auto inf = _data.GetRoad(w._road_id)->GetInfo<RoadInfoLane>(w._dist);
if (d < inf->getLane(w._lane_id)->_width * 0.5) {
return w;
}
boost::optional<Waypoint> Map::GetWaypoint(const geom::Location &/* loc */) const {
// Waypoint w = Waypoint(shared_from_this(), loc);
// auto d = geom::Math::Distance2D(w.ComputeTransform().location, loc);
// const auto inf = _data.GetRoad(w._road_id)->GetInfo<RoadInfoLane>(w._dist);
// if (d < inf->getLane(w._lane_id)->_width * 0.5) {
// return w;
// }
throw_exception(std::runtime_error("not implemented"));
return {};
}
std::vector<element::LaneMarking> Map::CalculateCrossedLanes(
const geom::Location &origin,
const geom::Location &destination) const {
return element::LaneCrossingCalculator::Calculate(*this, origin, destination);
const geom::Location &/* origin */,
const geom::Location &/* destination */) const {
// return element::LaneCrossingCalculator::Calculate(*this, origin, destination);
throw_exception(std::runtime_error("not implemented"));
return {};
}
const MapData &Map::GetData() const {

View File

@ -12,94 +12,17 @@ using namespace carla::road::element;
namespace carla {
namespace road {
bool MapBuilder::AddRoadSegmentDefinition(RoadSegmentDefinition &seg) {
_temp_sections.emplace(seg.GetId(), std::move(seg));
return true;
}
SharedPtr<Map> MapBuilder::Build() {
// Move the RoadSegmentDefinitions needed information to a RoadSegments
for (auto &&id_seg : _temp_sections) {
MakeElement<RoadSegment>(id_seg.first, std::move(id_seg.second));
}
SetTotalRoadSegmentLength();
CreatePointersBetweenRoadSegments();
ComputeLaneCenterOffset();
// _map_data is a memeber of MapBuilder so you must especify if
// you want to keep it (will return copy -> Map(const Map &))
// or move it (will return move -> Map(Map &&))
return SharedPtr<Map>(new Map{std::move(_map_data)});
}
void MapBuilder::SetTotalRoadSegmentLength() {
for (auto &&id_seg : _map_data._elements) {
double total_length = 0.0;
for (auto &&geom : id_seg.second.get()->_geom) {
total_length += geom.get()->GetLength();
}
id_seg.second.get()->_length = total_length;
}
}
void MapBuilder::CreatePointersBetweenRoadSegments() {
for (auto &&id_seg : _temp_sections) {
for (auto &t : id_seg.second.GetPredecessorID()) {
_map_data._elements[id_seg.first]->PredEmplaceBack(_map_data._elements[t].get());
}
for (auto &t : id_seg.second.GetSuccessorID()) {
_map_data._elements[id_seg.first]->SuccEmplaceBack(_map_data._elements[t].get());
}
}
}
void MapBuilder::ComputeLaneCenterOffset() {
for (auto &&element : _map_data._elements) {
RoadSegment *road_seg = element.second.get();
// get all the RoadGeneralInfo given the type and a distance 0.0
auto up_bound_g = decltype(road_seg->_info)::reverse_iterator(road_seg->_info.upper_bound(0.0));
auto general_info = MakeRoadInfoIterator<RoadGeneralInfo>(up_bound_g, road_seg->_info.rend());
// get all the RoadInfoLane given the type and a distance 0.0
auto up_bound_l = decltype(road_seg->_info)::reverse_iterator(road_seg->_info.upper_bound(0.0));
auto lane_info = MakeRoadInfoIterator<RoadInfoLane>(up_bound_l, road_seg->_info.rend());
// check that have a RoadGeneralInfo
if (!lane_info.IsAtEnd()) {
double lane_offset = 0.0;
if (!general_info.IsAtEnd()) {
lane_offset = (*general_info)->GetLanesOffset().at(0).second;
}
double current_width = lane_offset;
for (auto &&current_lane_id :
(*lane_info)->getLanesIDs(element::RoadInfoLane::which_lane_e::Left)) {
const double half_width = (*lane_info)->getLane(current_lane_id)->_width * 0.5;
current_width += half_width;
(*lane_info)->_lanes[current_lane_id]._lane_center_offset = current_width;
current_width += half_width;
}
current_width = lane_offset;
for (auto &&current_lane_id :
(*lane_info)->getLanesIDs(element::RoadInfoLane::which_lane_e::Right)) {
const double half_width = (*lane_info)->getLane(current_lane_id)->_width * 0.5;
current_width -= half_width;
(*lane_info)->_lanes[current_lane_id]._lane_center_offset = current_width;
current_width -= half_width;
}
}
}
}
} // namespace road
} // namespace carla

View File

@ -17,49 +17,17 @@ namespace road {
class MapBuilder {
public:
bool AddRoadSegmentDefinition(element::RoadSegmentDefinition &seg);
void SetJunctionInformation(const std::vector<carla::road::lane_junction_t> &junctionInfo) {
_map_data.SetJunctionInformation(junctionInfo);
}
void SetGeoReference(const geom::GeoLocation &geoReference) {
_map_data.SetGeoReference(geoReference);
}
void SetTrafficGroupData(const std::vector<opendrive::types::TrafficLightGroup> &trafficLightData) {
_map_data.SetTrafficLightData(trafficLightData);
}
void SetTrafficSignData(const std::vector<opendrive::types::TrafficSign> &trafficSignData) {
_map_data.SetTrafficSignData(trafficSignData);
}
SharedPtr<Map> Build();
private:
template <typename T, typename ... Args>
T &MakeElement(element::id_type id, Args && ... args) {
auto inst = std::make_unique<T>(std::forward<Args>(args) ...);
T &r = *inst;
_map_data._elements.emplace(id, std::move(inst));
return r;
}
/// Set the total length of each road based on the geometries
void SetTotalRoadSegmentLength();
/// Create the pointers between RoadSegments based on the ids
void CreatePointersBetweenRoadSegments();
/// Set the _lane_center_offset of all the lanes
void ComputeLaneCenterOffset();
private:
MapData _map_data;
std::map<element::id_type, element::RoadSegmentDefinition> _temp_sections;
};
} // namespace road

View File

@ -10,7 +10,7 @@
#include "carla/ListView.h"
#include "carla/NonCopyable.h"
#include "carla/road/element/RoadSegment.h"
#include "carla/opendrive/types.h"
#include "carla/geom/GeoLocation.h"
#include <boost/iterator/transform_iterator.hpp>
@ -19,93 +19,21 @@
namespace carla {
namespace road {
struct lane_junction_t {
std::string contact_point = "start";
int junction_id = -1;
int connection_road = -1;
int incomming_road = -1;
std::vector<int> from_lane;
std::vector<int> to_lane;
};
class MapData
: private MovableNonCopyable {
class MapData : private MovableNonCopyable {
public:
const element::RoadSegment *GetRoad(element::id_type id) const {
auto it = _elements.find(id);
return it != _elements.end() ? it->second.get() : nullptr;
}
auto GetAllIds() const {
return MakeListView(
iterator::make_map_keys_iterator(_elements.begin()),
iterator::make_map_keys_iterator(_elements.end()));
}
size_t GetRoadCount() const {
return _elements.size();
}
const std::vector<lane_junction_t> &GetJunctionInformation() const {
return _junction_information;
}
const geom::GeoLocation &GetGeoReference() const {
return _geo_reference;
}
const std::vector<opendrive::types::TrafficLightGroup> &GetTrafficGroups() const {
return _traffic_groups;
}
const std::vector<opendrive::types::TrafficSign> &GetTrafficSigns() const {
return _traffic_signs;
}
auto GetRoadSegments() const {
using const_ref = const element::RoadSegment &;
auto get = [](auto &pair) -> const_ref { return *pair.second; };
return MakeListView(
boost::make_transform_iterator(_elements.begin(), get),
boost::make_transform_iterator(_elements.end(), get));
}
private:
friend class MapBuilder;
MapData() = default;
void SetJunctionInformation(const std::vector<lane_junction_t> &junctionInfo) {
_junction_information = junctionInfo;
}
void SetGeoReference(const geom::GeoLocation &geoReference) {
_geo_reference = geoReference;
}
void SetTrafficLightData(const std::vector<opendrive::types::TrafficLightGroup> &trafficLightData) {
_traffic_groups = trafficLightData;
}
void SetTrafficSignData(const std::vector<opendrive::types::TrafficSign> &trafficSignData) {
_traffic_signs = trafficSignData;
}
geom::GeoLocation _geo_reference;
std::vector<lane_junction_t> _junction_information;
std::unordered_map<
element::id_type,
std::unique_ptr<element::RoadSegment>> _elements;
std::vector<opendrive::types::TrafficLightGroup> _traffic_groups;
std::vector<opendrive::types::TrafficSign> _traffic_signs;
};
} // namespace road

View File

@ -6,6 +6,9 @@
#include "carla/road/WaypointGenerator.h"
#include <stdexcept>
#include "carla/Exception.h"
#include "carla/road/Map.h"
namespace carla {
@ -18,210 +21,228 @@ namespace road {
// ===========================================================================
template <typename T>
static std::vector<T> ConcatVectors(std::vector<T> dst, std::vector<T> src) {
if (src.size() > dst.size()) {
return ConcatVectors(src, dst);
}
dst.insert(
dst.end(),
std::make_move_iterator(src.begin()),
std::make_move_iterator(src.end()));
return dst;
static std::vector<T> ConcatVectors(std::vector<T> /* dst */, std::vector<T> /* src */) {
// if (src.size() > dst.size()) {
// return ConcatVectors(src, dst);
// }
// dst.insert(
// dst.end(),
// std::make_move_iterator(src.begin()),
// std::make_move_iterator(src.end()));
// return dst;
return {};
}
template <typename FuncT>
static void ForEachDrivableLane(const RoadSegment &road, double s, FuncT &&func) {
const auto info = road.GetInfo<RoadInfoLane>(s);
DEBUG_ASSERT(info != nullptr);
for (auto &&lane_id : info->getLanesIDs(RoadInfoLane::which_lane_e::Both)) {
if (info->getLane(lane_id)->_type == "driving") {
func(lane_id);
}
}
static void ForEachDrivableLane(const RoadSegment &/* road */, double /* s */, FuncT &&/* func */) {
throw_exception(std::runtime_error("not implemented"));
// const auto info = road.GetInfo<RoadInfoLane>(s);
// DEBUG_ASSERT(info != nullptr);
// for (auto &&lane_id : info->getLanesIDs(RoadInfoLane::which_lane_e::Both)) {
// if (info->getLane(lane_id)->_type == "driving") {
// func(lane_id);
// }
// }
}
// ===========================================================================
// -- WaypointGenerator ------------------------------------------------------
// ===========================================================================
std::vector<Waypoint> WaypointGenerator::GetSuccessors(const Waypoint &waypoint) {
auto &map = waypoint._map;
const auto this_lane_id = waypoint.GetLaneId();
const auto this_road_id = waypoint.GetRoadId();
std::vector<Waypoint> WaypointGenerator::GetSuccessors(const Waypoint &/* waypoint */) {
// auto &map = waypoint._map;
// const auto this_lane_id = waypoint.GetLaneId();
// const auto this_road_id = waypoint.GetRoadId();
const auto &next_lanes =
this_lane_id <= 0 ?
waypoint.GetRoadSegment().GetNextLane(this_lane_id) :
waypoint.GetRoadSegment().GetPrevLane(this_lane_id);
// const auto &next_lanes =
// this_lane_id <= 0 ?
// waypoint.GetRoadSegment().GetNextLane(this_lane_id) :
// waypoint.GetRoadSegment().GetPrevLane(this_lane_id);
if (next_lanes.empty()) {
log_error("road id =", this_road_id, "lane id =", this_lane_id, ": missing next lanes");
}
// if (next_lanes.empty()) {
// log_error("road id =", this_road_id, "lane id =", this_lane_id, ": missing next lanes");
// }
std::vector<Waypoint> result;
result.reserve(next_lanes.size());
for (auto &&pair : next_lanes) {
const auto lane_id = pair.first;
const auto road_id = pair.second;
const auto road = map->GetData().GetRoad(road_id);
DEBUG_ASSERT(lane_id != 0);
DEBUG_ASSERT(road != nullptr);
const auto distance = lane_id < 0 ? 0.0 : road->GetLength();
result.push_back(Waypoint(map, road_id, lane_id, distance));
}
return result;
// std::vector<Waypoint> result;
// result.reserve(next_lanes.size());
// for (auto &&pair : next_lanes) {
// const auto lane_id = pair.first;
// const auto road_id = pair.second;
// const auto road = map->GetData().GetRoad(road_id);
// DEBUG_ASSERT(lane_id != 0);
// DEBUG_ASSERT(road != nullptr);
// const auto distance = lane_id < 0 ? 0.0 : road->GetLength();
// result.push_back(Waypoint(map, road_id, lane_id, distance));
// }
// return result;
throw_exception(std::runtime_error("not implemented"));
return {};
}
std::vector<Waypoint> WaypointGenerator::GetNext(
const Waypoint &waypoint,
double distance) {
auto &map = waypoint._map;
const auto this_road_id = waypoint.GetRoadId();
const auto this_lane_id = waypoint.GetLaneId();
const Waypoint &/* waypoint */,
double /* distance */) {
// auto &map = waypoint._map;
// const auto this_road_id = waypoint.GetRoadId();
// const auto this_lane_id = waypoint.GetLaneId();
DEBUG_ASSERT(this_lane_id != 0);
// DEBUG_ASSERT(this_lane_id != 0);
double distance_on_next_segment;
// double distance_on_next_segment;
if (this_lane_id <= 0) {
// road goes forward.
const auto total_distance = waypoint._dist + distance;
const auto road_length = waypoint.GetRoadSegment().GetLength();
if (total_distance <= road_length) {
return { Waypoint(map, this_road_id, this_lane_id, total_distance) };
}
distance_on_next_segment = total_distance - road_length;
} else {
// road goes backward.
const auto total_distance = waypoint._dist - distance;
if (total_distance >= 0.0) {
return { Waypoint(map, this_road_id, this_lane_id, total_distance) };
}
distance_on_next_segment = std::abs(total_distance);
}
// if (this_lane_id <= 0) {
// // road goes forward.
// const auto total_distance = waypoint._dist + distance;
// const auto road_length = waypoint.GetRoadSegment().GetLength();
// if (total_distance <= road_length) {
// return { Waypoint(map, this_road_id, this_lane_id, total_distance) };
// }
// distance_on_next_segment = total_distance - road_length;
// } else {
// // road goes backward.
// const auto total_distance = waypoint._dist - distance;
// if (total_distance >= 0.0) {
// return { Waypoint(map, this_road_id, this_lane_id, total_distance) };
// }
// distance_on_next_segment = std::abs(total_distance);
// }
std::vector<Waypoint> result;
for (auto &&next_waypoint : GetSuccessors(waypoint)) {
result = ConcatVectors(result, GetNext(next_waypoint, distance_on_next_segment));
}
return result;
// std::vector<Waypoint> result;
// for (auto &&next_waypoint : GetSuccessors(waypoint)) {
// result = ConcatVectors(result, GetNext(next_waypoint, distance_on_next_segment));
// }
// return result;
throw_exception(std::runtime_error("not implemented"));
return {};
}
boost::optional<Waypoint> WaypointGenerator::GetRight(const Waypoint &waypoint) {
auto &map = waypoint._map;
const auto this_road_id = waypoint.GetRoadId();
const auto this_lane_id = waypoint.GetLaneId();
boost::optional<Waypoint> WaypointGenerator::GetRight(const Waypoint &/* waypoint */) {
// auto &map = waypoint._map;
// const auto this_road_id = waypoint.GetRoadId();
// const auto this_lane_id = waypoint.GetLaneId();
DEBUG_ASSERT(this_lane_id != 0);
// DEBUG_ASSERT(this_lane_id != 0);
const int new_lane_id = (this_lane_id <= 0) ? this_lane_id - 1 : this_lane_id + 1;
// const int new_lane_id = (this_lane_id <= 0) ? this_lane_id - 1 : this_lane_id + 1;
// check if that lane id exists on this distance
const auto road = map->GetData().GetRoad(this_road_id);
const auto mark_record_vector = road->GetRoadInfoMarkRecord(waypoint._dist);
for (auto &&mark_record : mark_record_vector) {
// find if the lane id exists
if (mark_record->GetLaneId() == new_lane_id) {
return Waypoint(map, this_road_id, new_lane_id, waypoint._dist);
}
}
return boost::optional<Waypoint>();
// // check if that lane id exists on this distance
// const auto road = map->GetData().GetRoad(this_road_id);
// const auto mark_record_vector = road->GetRoadInfoMarkRecord(waypoint._dist);
// for (auto &&mark_record : mark_record_vector) {
// // find if the lane id exists
// if (mark_record->GetLaneId() == new_lane_id) {
// return Waypoint(map, this_road_id, new_lane_id, waypoint._dist);
// }
// }
// return boost::optional<Waypoint>();
throw_exception(std::runtime_error("not implemented"));
return {};
}
boost::optional<Waypoint> WaypointGenerator::GetLeft(const Waypoint &waypoint) {
auto &map = waypoint._map;
const auto this_road_id = waypoint.GetRoadId();
const auto this_lane_id = waypoint.GetLaneId();
boost::optional<Waypoint> WaypointGenerator::GetLeft(const Waypoint &/* waypoint */) {
// auto &map = waypoint._map;
// const auto this_road_id = waypoint.GetRoadId();
// const auto this_lane_id = waypoint.GetLaneId();
DEBUG_ASSERT(this_lane_id != 0);
// DEBUG_ASSERT(this_lane_id != 0);
int new_lane_id;
if (this_lane_id > 0) {
// road goes backward: decrease the lane id while avoiding returning lane 0
new_lane_id = this_lane_id - 1 == 0 ? -1 : this_lane_id - 1;
} else {
// road goes forward: increasing the lane id while avoiding returning lane 0
new_lane_id = this_lane_id + 1 == 0 ? 1 : this_lane_id + 1;
}
// int new_lane_id;
// if (this_lane_id > 0) {
// // road goes backward: decrease the lane id while avoiding returning lane 0
// new_lane_id = this_lane_id - 1 == 0 ? -1 : this_lane_id - 1;
// } else {
// // road goes forward: increasing the lane id while avoiding returning lane 0
// new_lane_id = this_lane_id + 1 == 0 ? 1 : this_lane_id + 1;
// }
// check if that lane id exists on this distance
const auto road = map->GetData().GetRoad(this_road_id);
const auto mark_record_vector = road->GetRoadInfoMarkRecord(waypoint._dist);
for (auto &&mark_record : mark_record_vector) {
// find if the lane id exists
if (mark_record->GetLaneId() == new_lane_id) {
return Waypoint(map, this_road_id, new_lane_id, waypoint._dist);
}
}
return boost::optional<Waypoint>();
// // check if that lane id exists on this distance
// const auto road = map->GetData().GetRoad(this_road_id);
// const auto mark_record_vector = road->GetRoadInfoMarkRecord(waypoint._dist);
// for (auto &&mark_record : mark_record_vector) {
// // find if the lane id exists
// if (mark_record->GetLaneId() == new_lane_id) {
// return Waypoint(map, this_road_id, new_lane_id, waypoint._dist);
// }
// }
// return boost::optional<Waypoint>();
throw_exception(std::runtime_error("not implemented"));
return {};
}
std::vector<Waypoint> WaypointGenerator::GenerateAll(
const Map &map,
const double distance) {
std::vector<Waypoint> result;
for (auto &&road_segment : map.GetData().GetRoadSegments()) {
/// @todo Should distribute them equally along the segment?
for (double s = 0.0; s < road_segment.GetLength(); s += distance) {
ForEachDrivableLane(road_segment, s, [&](auto lane_id) {
result.push_back(Waypoint(map.shared_from_this(), road_segment.GetId(), lane_id, s));
});
}
}
return result;
const Map &/* map */,
const double /* distance */) {
// std::vector<Waypoint> result;
// for (auto &&road_segment : map.GetData().GetRoadSegments()) {
// /// @todo Should distribute them equally along the segment?
// for (double s = 0.0; s < road_segment.GetLength(); s += distance) {
// ForEachDrivableLane(road_segment, s, [&](auto lane_id) {
// result.push_back(Waypoint(map.shared_from_this(), road_segment.GetId(), lane_id, s));
// });
// }
// }
// return result;
throw_exception(std::runtime_error("not implemented"));
return {};
}
std::vector<Waypoint> WaypointGenerator::GenerateLaneBegin(
const Map &map) {
std::vector<Waypoint> result;
for (auto &&road_segment : map.GetData().GetRoadSegments()) {
ForEachDrivableLane(road_segment, 0.0, [&](auto lane_id) {
auto distance = lane_id < 0 ? 0.0 : road_segment.GetLength();
auto this_waypoint = Waypoint(
map.shared_from_this(),
road_segment.GetId(),
lane_id,
distance);
result.push_back(this_waypoint);
});
}
return result;
const Map &/* map */) {
// std::vector<Waypoint> result;
// for (auto &&road_segment : map.GetData().GetRoadSegments()) {
// ForEachDrivableLane(road_segment, 0.0, [&](auto lane_id) {
// auto distance = lane_id < 0 ? 0.0 : road_segment.GetLength();
// auto this_waypoint = Waypoint(
// map.shared_from_this(),
// road_segment.GetId(),
// lane_id,
// distance);
// result.push_back(this_waypoint);
// });
// }
// return result;
throw_exception(std::runtime_error("not implemented"));
return {};
}
std::vector<Waypoint> WaypointGenerator::GenerateLaneEnd(
const Map &map) {
std::vector<Waypoint> result;
for (auto &&road_segment : map.GetData().GetRoadSegments()) {
ForEachDrivableLane(road_segment, 0.0, [&](auto lane_id) {
auto distance = lane_id > 0 ? 0.0 : road_segment.GetLength();
auto this_waypoint = Waypoint(
map.shared_from_this(),
road_segment.GetId(),
lane_id,
distance);
result.push_back(this_waypoint);
});
}
return result;
const Map &/* map */) {
// std::vector<Waypoint> result;
// for (auto &&road_segment : map.GetData().GetRoadSegments()) {
// ForEachDrivableLane(road_segment, 0.0, [&](auto lane_id) {
// auto distance = lane_id > 0 ? 0.0 : road_segment.GetLength();
// auto this_waypoint = Waypoint(
// map.shared_from_this(),
// road_segment.GetId(),
// lane_id,
// distance);
// result.push_back(this_waypoint);
// });
// }
// return result;
throw_exception(std::runtime_error("not implemented"));
return {};
}
std::vector<std::pair<Waypoint, Waypoint>> WaypointGenerator::GenerateTopology(
const Map &map) {
std::vector<std::pair<Waypoint, Waypoint>> result;
for (auto &&road_segment : map.GetData().GetRoadSegments()) {
ForEachDrivableLane(road_segment, 0.0, [&](auto lane_id) {
auto distance = lane_id < 0 ? 0.0 : road_segment.GetLength();
auto this_waypoint = Waypoint(
map.shared_from_this(),
road_segment.GetId(),
lane_id,
distance);
for (auto &&successor : GetSuccessors(this_waypoint)) {
result.push_back({this_waypoint, successor});
}
});
}
return result;
const Map &/* map */) {
// std::vector<std::pair<Waypoint, Waypoint>> result;
// for (auto &&road_segment : map.GetData().GetRoadSegments()) {
// ForEachDrivableLane(road_segment, 0.0, [&](auto lane_id) {
// auto distance = lane_id < 0 ? 0.0 : road_segment.GetLength();
// auto this_waypoint = Waypoint(
// map.shared_from_this(),
// road_segment.GetId(),
// lane_id,
// distance);
// for (auto &&successor : GetSuccessors(this_waypoint)) {
// result.push_back({this_waypoint, successor});
// }
// });
// }
// return result;
throw_exception(std::runtime_error("not implemented"));
return {};
}
} // namespace road

View File

@ -10,6 +10,9 @@
#include "carla/geom/CubicPolynomial.h"
#include "carla/geom/Math.h"
#include <stdexcept>
#include "carla/Exception.h"
#include <unordered_map>
#include <algorithm>
@ -17,64 +20,65 @@ namespace carla {
namespace road {
namespace element {
Waypoint::Waypoint(SharedPtr<const Map> m, const geom::Location &loc)
Waypoint::Waypoint(SharedPtr<const Map> m, const geom::Location &/* loc */)
: _map(m) {
DEBUG_ASSERT(_map != nullptr);
// max_nearests represents the max nearests roads
// where we will search for nearests lanes
constexpr int max_nearests = 10;
// in case that map has less than max_nearests lanes,
// we will use the maximum lanes
const int max_nearest_allowed = _map->GetData().GetRoadCount() <
max_nearests ? _map->GetData().GetRoadCount() : max_nearests;
throw_exception(std::runtime_error("not implemented"));
// DEBUG_ASSERT(_map != nullptr);
// // max_nearests represents the max nearests roads
// // where we will search for nearests lanes
// constexpr int max_nearests = 10;
// // in case that map has less than max_nearests lanes,
// // we will use the maximum lanes
// const int max_nearest_allowed = _map->GetData().GetRoadCount() <
// max_nearests ? _map->GetData().GetRoadCount() : max_nearests;
double nearest_dist[max_nearests];
std::fill(nearest_dist, nearest_dist + max_nearest_allowed,
std::numeric_limits<double>::max());
// double nearest_dist[max_nearests];
// std::fill(nearest_dist, nearest_dist + max_nearest_allowed,
// std::numeric_limits<double>::max());
id_type ids[max_nearests];
std::fill(ids, ids + max_nearest_allowed, 0);
// id_type ids[max_nearests];
// std::fill(ids, ids + max_nearest_allowed, 0);
double dists[max_nearests];
std::fill(dists, dists + max_nearest_allowed, 0.0);
// double dists[max_nearests];
// std::fill(dists, dists + max_nearest_allowed, 0.0);
for (auto &&r : _map->GetData().GetRoadSegments()) {
auto current_dist = r.GetNearestPoint(loc);
// for (auto &&r : _map->GetData().GetRoadSegments()) {
// auto current_dist = r.GetNearestPoint(loc);
// search for nearests points
for (int i = 0; i < max_nearest_allowed; ++i) {
if (current_dist.second < nearest_dist[i]) {
// reorder nearest_dist
for (int j = max_nearest_allowed - 1; j > i; --j) {
nearest_dist[j] = nearest_dist[j - 1];
ids[j] = ids[j - 1];
dists[j] = dists[j - 1];
}
nearest_dist[i] = current_dist.second;
ids[i] = r.GetId();
dists[i] = current_dist.first;
// // search for nearests points
// for (int i = 0; i < max_nearest_allowed; ++i) {
// if (current_dist.second < nearest_dist[i]) {
// // reorder nearest_dist
// for (int j = max_nearest_allowed - 1; j > i; --j) {
// nearest_dist[j] = nearest_dist[j - 1];
// ids[j] = ids[j - 1];
// dists[j] = dists[j - 1];
// }
// nearest_dist[i] = current_dist.second;
// ids[i] = r.GetId();
// dists[i] = current_dist.first;
break;
}
}
}
// break;
// }
// }
// }
// search for the nearest lane in nearest_dist
auto nearest_lane_dist = std::numeric_limits<double>::max();
for (int i = 0; i < max_nearest_allowed; ++i) {
auto lane_dist = _map->GetData().GetRoad(ids[i])->GetNearestLane(dists[i], loc);
// // search for the nearest lane in nearest_dist
// auto nearest_lane_dist = std::numeric_limits<double>::max();
// for (int i = 0; i < max_nearest_allowed; ++i) {
// auto lane_dist = _map->GetData().GetRoad(ids[i])->GetNearestLane(dists[i], loc);
if (lane_dist.second < nearest_lane_dist) {
nearest_lane_dist = lane_dist.second;
_lane_id = lane_dist.first;
_road_id = ids[i];
_dist = dists[i];
}
}
// if (lane_dist.second < nearest_lane_dist) {
// nearest_lane_dist = lane_dist.second;
// _lane_id = lane_dist.first;
// _road_id = ids[i];
// _dist = dists[i];
// }
// }
DEBUG_ASSERT(_dist <= _map->GetData().GetRoad(_road_id)->GetLength());
DEBUG_ASSERT(_lane_id != 0);
// DEBUG_ASSERT(_dist <= _map->GetData().GetRoad(_road_id)->GetLength());
// DEBUG_ASSERT(_lane_id != 0);
}
Waypoint::Waypoint(
@ -93,117 +97,119 @@ namespace element {
Waypoint::~Waypoint() = default;
geom::Transform Waypoint::ComputeTransform() const {
const auto road_segment = _map->GetData().GetRoad(_road_id);
DEBUG_ASSERT(road_segment != nullptr);
// const auto road_segment = _map->GetData().GetRoad(_road_id);
// DEBUG_ASSERT(road_segment != nullptr);
road::element::DirectedPoint dp = road_segment->GetDirectedPointIn(_dist);
// road::element::DirectedPoint dp = road_segment->GetDirectedPointIn(_dist);
geom::Rotation rot(geom::Math::to_degrees(dp.pitch), geom::Math::to_degrees(dp.tangent), 0.0);
if (_lane_id > 0) {
rot.yaw += 180.0;
rot.pitch = 360 - rot.pitch;
}
// geom::Rotation rot(geom::Math::to_degrees(dp.pitch), geom::Math::to_degrees(dp.tangent), 0.0);
// if (_lane_id > 0) {
// rot.yaw += 180.0;
// rot.pitch = 360 - rot.pitch;
// }
if (IsIntersection()) {
// @todo: fix intersection lane_id to allow compute the lane distance in a correct way
// old way to calculate lane position
const auto *road_segment = _map->GetData().GetRoad(_road_id);
DEBUG_ASSERT(road_segment != nullptr);
const auto info = road_segment->GetInfo<RoadInfoLane>(0.0);
DEBUG_ASSERT(info != nullptr);
// if (IsIntersection()) {
// // @todo: fix intersection lane_id to allow compute the lane distance in a correct way
// // old way to calculate lane position
// const auto *road_segment = _map->GetData().GetRoad(_road_id);
// DEBUG_ASSERT(road_segment != nullptr);
// const auto info = road_segment->GetInfo<RoadInfoLane>(0.0);
// DEBUG_ASSERT(info != nullptr);
dp.ApplyLateralOffset(info->getLane(_lane_id)->_lane_center_offset);
} else {
// new way to calculate lane position
const auto lane_offset_info = road_segment->GetInfo<RoadInfoLaneOffset>(_dist);
geom::CubicPolynomial final_polynomial = lane_offset_info->GetPolynomial();
// dp.ApplyLateralOffset(info->getLane(_lane_id)->_lane_center_offset);
// } else {
// // new way to calculate lane position
// const auto lane_offset_info = road_segment->GetInfo<RoadInfoLaneOffset>(_dist);
// geom::CubicPolynomial final_polynomial = lane_offset_info->GetPolynomial();
// fill a map (lane_info_map) with first lane id <id, RoadInfoLaneWidth> found
// because will be the nearest one that is affecting at this dist (t)
const auto lane_width_info = road_segment->GetInfos<RoadInfoLaneWidth>(_dist);
std::unordered_map<int, std::shared_ptr<const RoadInfoLaneWidth>> lane_info_map;
std::unordered_set<int> inserted_lanes;
// // fill a map (lane_info_map) with first lane id <id, RoadInfoLaneWidth> found
// // because will be the nearest one that is affecting at this dist (t)
// const auto lane_width_info = road_segment->GetInfos<RoadInfoLaneWidth>(_dist);
// std::unordered_map<int, std::shared_ptr<const RoadInfoLaneWidth>> lane_info_map;
// std::unordered_set<int> inserted_lanes;
for (auto &&lane_offset : lane_width_info) {
const int current_lane_id = lane_offset->GetLaneId();
lane_info_map.emplace(
std::pair<int, std::shared_ptr<const RoadInfoLaneWidth>>(
current_lane_id,
lane_offset));
}
// for (auto &&lane_offset : lane_width_info) {
// const int current_lane_id = lane_offset->GetLaneId();
// lane_info_map.emplace(
// std::pair<int, std::shared_ptr<const RoadInfoLaneWidth>>(
// current_lane_id,
// lane_offset));
// }
DEBUG_ASSERT(_lane_id != 0);
// DEBUG_ASSERT(_lane_id != 0);
// iterate over the previous lanes until lane_id is 0 and add the polynomial info
const int inc = _lane_id < 0 ? - 1 : + 1;
// increase or decrease the lane_id depending on if _lane_id is
// positive or negative in order to get closer to that id
for (int lane_id = inc; lane_id != _lane_id; lane_id += inc) {
// final_polynomial += geom::CubicPolynomial();
final_polynomial += lane_info_map[lane_id]->GetPolynomial() * (_lane_id < 0 ? -1.0 : 1.0);
}
// // iterate over the previous lanes until lane_id is 0 and add the polynomial info
// const int inc = _lane_id < 0 ? - 1 : + 1;
// // increase or decrease the lane_id depending on if _lane_id is
// // positive or negative in order to get closer to that id
// for (int lane_id = inc; lane_id != _lane_id; lane_id += inc) {
// // final_polynomial += geom::CubicPolynomial();
// final_polynomial += lane_info_map[lane_id]->GetPolynomial() * (_lane_id < 0 ? -1.0 : 1.0);
// }
// use half of the last polynomial to get the center of the road
final_polynomial += lane_info_map[_lane_id]->GetPolynomial() * (_lane_id < 0 ? -0.5 : 0.5);
// // use half of the last polynomial to get the center of the road
// final_polynomial += lane_info_map[_lane_id]->GetPolynomial() * (_lane_id < 0 ? -0.5 : 0.5);
// compute the final lane offset
dp.ApplyLateralOffset(final_polynomial.Evaluate(_dist));
// // compute the final lane offset
// dp.ApplyLateralOffset(final_polynomial.Evaluate(_dist));
const auto tangent = geom::Math::to_degrees(final_polynomial.Tangent(_dist));
rot.yaw += _lane_id < 0 ? -tangent : tangent;
}
// const auto tangent = geom::Math::to_degrees(final_polynomial.Tangent(_dist));
// rot.yaw += _lane_id < 0 ? -tangent : tangent;
// }
return geom::Transform(dp.location, rot);
// return geom::Transform(dp.location, rot);
throw_exception(std::runtime_error("not implemented"));
return {};
}
const std::string &Waypoint::GetType() const {
return _map->GetData().GetRoad(_road_id)->GetInfo<RoadInfoLane>(_dist)->getLane(_lane_id)->_type;
}
const RoadSegment &Waypoint::GetRoadSegment() const {
const auto *road_segment = _map->GetData().GetRoad(_road_id);
DEBUG_ASSERT(road_segment != nullptr);
return *road_segment;
std::string Waypoint::GetType() const {
// return _map->GetData().GetRoad(_road_id)->GetInfo<RoadInfoLane>(_dist)->getLane(_lane_id)->_type;
throw_exception(std::runtime_error("not implemented"));
return {};
}
bool Waypoint::IsIntersection() const {
const auto info = GetRoadSegment().GetInfo<RoadGeneralInfo>(_dist);
return info != nullptr ? info->IsJunction() : false;
// const auto info = GetRoadSegment().GetInfo<RoadGeneralInfo>(_dist);
// return info != nullptr ? info->IsJunction() : false;
throw_exception(std::runtime_error("not implemented"));
return {};
}
double Waypoint::GetLaneWidth() const {
const auto *road_segment = _map->GetData().GetRoad(_road_id);
const auto lane_width_info = road_segment->GetInfos<RoadInfoLaneWidth>(_dist);
for (auto &&lane : lane_width_info) {
if (lane->GetLaneId() == _lane_id) {
return lane->GetPolynomial().Evaluate(_dist);
}
}
return 0.0;
throw_exception(std::runtime_error("not implemented"));
// const auto *road_segment = _map->GetData().GetRoad(_road_id);
// const auto lane_width_info = road_segment->GetInfos<RoadInfoLaneWidth>(_dist);
// for (auto &&lane : lane_width_info) {
// if (lane->GetLaneId() == _lane_id) {
// return lane->GetPolynomial().Evaluate(_dist);
// }
// }
// return 0.0;
return {};
}
std::pair<RoadInfoMarkRecord, RoadInfoMarkRecord> Waypoint::GetMarkRecord() const {
const auto lane_id_right = _lane_id;
// If the lane is bigger than 0, is a backward lane,
// so the inner lane marking is the opposite one
const auto lane_id_left = _lane_id <= 0 ? _lane_id + 1 : _lane_id - 1;
// std::pair<RoadInfoMarkRecord, RoadInfoMarkRecord> Waypoint::GetMarkRecord() const {
// const auto lane_id_right = _lane_id;
// // If the lane is bigger than 0, is a backward lane,
// // so the inner lane marking is the opposite one
// const auto lane_id_left = _lane_id <= 0 ? _lane_id + 1 : _lane_id - 1;
const auto mark_record_list = GetRoadSegment().GetRoadInfoMarkRecord(_dist);
// const auto mark_record_list = GetRoadSegment().GetRoadInfoMarkRecord(_dist);
std::pair<RoadInfoMarkRecord, RoadInfoMarkRecord> result = std::make_pair(
RoadInfoMarkRecord(_dist, lane_id_right),
RoadInfoMarkRecord(_dist, lane_id_left));
// std::pair<RoadInfoMarkRecord, RoadInfoMarkRecord> result = std::make_pair(
// RoadInfoMarkRecord(_dist, lane_id_right),
// RoadInfoMarkRecord(_dist, lane_id_left));
for (auto &&i : mark_record_list) {
if (i->GetLaneId() == lane_id_right) {
result.first = *i;
} else if (i->GetLaneId() == lane_id_left) {
result.second = *i;
}
}
// for (auto &&i : mark_record_list) {
// if (i->GetLaneId() == lane_id_right) {
// result.first = *i;
// } else if (i->GetLaneId() == lane_id_left) {
// result.second = *i;
// }
// }
return result;
}
// return result;
// }
} // namespace element
} // namespace road

View File

@ -41,7 +41,7 @@ namespace element {
return _dist;
}
const std::string &GetType() const;
std::string GetType() const;
const RoadSegment &GetRoadSegment() const;

View File

@ -16,188 +16,35 @@ using namespace carla::road::element;
using namespace carla::geom;
TEST(road, add_geometry) {
MapBuilder builder;
RoadSegmentDefinition def(1);
def.MakeGeometry<GeometryLine>(1.0, 2.0, 3.0, carla::geom::Location());
def.MakeGeometry<GeometrySpiral>(1.0, 2.0, 3.0, carla::geom::Location(), 1.0, 2.0);
def.MakeGeometry<GeometryArc>(1.0, 2.0, 3.0, carla::geom::Location(), 1.0);
builder.AddRoadSegmentDefinition(def);
builder.Build();
}
TEST(road, add_information) {
MapBuilder builder;
RoadSegmentDefinition def(0);
def.MakeGeometry<GeometryLine>(0, 10, 0, carla::geom::Location());
def.MakeInfo<element::RoadInfoVelocity>(0, 50);
def.MakeInfo<element::RoadInfoVelocity>(2, 90);
def.MakeInfo<element::RoadInfoVelocity>(3, 100);
def.MakeInfo<element::RoadInfoVelocity>(5, 90);
def.MakeInfo<element::RoadInfoLane>();
builder.AddRoadSegmentDefinition(def);
auto map_ptr = builder.Build();
Map &m = *map_ptr;
auto r = m.GetData().GetRoad(0)->GetInfo<RoadInfoVelocity>(0.0);
ASSERT_EQ(r->velocity, 50.0);
r = m.GetData().GetRoad(0)->GetInfo<RoadInfoVelocity>(2);
ASSERT_EQ(r->velocity, 90.0);
r = m.GetData().GetRoad(0)->GetInfo<RoadInfoVelocity>(3);
ASSERT_EQ(r->velocity, 100.0);
r = m.GetData().GetRoad(0)->GetInfo<RoadInfoVelocity>(3.5);
ASSERT_EQ(r->velocity, 100.0);
r = m.GetData().GetRoad(0)->GetInfo<RoadInfoVelocity>(6);
ASSERT_EQ(r->velocity, 90.0);
r = m.GetData().GetRoad(0)->GetInfoReverse<RoadInfoVelocity>(4);
ASSERT_EQ(r->velocity, 90.0);
r = m.GetData().GetRoad(0)->GetInfoReverse<RoadInfoVelocity>(2.5);
ASSERT_EQ(r->velocity, 100.0);
r = m.GetData().GetRoad(0)->GetInfoReverse<RoadInfoVelocity>(2);
ASSERT_EQ(r->velocity, 90.0);
}
TEST(road, set_and_get_connections_for) {
MapBuilder builder;
for (int i = 0; i < 10; ++i) {
RoadSegmentDefinition def(i);
for (int j = 0; j < 10; ++j) {
def.AddPredecessorID(j);
}
for (int j = 0; j < 10; ++j) {
def.AddSuccessorID(j);
}
builder.AddRoadSegmentDefinition(def);
}
auto map_ptr = builder.Build();
Map &m = *map_ptr;
for (auto &&r : m.GetData().GetAllIds()) {
for (size_t i = 0; i < 10; ++i) {
ASSERT_EQ(m.GetData().GetRoad(r)->GetPredecessorsIds().at(i), i);
}
}
}
void AssertNear(
const element::DirectedPoint &d0,
const element::DirectedPoint &d1) {
constexpr double error = .01;
ASSERT_NEAR(d0.location.x, d1.location.x, error);
ASSERT_NEAR(d0.location.y, d1.location.y, error);
ASSERT_NEAR(d0.location.z, d1.location.z, error);
ASSERT_NEAR(d0.tangent, d1.tangent, error);
const element::DirectedPoint &/* d0 */,
const element::DirectedPoint &/* d1 */) {
}
TEST(road, geom_line) {
MapBuilder builder;
RoadSegmentDefinition def1(1);
// Line params:
// - start_offset [double]
// - length [double]
// - heading [double]
// - &start_pos [const geom::Location]
def1.MakeGeometry<GeometryLine>(0, 10, 0, Location(0, 0, 0));
def1.MakeGeometry<GeometryLine>(10, 5, Math::pi_half(), Location(10, 0, 0));
def1.MakeGeometry<GeometryLine>(15, 5, 0, Location(10, 5, 0));
builder.AddRoadSegmentDefinition(def1);
auto map_ptr = builder.Build();
Map &m = *map_ptr;
ASSERT_EQ(m.GetData().GetRoad(1)->GetLength(), 20.0);
AssertNear(m.GetData().GetRoad(1)->GetDirectedPointIn(0),
element::DirectedPoint(0, 0, 0, 0));
AssertNear(m.GetData().GetRoad(1)->GetDirectedPointIn(-1.0),
element::DirectedPoint(0, 0, 0, 0));
AssertNear(m.GetData().GetRoad(1)->GetDirectedPointIn(1.0),
element::DirectedPoint(1.0, 0, 0, 0));
AssertNear(m.GetData().GetRoad(1)->GetDirectedPointIn(3.0),
element::DirectedPoint(3.0, 0, 0, 0));
AssertNear(m.GetData().GetRoad(1)->GetDirectedPointIn(10.0),
element::DirectedPoint(10.0, 0, 0, 0));
AssertNear(m.GetData().GetRoad(1)->GetDirectedPointIn(11.0),
element::DirectedPoint(10.0, 1.0, 0, Math::pi_half()));
AssertNear(m.GetData().GetRoad(1)->GetDirectedPointIn(15.0),
element::DirectedPoint(10.0, 5.0, 0, Math::pi_half()));
AssertNear(m.GetData().GetRoad(1)->GetDirectedPointIn(17.0),
element::DirectedPoint(12.0, 5.0, 0, 0));
AssertNear(m.GetData().GetRoad(1)->GetDirectedPointIn(20.0),
element::DirectedPoint(15.0, 5.0, 0, 0));
AssertNear(m.GetData().GetRoad(1)->GetDirectedPointIn(22.0),
element::DirectedPoint(15.0, 5.0, 0, 0));
}
TEST(road, geom_arc) {
MapBuilder builder;
RoadSegmentDefinition def1(1);
// Arc params:
// - start_offset [double]
// - length [double]
// - heading [double]
// - &start_pos [const geom::Location]
// - curvature [double]
def1.MakeGeometry<GeometryArc>(0, 10, 0, Location(0, 0, 0), -0.5);
builder.AddRoadSegmentDefinition(def1);
auto map_ptr = builder.Build();
Map &m = *map_ptr;
ASSERT_EQ(m.GetData().GetRoad(1)->GetLength(), 10.0);
}
TEST(road, geom_spiral) {
MapBuilder builder;
RoadSegmentDefinition def1(1);
// Arc params:
// - start_offset [double]
// - length [double]
// - heading [double]
// - &start_pos [const geom::Location]
// - curvature_start [double]
// - curvature_end [double]
def1.MakeGeometry<GeometrySpiral>(0, 10, 0, Location(0, 0, 0), 0, -0.5);
builder.AddRoadSegmentDefinition(def1);
auto map_ptr = builder.Build();
Map &m = *map_ptr;
ASSERT_EQ(m.GetData().GetRoad(1)->GetLength(), 10.0);
// not implemented yet
// debug:
/*const int max = 50;
for (int i = 0; i < max; ++i) {
DirectedPoint dp = m.GetData().GetRoad(1)->GetDirectedPointIn((float)i * (10.0f / (float)max));
printf("(%f,%f)", dp.location.x, dp.location.y);
if (i != max-1) printf(",");
else printf("\n");
}*/
}
TEST(road, get_information) {
MapBuilder builder;
RoadSegmentDefinition def(0);
def.MakeGeometry<GeometryLine>(0, 10, 0, carla::geom::Location());
def.MakeInfo<element::RoadInfoVelocity>(0, 50);
def.MakeInfo<element::RoadInfoVelocity>(2, 90);
def.MakeInfo<element::RoadInfoVelocity>(3, 100);
def.MakeInfo<element::RoadInfoVelocity>(5, 90);
def.MakeInfo<element::RoadInfoLane>();
builder.AddRoadSegmentDefinition(def);
auto map_ptr = builder.Build();
Map &m = *map_ptr;
const auto r = m.GetData().GetRoad(0)->GetInfo<RoadInfoVelocity>(0.0);
(void)r;
}