61#define DEBUG_COND(road) ((road)->id == "32")
62#define DEBUG_COND2(edgeID) (StringUtils::startsWith((edgeID), "67"))
63#define DEBUG_COND3(roadID) (roadID == "32")
186 bool customLaneShapes = oc.
getBool(
"opendrive.lane-shapes");
190 std::map<std::string, OpenDriveEdge*> edges;
194 std::vector<std::string> files = oc.
getStringVector(
"opendrive-files");
195 for (std::vector<std::string>::const_iterator file = files.begin(); file != files.end(); ++file) {
197 WRITE_ERROR(
"Could not open opendrive file '" + *file +
"'.");
206 for (
auto& item : edges) {
208 if (signal.
type ==
"") {
222 std::map<std::string, OpenDriveEdge*> innerEdges, outerEdges;
223 for (std::map<std::string, OpenDriveEdge*>::iterator i = edges.begin(); i != edges.end(); ++i) {
224 if ((*i).second->isInner) {
225 innerEdges[(*i).first] = (*i).second;
227 outerEdges[(*i).first] = (*i).second;
242 std::map<std::string, Boundary> posMap;
243 std::map<std::string, std::string> edge2junction;
244 std::vector<NodeSet> joinedNodeIDs;
246 for (std::map<std::string, OpenDriveEdge*>::iterator i = innerEdges.begin(); i != innerEdges.end(); ++i) {
250 if (posMap.find(e->
junction) == posMap.end()) {
256 for (std::map<std::string, Boundary>::iterator i = posMap.begin(); i != posMap.end(); ++i) {
259 throw ProcessError(
"Could not add node '" + (*i).first +
"'.");
263 for (std::map<std::string, OpenDriveEdge*>::iterator i = outerEdges.begin(); i != outerEdges.end(); ++i) {
265 for (std::vector<OpenDriveLink>::iterator j = e->
links.begin(); j != e->
links.end(); ++j) {
273 throw ProcessError(
"Could not build node '" + nid +
"'.");
280 if (edge2junction.find(l.
elementID) != edge2junction.end()) {
292 for (std::map<std::string, OpenDriveEdge*>::iterator i = outerEdges.begin(); i != outerEdges.end(); ++i) {
294 for (std::vector<OpenDriveLink>::iterator j = e->
links.begin(); j != e->
links.end(); ++j) {
301 std::string id1 = e->
id;
306 std::string nid = id1 +
"." + id2;
311 throw ProcessError(
"Could not build node '" + nid +
"'.");
329 for (std::map<std::string, OpenDriveEdge*>::iterator i = outerEdges.begin(); i != outerEdges.end(); ++i) {
331 if (e->
to !=
nullptr && e->
from !=
nullptr) {
334 for (std::map<std::string, OpenDriveEdge*>::iterator j = innerEdges.begin(); j != innerEdges.end(); ++j) {
336 for (std::vector<OpenDriveLink>::iterator k = ie->
links.begin(); k != ie->
links.end(); ++k) {
342 std::string nid = edge2junction[ie->
id];
354 for (std::map<std::string, OpenDriveEdge*>::iterator i = outerEdges.begin(); i != outerEdges.end(); ++i) {
356 if ((e->
from ==
nullptr || e->
to ==
nullptr) && e->
geom.size() == 0) {
359 if (e->
from ==
nullptr) {
360 const std::string nid = e->
id +
".begin";
363 if (e->
to ==
nullptr) {
364 const std::string nid = e->
id +
".end";
369 std::map<NBNode*, NBNode*> joinedNodes;
370 for (
NodeSet& joined : joinedNodeIDs) {
372 for (
NBNode* j : joined) {
373 joinedPos.
add(j->getPosition());
375 joinedPos.
mul(1. / (
double)joined.size());
377 if (!nc.
insert(joinedID, joinedPos)) {
378 throw ProcessError(
"Could not add node '" + joinedID +
"'.");
381 for (
NBNode* j : joined) {
385 for (std::map<std::string, OpenDriveEdge*>::iterator i = outerEdges.begin(); i != outerEdges.end(); ++i) {
387 if (joinedNodes.count(e->
from) != 0) {
391 if (joinedNodes.count(e->
to) != 0) {
393 e->
to = joinedNodes[e->
to];
405 std::map<std::pair<NBEdge*, int>,
int> laneIndexMap;
407 for (std::map<std::string, OpenDriveEdge*>::iterator i = outerEdges.begin(); i != outerEdges.end(); ++i) {
409 if (e->
geom.size() < 2) {
413 bool lanesBuilt =
false;
439 std::cout <<
" geomWithOffset=" << geomWithOffset <<
"\n";
442 const double length2D = geomWithOffset.
length2D();
443 double cF = length2D == 0 ? 1 : e->
length / length2D;
444 NBEdge* prevRight =
nullptr;
445 NBEdge* prevLeft =
nullptr;
453 WRITE_WARNING(
"Edge '" + e->
id +
"' has to be split as it connects same junctions.")
457 const double minDist = oc.
getFloat(
"opendrive.curve-resolution");
462 int sectionIndex = 0;
469 double nextS = (j + 1)->s;
470 const std::string nodeID = e->
id + (positionIDs ?
"." +
toString(nextS) :
"#" +
toString(sectionIndex + 1));
478 std::string
id = e->
id;
480 if (sFrom != e->
from || sTo != e->
to) {
486 id =
id +
"#" +
toString(sectionIndex++);
488#ifdef DEBUG_VARIABLE_WIDTHS
490 std::cout <<
" id=" <<
id <<
" sB=" << sB <<
" sE=" << sE <<
" geom=" << geom <<
"\n";
495 NBEdge* currRight =
nullptr;
496 if ((*j).rightLaneNumber > 0) {
497 std::vector<double> offsets(geom.size(), 0);
498 bool useOffsets =
false;
505 rightGeom.
move2side((*j).discardedInnerWidthRight);
508 std::cout <<
" -" <<
id <<
"_geom=" << geom <<
" -" <<
id <<
"_rightGeom=" << rightGeom <<
"\n";
517 std::sort(lanes.begin(), lanes.end(),
LaneSorter());
518 for (std::vector<OpenDriveLane>::const_iterator k = lanes.begin(); k != lanes.end(); ++k) {
519 std::map<int, int>::const_iterator lp = (*j).laneMap.find((*k).id);
520 if (lp != (*j).laneMap.end()) {
521 int sumoLaneIndex = lp->second;
523 laneIndexMap[std::make_pair(currRight, sumoLaneIndex)] = (*k).id;
529 }
else if (customLaneShapes) {
532 if (customLaneShapes) {
543 if (prevRight !=
nullptr) {
545 for (std::map<int, int>::const_iterator k = connections.begin(); k != connections.end(); ++k) {
546#ifdef DEBUG_CONNECTIONS
548 std::cout <<
"addCon1 from=" << prevRight->
getID() <<
"_" << (*k).first <<
" to=" << currRight->
getID() <<
"_" << (*k).second <<
"\n";
554 prevRight = currRight;
559 NBEdge* currLeft =
nullptr;
560 if ((*j).leftLaneNumber > 0) {
561 std::vector<double> offsets(geom.size(), 0);
562 bool useOffsets =
false;
564 leftGeom.
move2side(-(*j).discardedInnerWidthLeft);
568 std::cout <<
" " <<
id <<
"_geom=" << geom <<
" " <<
id <<
"_leftGeom=" << leftGeom <<
"\n";
575 std::sort(lanes.begin(), lanes.end(),
LaneSorter());
576 for (std::vector<OpenDriveLane>::const_iterator k = lanes.begin(); k != lanes.end(); ++k) {
577 std::map<int, int>::const_iterator lp = (*j).laneMap.find((*k).id);
578 if (lp != (*j).laneMap.end()) {
579 int sumoLaneIndex = lp->second;
581 laneIndexMap[std::make_pair(currLeft, sumoLaneIndex)] = (*k).id;
587 }
else if (customLaneShapes) {
590 if (customLaneShapes) {
601 if (prevLeft !=
nullptr) {
602 std::map<int, int> connections = (*j).getInnerConnections(
OPENDRIVE_TAG_LEFT, *(j - 1));
603 for (std::map<int, int>::const_iterator k = connections.begin(); k != connections.end(); ++k) {
604#ifdef DEBUG_CONNECTIONS
606 std::cout <<
"addCon2 from=" << currLeft->
getID() <<
"_" << (*k).first <<
" to=" << prevLeft->
getID() <<
"_" << (*k).second <<
"\n";
622 if (oc.
isSet(
"polygon-output")) {
641 centerLine.push_back(
Position(-o.length / 2, 0));
642 centerLine.push_back(
Position(o.length / 2, 0));
644 centerLine.
rotate2D(roadHdg + o.hdg);
675 for (std::map<std::string, OpenDriveEdge*>::iterator i = edges.begin(); i != edges.end(); ++i) {
679 std::vector<Connection> connections2;
680 for (std::map<std::string, OpenDriveEdge*>::iterator j = edges.begin(); j != edges.end(); ++j) {
681 const std::set<Connection>& conns = (*j).second->connections;
683 for (std::set<Connection>::const_iterator i = conns.begin(); i != conns.end(); ++i) {
684 if (innerEdges.find((*i).fromEdge) != innerEdges.end()) {
688 if (innerEdges.find((*i).toEdge) != innerEdges.end()) {
689 std::set<Connection> seen;
692 connections2.push_back(*i);
697 for (std::vector<Connection>::const_iterator i = connections2.begin(); i != connections2.end(); ++i) {
698#ifdef DEBUG_CONNECTIONS
699 std::cout <<
"connections2 " << (*i).getDescription() <<
"\n";
701 std::string fromEdge = (*i).fromEdge;
702 if (edges.find(fromEdge) == edges.end()) {
703 WRITE_WARNING(
"While setting connections: from-edge '" + fromEdge +
"' is not known.");
707 int fromLane = (*i).fromLane;
711 std::string toEdge = (*i).toEdge;
712 if (edges.find(toEdge) == edges.end()) {
713 WRITE_WARNING(
"While setting connections: to-edge '" + toEdge +
"' is not known.");
718 int toLane = (*i).toLane;
738 if (from ==
nullptr) {
739 WRITE_WARNING(
"Could not find fromEdge representation of '" + fromEdge +
"' in connection '" + (*i).origID +
"'.");
742 WRITE_WARNING(
"Could not find fromEdge representation of '" + toEdge +
"' in connection '" + (*i).origID +
"'.");
744 if (from ==
nullptr || to ==
nullptr) {
748#ifdef DEBUG_CONNECTIONS
750 std::cout <<
"addCon3 from=" << from->
getID() <<
"_" << fromLane <<
" to=" << to->
getID() <<
"_" << toLane <<
"\n";
762 if ((*i).origID !=
"" && saveOrigIDs) {
765 for (std::vector<NBEdge::Connection>::iterator k = cons.begin(); k != cons.end(); ++k) {
766 if ((*k).fromLane == fromLane && (*k).toEdge == to && (*k).toLane == toLane) {
778 std::map<std::string, std::string> tlsControlled;
779 for (std::map<std::string, OpenDriveEdge*>::iterator i = edges.begin(); i != edges.end(); ++i) {
786 if (intType < 1000001 || (intType > 1000013 && intType != 1000020) || intType == 1000008) {
791 WRITE_WARNING(
"Edge '" + e->
id +
"' has signals but no lane sections.");
794 std::vector<OpenDriveLaneSection>::iterator k = e->
laneSections.begin();
797 if (signal.
s > (*k).s && signal.
s <= (*(k + 1)).s) {
804 std::string
id = (*k).sumoID;
809 std::string fromID, toID;
810 for (std::vector<OpenDriveLink>::const_iterator l = e->
links.begin(); l != e->
links.end(); ++l) {
819 fromID =
"-" + fromID;
824 fromID =
"-" + fromID;
842 if (from ==
nullptr) {
849 bool fromForward = from->
getID()[0] ==
'-';
850 bool lanesForward = signal.
maxLane < 0;
851 if (fromForward != lanesForward) {
855 from = signalFromTo.first;
856 to = signalFromTo.second;
857 if (from ==
nullptr) {
864 if (c.toEdge == to) {
865 int odLane = laneIndexMap[std::make_pair(from, c.fromLane)];
868 if (c.knowsParameter(
"signalID")) {
869 c.setParameter(
"signalID", c.getParameter(
"signalID") +
" " + signal.
id);
871 c.setParameter(
"signalID", signal.
id);
880 WRITE_WARNINGF(
TL(
"Found a traffic light signal on an unknown edge (original edge id='%')."), e->
id);
890 if (edge ==
nullptr) {
897 int odLane = laneIndexMap[std::make_pair(edge, c.fromLane)];
899 if (c.knowsParameter(
"signalID")) {
900 c.setParameter(
"signalID", c.getParameter(
"signalID") +
" " + signal.
id);
902 c.setParameter(
"signalID", signal.
id);
916 for (std::map<std::string, OpenDriveEdge*>::iterator i = edges.begin(); i != edges.end(); ++i) {
921std::pair<NBEdge*, NBEdge*>
933 return std::make_pair(from, to);
971 if (sumoLane.
width >= 0 && widthResolution > 0) {
972 sumoLane.
width = floor(sumoLane.
width / widthResolution + 0.5) * widthResolution;
974 sumoLane.
width -= widthResolution;
975 if (sumoLane.
width <= 0) {
978 }
else if (sumoLane.
width == 0) {
980 sumoLane.
width = widthResolution;
986 if (forbiddenNarrow) {
994 const std::map<std::string, OpenDriveEdge*>& innerEdges,
995 const std::map<std::string, OpenDriveEdge*>& edges,
997 std::vector<Connection>& into, std::set<Connection>& seen) {
1000#ifdef DEBUG_CONNECTIONS
1002 std::cout <<
" buildConnectionsToOuter " << c.
getDescription() <<
"\n";
1003 std::cout <<
" dest=" << (dest ==
nullptr ?
"NULL" : dest->
id) <<
" seenlist=";
1004 for (std::set<Connection>::const_iterator i = seen.begin(); i != seen.end(); ++i) {
1005 std::cout <<
" " << (*i).fromEdge <<
"," << (*i).toEdge <<
" ";
1010 if (dest ==
nullptr) {
1016 auto innerEdgesIt = innerEdges.find(destCon.
toEdge);
1017#ifdef DEBUG_CONNECTIONS
1019 std::cout <<
" toInner=" << (innerEdgesIt != innerEdges.end()) <<
" destCon " << (*i).getDescription() <<
"\n";
1022 if (innerEdgesIt != innerEdges.end()) {
1023 std::vector<Connection> t;
1024 if (seen.count(destCon) == 0) {
1026 for (std::vector<Connection>::const_iterator j = t.begin(); j != t.end(); ++j) {
1034 cn.shape = innerEdgesIt->second->geom + c.
shape;
1048#ifdef DEBUG_CONNECTIONS
1050 std::cout <<
" laneSectionsConnected dest=" << dest->
id <<
" in=" << in <<
" out=" << out
1067 int referenceLane = 0;
1068 int offsetFactor = 1;
1072 for (
const auto& destLane : dest->
laneSections.front().lanesByDir[lanesDir]) {
1073 if (destLane.successor == c.
fromLane) {
1074 referenceLane = destLane.id;
1080 for (
const auto& destLane : dest->
laneSections.front().lanesByDir[lanesDir]) {
1081 if (destLane.predecessor == c.
fromLane) {
1082 referenceLane = destLane.id;
1091 std::vector<double> offsets(dest->
geom.size(), 0);
1095#ifdef DEBUG_INTERNALSHAPES
1096 std::string destPred;
1100 for (
int laneSectionIndex = 0; laneSectionIndex < (int)dest->
laneSections.size(); laneSectionIndex++) {
1102 const double nextS = laneSectionIndex + 1 < (int)dest->
laneSections.size() ? dest->
laneSections[laneSectionIndex + 1].s : std::numeric_limits<double>::max();
1105 int finalI = iShape;
1108 double sectionS = 0;
1111#ifdef DEBUG_INTERNALSHAPES
1112 destPred +=
" lane=" +
toString(destLane.id)
1113 +
" pred=" +
toString(destLane.predecessor)
1114 +
" succ=" +
toString(destLane.successor)
1115 +
" wStart=" + (destLane.widthData.empty() ?
"?" :
toString(destLane.widthData.front().computeAt(0)))
1116 +
" wEnd=" + (destLane.widthData.empty() ?
"?" :
toString(destLane.widthData.front().computeAt(
cn.shape.length2D())))
1117 +
" width=" +
toString(destLane.width) +
"\n";
1119 if (abs(destLane.id) <= abs(referenceLane)) {
1120 const double multiplier = offsetFactor * (destLane.id == referenceLane ? 0.5 : 1);
1121#ifdef DEBUG_INTERNALSHAPES
1122 destPred +=
" multiplier=" +
toString(multiplier) +
"\n";
1124 int widthDataIndex = 0;
1125 while (s < nextS && i < (
int)
cn.shape.size()) {
1127 const double dist =
cn.shape[i - 1].distanceTo2D(
cn.shape[i]);
1132 while (widthDataIndex + 1 < (
int)destLane.widthData.size()
1133 && sectionS >= destLane.widthData[widthDataIndex + 1].s) {
1137 if (destLane.widthData.size() > 0) {
1138 width = destLane.widthData[widthDataIndex].computeAt(sectionS);
1140#ifdef DEBUG_INTERNALSHAPES
1141 std::cout <<
" missing width data at inner edge " << dest->
id <<
" to=" <<
cn.toEdge <<
"_" <<
cn.toLane <<
" cp=" <<
cn.toCP <<
"\n";
1148 if (outerToLane.id ==
cn.toLane && outerToLane.width > 0) {
1149#ifdef DEBUG_INTERNALSHAPES
1150 std::cout <<
" using toLane width " << width <<
"\n";
1156 offsets[i] += width * multiplier;
1164 }
else if (finalS == s) {
1166 while (s < nextS && i < (
int)
cn.shape.size()) {
1168 const double dist =
cn.shape[i - 1].distanceTo2D(
cn.shape[i]);
1184 cn.shape.move2sideCustom(offsets);
1189#ifdef DEBUG_INTERNALSHAPES
1190 std::cout <<
"internalShape "
1192 <<
" dest=" << dest->
id
1193 <<
" refLane=" << referenceLane
1194 <<
" destPred\n" << destPred
1195 <<
" offsets=" << offsets
1196 <<
"\n shape=" << dest->
geom
1197 <<
"\n shape2=" <<
cn.shape
1201 cn.shape =
cn.shape.reverse();
1204#ifdef DEBUG_CONNECTIONS
1206 std::cout <<
" added connection\n";
1226 if (lane.id == in) {
1227 in = lane.successor;
1234 if (lane.id == in) {
1235 in = lane.successor;
1248 for (std::vector<OpenDriveLink>::iterator i = e.
links.begin(); i != e.
links.end(); ++i) {
1255 std::string connectedEdge = l.
elementID;
1256 std::string edgeID = e.
id;
1259 const std::map<int, int>& laneMap = laneSection.
laneMap;
1260#ifdef DEBUG_CONNECTIONS
1262 std::cout <<
"edge=" << e.
id <<
" eType=" << l.
elementType <<
" lType=" << l.
linkType <<
" connectedEdge=" << connectedEdge <<
" laneSection=" << laneSection.
s <<
" map:\n";
1268 for (std::vector<OpenDriveLane>::const_iterator j = lanes.begin(); j != lanes.end(); ++j) {
1277 c.
toEdge = connectedEdge;
1285 if (edges.find(c.
fromEdge) == edges.end()) {
1286 WRITE_ERROR(
"While setting connections: incoming road '" + c.
fromEdge +
"' is not known.");
1290#ifdef DEBUG_CONNECTIONS
1292 std::cout <<
"insertConRight from=" << src->
id <<
"_" << c.
fromLane <<
" to=" << c.
toEdge <<
"_" << c.
toLane <<
"\n";
1300 for (std::vector<OpenDriveLane>::const_iterator j = lanes.begin(); j != lanes.end(); ++j) {
1317 if (edges.find(c.
fromEdge) == edges.end()) {
1318 WRITE_ERROR(
"While setting connections: incoming road '" + c.
fromEdge +
"' is not known.");
1322#ifdef DEBUG_CONNECTIONS
1324 std::cout <<
"insertConLeft from=" << src->
id <<
"_" << c.
fromLane <<
" to=" << c.
toEdge <<
"_" << c.
toLane <<
"\n";
1336 return id.substr(1);
1347 if (!nc.
insert(
id, pos)) {
1349 throw ProcessError(
"Could not add node '" +
id +
"'.");
1361 throw ProcessError(
"Could not find node '" + nodeID +
"'.");
1363 NBNode* toJoin =
nullptr;
1365 if (e.
to !=
nullptr && e.
to != n) {
1370 if (e.
from !=
nullptr && e.
from != n) {
1375 if (toJoin !=
nullptr) {
1379 for (
NodeSet& joined : joinedNodeIDs) {
1380 if (joined.count(toJoin) != 0) {
1383 if (joined.count(n) != 0) {
1387 if (set1 ==
nullptr && set2 ==
nullptr) {
1388 joinedNodeIDs.push_back(
NodeSet());
1389 joinedNodeIDs.back().insert(n);
1390 joinedNodeIDs.back().insert(toJoin);
1391 }
else if (set1 ==
nullptr && set2 !=
nullptr) {
1392 set2->insert(toJoin);
1393 }
else if (set1 !=
nullptr && set2 ==
nullptr) {
1396 set1->insert(set2->begin(), set2->end());
1397 joinedNodeIDs.erase(std::find(joinedNodeIDs.begin(), joinedNodeIDs.end(), *set2));
1408 if (el.
c != 0 || el.
d != 0) {
1418 const double res = oc.
getFloat(
"opendrive.curve-resolution");
1419 for (std::map<std::string, OpenDriveEdge*>::iterator i = edges.begin(); i != edges.end(); ++i) {
1424 for (std::vector<OpenDriveGeometry>::iterator j = e.
geometries.begin(); j != e.
geometries.end(); ++j) {
1452 if (!e.
geom.back().almostSame(geom.front())) {
1453 const int index = (int)(j - e.
geometries.begin());
1454 WRITE_WARNINGF(
TL(
"Mismatched geometry for edge '%' between geometry segments % and %."), e.
id, index - 1, index);
1459 for (PositionVector::iterator k = geom.begin(); k != geom.end(); ++k) {
1465 if (e.
geom.size() == 1 && e.
geom.front() != last) {
1467 e.
geom.push_back(last);
1471 std::cout <<
" initialGeom=" << e.
geom <<
"\n";
1474 if (oc.
exists(
"geometry.min-dist") && !oc.
isDefault(
"geometry.min-dist")) {
1477 if (e.
geom.size() > 4) {
1483 std::cout <<
" reducedGeom=" << e.
geom <<
"\n";
1487 WRITE_ERROR(
"Unable to project coordinates for edge '" + e.
id +
"'.");
1494 for (std::vector<OpenDriveElevation>::iterator j = e.
elevations.begin(); j != e.
elevations.end(); ++j) {
1496 const double sNext = (j + 1) == e.
elevations.end() ? std::numeric_limits<double>::max() : (*(j + 1)).s;
1497 while (k < (
int)e.
geom.size() && pos < sNext) {
1502 if (k < (
int)e.
geom.size()) {
1505 pos += e.
geom[k - 1].distanceTo2D(e.
geom[k]);
1522 std::vector<double> laneOffsets;
1538 for (
auto j = offsets.begin(); j != offsets.end(); ++j) {
1540 const double sNext = (j + 1) == offsets.end() ? std::numeric_limits<double>::max() : (*(j + 1)).s;
1541 while (kk < (
int)geom.size() && ppos < sNext) {
1542 const double offset = el.
computeAt(ppos);
1543 laneOffsets.push_back(fabs(offset) > POSITION_EPS ? -offset : 0);
1545 if (kk < (
int)geom.size()) {
1548 ppos += geom[kk - 1].distanceTo2D(geom[kk]);
1568 double interpolatedOffset = 0;
1570 interpolatedOffset = result.front();
1571 }
else if (at == (
int)geom.size() - 1) {
1572 interpolatedOffset = result.back();
1574 interpolatedOffset = (result[at - 1] + result[at]) / 2;
1576 result.insert(result.begin() + at, interpolatedOffset);
1582 const int sign = left ? -1 : 1;
1583 for (
auto j = offsets.begin(); j != offsets.end(); ++j) {
1585 const double sNext = (j + 1) == offsets.end() ? std::numeric_limits<double>::max() : (*(j + 1)).s;
1586 while (kk < (
int)geom.size() && ppos < sNext) {
1587 const double offset = el.
computeAt(ppos);
1588 result[kk] += fabs(offset) > POSITION_EPS ? sign * offset : 0;
1590 if (kk < (
int)geom.size()) {
1593 ppos += geom[kk - 1].distanceTo2D(geom[kk]);
1602 for (std::map<std::string, OpenDriveEdge*>::iterator i = edges.begin(); i != edges.end(); ++i) {
1604#ifdef DEBUG_VARIABLE_SPEED
1607 std::cout <<
"revisitLaneSections e=" << e.
id <<
"\n";
1610 std::vector<OpenDriveLaneSection>& laneSections = e.
laneSections;
1612 std::vector<OpenDriveLaneSection> newSections;
1613 for (std::vector<OpenDriveLaneSection>::iterator j = laneSections.begin(); j != laneSections.end(); ++j) {
1614 std::vector<OpenDriveLaneSection> splitSections;
1615 bool splitBySpeed = (*j).buildSpeedChanges(tc, splitSections);
1616 if (!splitBySpeed) {
1617 newSections.push_back(*j);
1619 std::copy(splitSections.begin(), splitSections.end(), back_inserter(newSections));
1628 for (std::vector<OpenDriveLaneSection>::const_iterator j = laneSections.begin(); j != laneSections.end() && sorted; ++j) {
1629 if ((*j).s <= lastS) {
1635 WRITE_WARNING(
"The sections of edge '" + e.
id +
"' are not sorted properly.");
1641 for (std::vector<OpenDriveLaneSection>::iterator j = laneSections.begin(); j != laneSections.end();) {
1642 bool simlarToLast = fabs((*j).s - lastS) < POSITION_EPS;
1646 if (simlarToLast && !e.
isInner) {
1647 WRITE_WARNINGF(
TL(
"Almost duplicate s-value '%' for lane sections occurred at edge '%'; second entry was removed."),
toString(lastS), e.
id);
1648 j = laneSections.erase(j);
1653#ifdef DEBUG_VARIABLE_SPEED
1666 if (resolution > 0 && g.
length > 0) {
1667 const int numPoints = (int)ceil(g.
length / resolution) + 1;
1668 double dx = (end.
x() - start.
x()) / (numPoints - 1);
1669 double dy = (end.
y() - start.
y()) / (numPoints - 1);
1670 for (
int i = 0; i < numPoints; i++) {
1671 ret.push_back(
Position(g.
x + i * dx, g.
y + i * dy));
1674 ret.push_back(start);
1685 double curveStart = g.
params[0];
1686 double curveEnd = g.
params[1];
1688 double cDot = (curveEnd - curveStart) / g.
length;
1689 if (cDot == 0 || g.
length == 0) {
1694 double sStart = curveStart / cDot;
1695 double sEnd = curveEnd / cDot;
1701 odrSpiral(sStart, cDot, &x, &y, &tStart);
1702 for (s = sStart; s <= sEnd; s += resolution) {
1713 assert(ret.size() >= 2);
1714 assert(ret[0] != ret[1]);
1717 ret.
add(ret.front() * -1);
1723 << std::setprecision(4)
1724 <<
"edge=" << e.
id <<
" s=" << g.
s
1725 <<
" cStart=" << curveStart
1726 <<
" cEnd=" << curveEnd
1728 <<
" sStart=" << sStart
1732 <<
"\n beforeShift=" << ret1
1733 <<
"\n beforeRot=" << ret2
1737 ret.
add(g.
x, g.
y, 0);
1738 }
catch (
const std::runtime_error&
error) {
1739 WRITE_WARNING(
"Could not compute spiral geometry for edge '" + e.
id +
"' (" +
error.what() +
").");
1750 double centerX = g.
x;
1751 double centerY = g.
y;
1753 double curvature = g.
params[0];
1754 double radius = 1. / curvature;
1759 double startX = g.
x;
1760 double startY = g.
y;
1761 double geo_posS = g.
s;
1762 double geo_posE = g.
s;
1765 geo_posE += resolution;
1766 if (geo_posE - g.
s > g.
length) {
1769 if (geo_posE - g.
s > g.
length) {
1772 calcPointOnCurve(&endX, &endY, centerX, centerY, radius, geo_posE - geo_posS);
1773 ret.push_back(
Position(startX, startY));
1777 geo_posS = geo_posE;
1779 if (geo_posE - (g.
s + g.
length) < 0.001 && geo_posE - (g.
s + g.
length) > -0.001) {
1783 ret.push_back(
Position(startX, startY));
1791 const double s = sin(g.
hdg);
1792 const double c = cos(g.
hdg);
1794 for (
double off = 0; off < g.
length + 2.; off += resolution) {
1797 double xnew = x * c - y * s;
1798 double ynew = x * s + y * c;
1799 ret.push_back(
Position(g.
x + xnew, g.
y + ynew));
1808 const double s = sin(g.
hdg);
1809 const double c = cos(g.
hdg);
1811 const double pStep = pMax / ceil(g.
length / resolution);
1813 for (
double p = 0; p <= pMax + pStep; p += pStep) {
1816 double xnew = x * c - y * s;
1817 double ynew = x * s + y * c;
1818 ret.push_back(
Position(g.
x + xnew, g.
y + ynew));
1826 double normx = 1.0f;
1827 double normy = 0.0f;
1828 double x2 = normx * cos(hdg) - normy * sin(hdg);
1829 double y2 = normx * sin(hdg) + normy * cos(hdg);
1830 normx = x2 * length;
1831 normy = y2 * length;
1832 return Position(start.
x() + normx, start.
y() + normy);
1842 if (ad_radius > 0) {
1849 normX = normX * cos(ad_hdg) + normY * sin(ad_hdg);
1850 normY = tmpX * sin(ad_hdg) + normY * cos(ad_hdg);
1853 normX = turn * normY;
1854 normY = -turn * tmpX;
1856 normX = fabs(ad_radius) * normX;
1857 normY = fabs(ad_radius) * normY;
1866 double ad_r,
double ad_length) {
1867 double rotAngle = ad_length / fabs(ad_r);
1868 double vx = *ad_x - ad_centerX;
1869 double vy = *ad_y - ad_centerY;
1879 vx = vx * cos(rotAngle) + turn * vy * sin(rotAngle);
1880 vy = -1 * turn * tmpx * sin(rotAngle) + vy * cos(rotAngle);
1881 *ad_x = vx + ad_centerX;
1882 *ad_y = vy + ad_centerY;
1898 discardedInnerWidthRight = 0;
1900 bool singleType =
true;
1901 std::vector<std::string> types;
1902 const std::vector<OpenDriveLane>& dirLanesR = lanesByDir.find(
OPENDRIVE_TAG_RIGHT)->second;
1903 for (std::vector<OpenDriveLane>::const_reverse_iterator i = dirLanesR.rbegin(); i != dirLanesR.rend(); ++i) {
1905 discardedInnerWidthRight = 0;
1906 laneMap[(*i).id] = sumoLane++;
1907 types.push_back((*i).type);
1908 if (types.front() != types.back()) {
1912 discardedInnerWidthRight += (*i).width;
1915 discardedInnerWidthLeft = 0;
1916 rightLaneNumber = sumoLane;
1917 rightType = sumoLane > 0 ? (singleType ? types.front() :
joinToString(types,
"|")) :
"";
1921 const std::vector<OpenDriveLane>& dirLanesL = lanesByDir.find(
OPENDRIVE_TAG_LEFT)->second;
1922 for (std::vector<OpenDriveLane>::const_iterator i = dirLanesL.begin(); i != dirLanesL.end(); ++i) {
1924 discardedInnerWidthLeft = 0;
1925 laneMap[(*i).id] = sumoLane++;
1926 types.push_back((*i).type);
1927 if (types.front() != types.back()) {
1931 discardedInnerWidthLeft += (*i).width;
1934 leftLaneNumber = sumoLane;
1935 leftType = sumoLane > 0 ? (singleType ? types.front() :
joinToString(types,
"|")) :
"";
1941 std::map<int, int> ret;
1942 const std::vector<OpenDriveLane>& dirLanes = lanesByDir.find(dir)->second;
1943 for (std::vector<OpenDriveLane>::const_reverse_iterator i = dirLanes.rbegin(); i != dirLanes.rend(); ++i) {
1944 std::map<int, int>::const_iterator toP = laneMap.find((*i).id);
1945 if (toP == laneMap.end()) {
1949 int to = (*toP).second;
1952 from = (*i).predecessor;
1955 std::map<int, int>::const_iterator fromP = prev.
laneMap.find(from);
1956 if (fromP != prev.
laneMap.end()) {
1957 from = (*fromP).second;
1963 if (ret.find(from) != ret.end()) {
1986 if (i != l.
speeds.end()) {
1987 l.
speed = (*i).second;
1994 if (i != l.
speeds.end()) {
1995 l.
speed = (*i).second;
2004 std::set<double> speedChangePositions;
2007 for (std::vector<std::pair<double, double> >::const_iterator l = (*k).speeds.begin(); l != (*k).speeds.end(); ++l) {
2008 speedChangePositions.insert((*l).first);
2009 if ((*l).first == 0) {
2010 (*k).speed = (*l).second;
2015 for (std::vector<std::pair<double, double> >::const_iterator l = (*k).speeds.begin(); l != (*k).speeds.end(); ++l) {
2016 speedChangePositions.insert((*l).first);
2017 if ((*l).first == 0) {
2018 (*k).speed = (*l).second;
2023 if (speedChangePositions.size() == 0) {
2026 if (*speedChangePositions.begin() > 0) {
2027 speedChangePositions.insert(0);
2029#ifdef DEBUG_VARIABLE_SPEED
2031 <<
" buildSpeedChanges sectionStart=" << s
2032 <<
" speedChangePositions=" <<
joinToString(speedChangePositions,
", ")
2035 for (std::set<double>::iterator i = speedChangePositions.begin(); i != speedChangePositions.end(); ++i) {
2036 if (i == speedChangePositions.begin()) {
2037 newSections.push_back(*
this);
2039 newSections.push_back(buildLaneSection(*i));
2043 for (
int i = 0; i != (int)newSections.size(); ++i) {
2044 for (
auto& k : newSections[i].lanesByDir) {
2045 for (
int j = 0; j != (int)k.second.size(); ++j) {
2051 l.
speed = newSections[i - 1].lanesByDir[k.first][j].speed;
2070 for (std::vector<OpenDriveSignal>::const_iterator i = signals.begin(); i != signals.end(); ++i) {
2072 if ((*i).type ==
"301" || (*i).type ==
"306") {
2075 if ((*i).type ==
"205" ) {
2189 std::vector<double> vals;
2195 std::vector<double> vals;
2202 std::vector<double> vals;
2208 std::vector<double> vals;
2217 std::vector<double> vals;
2227 if (pRange ==
"normalized") {
2228 vals.push_back(1.0);
2229 }
else if (pRange ==
"arcLength") {
2230 vals.push_back(-1.0);
2233 vals.push_back(1.0);
2281 int orientationCode = orientation ==
"-" ? -1 : orientation ==
"+" ? 1 : 0;
2292 int orientationCode = orientation ==
"-" ? -1 : orientation ==
"+" ? 1 : 0;
2332 WRITE_ERROR(
"In laneLink-element: incoming road '" + c.fromEdge +
"' is not known.");
2348 l.width =
MAX2(l.width, a);
2350#ifdef DEBUG_VARIABLE_WIDTHS
2357 <<
" type=" << l.type
2358 <<
" width=" << l.width
2364 <<
" entries=" << l.widthData.size()
2378 if (!unit.empty()) {
2380 if (unit ==
"km/h") {
2383 if (unit ==
"mph") {
2384 speed *= 1.609344 / 3.6;
2416 const std::string baseID = o.
id;
2431 for (
double x = 0; x <= length + NUMERICAL_EPS; x += dist) {
2433 const double a = x / length;
2434 o.
width = wStart * (1 - a) + wEnd * a;
2435 o.
t = tStart * (1 - a) + tEnd * a;
2452 size_t i = cdata.find(
"+proj");
2453 if (i != std::string::npos) {
2454 const std::string proj = cdata.substr(i);
2466 WRITE_ERROR(
"Could not set projection (" + std::string(e.what()) +
"). This can be ignored with --ignore-errors.");
2470 WRITE_WARNING(
"geoReference format '" + cdata +
"' currently not supported");
2515 const std::string& elementID,
2516 const std::string& contactPoint) {
2519 if (elementType ==
"road") {
2521 }
else if (elementType ==
"junction") {
2525 if (contactPoint ==
"start") {
2527 }
else if (contactPoint ==
"end") {
2567#ifdef DEBUG_VARIABLE_WIDTHS
2570 std::cout <<
"sanitizeWidths e=" << e->
id <<
" sections=" << e->
laneSections.size() <<
"\n";
2588 if (l.widthData.size() > 0) {
2589 auto& wd = l.widthData;
2590 const double threshold = POSITION_EPS;
2591 double maxNoShort = -std::numeric_limits<double>::max();
2593 for (
int i = 0; i < (int)wd.size(); i++) {
2594 const double wdLength = i < (int)wd.size() - 1 ? wd[i + 1].s - wd[i].s : length - seen;
2596 if (wdLength > threshold) {
2597 maxNoShort =
MAX2(maxNoShort, wd[i].a);
2600 if (maxNoShort > 0) {
2601 l.width = maxNoShort;
2610 std::vector<OpenDriveLaneSection> newSections;
2611#ifdef DEBUG_VARIABLE_WIDTHS
2614 std::cout <<
"splitMinWidths e=" << e->
id <<
" sections=" << e->
laneSections.size() <<
"\n";
2619 std::vector<double> splitPositions;
2620 const double sectionEnd = (j + 1) == e->
laneSections.end() ? e->
length : (*(j + 1)).s;
2621 const int section = (int)(j - e->
laneSections.begin());
2622#ifdef DEBUG_VARIABLE_WIDTHS
2624 std::cout <<
" findWidthSplit section=" << section <<
" sectionStart=" << sec.
s <<
" sectionOrigStart=" << sec.
sOrig <<
" sectionEnd=" << sectionEnd <<
"\n";
2633 newSections.push_back(sec);
2634 std::sort(splitPositions.begin(), splitPositions.end());
2636 double prevSplit = sec.
s;
2637 for (std::vector<double>::iterator it = splitPositions.begin(); it != splitPositions.end();) {
2638 if ((*it) - prevSplit < minDist || sectionEnd - (*it) < minDist) {
2640#ifdef DEBUG_VARIABLE_WIDTHS
2642 std::cout <<
" skip close split=" << (*it) <<
" prevSplit=" << prevSplit <<
"\n";
2645 it = splitPositions.erase(it);
2646 }
else if ((*it) < sec.
s) {
2648#ifdef DEBUG_VARIABLE_WIDTHS
2650 std::cout <<
" skip early split=" << (*it) <<
" s=" << sec.
s <<
"\n";
2653 it = splitPositions.erase(it);
2660 if (splitPositions.size() > 0) {
2661#ifdef DEBUG_VARIABLE_WIDTHS
2663 std::cout <<
" road=" << e->
id <<
" splitMinWidths section=" << section
2664 <<
" start=" << sec.
s
2665 <<
" origStart=" << sec.
sOrig
2666 <<
" end=" << sectionEnd <<
" minDist=" << minDist
2667 <<
" splitPositions=" <<
toString(splitPositions) <<
"\n";
2670#ifdef DEBUG_VARIABLE_WIDTHS
2672 std::cout <<
"first section...\n";
2676 for (std::vector<double>::iterator it = splitPositions.begin(); it != splitPositions.end(); ++it) {
2679#ifdef DEBUG_VARIABLE_WIDTHS
2681 std::cout <<
"splitAt " << secNew.
s <<
"\n";
2684 newSections.push_back(secNew);
2691 double end = (it + 1) == splitPositions.end() ? sectionEnd : *(it + 1);
2703 int section,
double sectionStart,
double sectionEnd,
2704 std::vector<double>& splitPositions) {
2706 for (std::vector<OpenDriveLane>::iterator k = lanes.begin(); k != lanes.end(); ++k) {
2711 double wPrev = l.
widthData.front().computeAt(sPrev);
2713 <<
"findWidthSplit section=" << section
2714 <<
" sectionStart=" << sectionStart
2715 <<
" sectionEnd=" << sectionEnd
2717 <<
" type=" << l.
type
2718 <<
" widthEntries=" << l.
widthData.size() <<
"\n"
2722 for (std::vector<OpenDriveWidth>::iterator it_w = l.
widthData.begin(); it_w != l.
widthData.end(); ++it_w) {
2723 double sEnd = (it_w + 1) != l.
widthData.end() ? (*(it_w + 1)).s : sectionEnd - sectionStart;
2724 double w = (*it_w).computeAt(sEnd);
2727 <<
" s=" << (*it_w).s
2728 <<
" a=" << (*it_w).a <<
" b=" << (*it_w).b <<
" c=" << (*it_w).c <<
" d=" << (*it_w).d
2731 const double changeDist = fabs(
myMinWidth - wPrev);
2734 double splitPos = sPrev + (sEnd - sPrev) / fabs(w - wPrev) * changeDist;
2735 double wSplit = (*it_w).computeAt(splitPos);
2737 std::cout <<
" candidate splitPos=" << splitPos <<
" w=" << wSplit <<
"\n";
2743 splitPos -= POSITION_EPS;
2744 if (splitPos < sPrev) {
2746 std::cout <<
" aborting search splitPos=" << splitPos <<
" wSplit=" << wSplit <<
" sPrev=" << sPrev <<
" wPrev=" << wPrev <<
"\n";
2753 splitPos += POSITION_EPS;
2754 if (splitPos > sEnd) {
2756 std::cout <<
" aborting search splitPos=" << splitPos <<
" wSplit=" << wSplit <<
" sEnd=" << sEnd <<
" w=" << w <<
"\n";
2762 wSplit = (*it_w).computeAt(splitPos);
2764 std::cout <<
" refined splitPos=" << splitPos <<
" w=" << wSplit <<
"\n";
2767 splitPositions.push_back(sectionStart + splitPos);
2785 for (std::vector<OpenDriveLane>::iterator k = lanes.begin(); k != lanes.end(); ++k) {
2786 (*k).predecessor = (*k).id;
2804 for (std::vector<OpenDriveLane>::iterator k = lanes.begin(); k != lanes.end(); ++k) {
2807#ifdef DEBUG_VARIABLE_WIDTHS
2809 <<
"recomputeWidths lane=" << l.
id
2810 <<
" type=" << l.
type
2811 <<
" start=" << start
2813 <<
" sectionStart=" << sectionStart
2814 <<
" sectionEnd=" << sectionEnd
2815 <<
" widthEntries=" << l.
widthData.size() <<
"\n"
2820 double sPrevAbs = sPrev + sectionStart;
2821 for (std::vector<OpenDriveWidth>::iterator it_w = l.
widthData.begin(); it_w != l.
widthData.end(); ++it_w) {
2822 double sEnd = (it_w + 1) != l.
widthData.end() ? (*(it_w + 1)).s : sectionEnd - sectionStart;
2823 double sEndAbs = sEnd + sectionStart;
2824#ifdef DEBUG_VARIABLE_WIDTHS
2826 <<
" sPrev=" << sPrev <<
" sPrevAbs=" << sPrevAbs
2827 <<
" sEnd=" << sEnd <<
" sEndAbs=" << sEndAbs
2828 <<
" widthData s=" << (*it_w).s
2829 <<
" a=" << (*it_w).a
2830 <<
" b=" << (*it_w).b
2831 <<
" c=" << (*it_w).c
2832 <<
" d=" << (*it_w).d
2835 if (sPrevAbs <= start && sEndAbs >= start) {
2836#ifdef DEBUG_VARIABLE_WIDTHS
2838 std::cout <<
" atStart=" << start <<
" pos=" << start - sectionStart <<
" w=" << (*it_w).computeAt(start - sectionStart) <<
"\n";
2841 l.
width =
MAX2(l.
width, (*it_w).computeAt(start - sectionStart));
2843 if (sPrevAbs <= end && sEndAbs >= end) {
2844#ifdef DEBUG_VARIABLE_WIDTHS
2846 std::cout <<
" atEnd=" << end <<
" pos=" << end - sectionStart <<
" w=" << (*it_w).computeAt(end - sectionStart) <<
"\n";
2851 if (start <= sPrevAbs && end >= sPrevAbs) {
2852#ifdef DEBUG_VARIABLE_WIDTHS
2854 std::cout <<
" atSPrev=" << sPrev <<
" w=" << (*it_w).computeAt(sPrev) <<
"\n";
2859 if (start <= sEndAbs && end >= sEndAbs) {
2860#ifdef DEBUG_VARIABLE_WIDTHS
2862 std::cout <<
" atSEnd=" << sEnd <<
" w=" << (*it_w).computeAt(sEnd) <<
"\n";
2867#ifdef DEBUG_VARIABLE_WIDTHS
2869 std::cout <<
" sPrev=" << sPrev <<
" sEnd=" << sEnd <<
" l.width=" << l.
width <<
"\n";
#define WRITE_WARNINGF(...)
#define WRITE_WARNING(msg)
#define PROGRESS_DONE_MESSAGE()
#define PROGRESS_BEGIN_MESSAGE(msg)
std::set< NBNode *, ComparatorIdLess > NodeSet
#define DEBUG_COND3(roadID)
bool operator<(const NIImporter_OpenDrive::Connection &c1, const NIImporter_OpenDrive::Connection &c2)
#define DEBUG_COND2(edgeID)
@ SVC_PASSENGER
vehicle is a passenger car (a "normal" car)
@ SVC_BICYCLE
vehicle is a bicycle
@ SVC_EMERGENCY
public emergency vehicles
@ SVC_AUTHORITY
authorities vehicles
@ SVC_PEDESTRIAN
pedestrian
int SVCPermissions
bitset where each bit declares whether a certain SVC may use this edge/lane
const std::string SUMO_PARAM_ORIGID
int gPrecision
the precision for floating point outputs
bool gDebugFlag1
global utility flags for debugging
#define UNUSED_PARAMETER(x)
std::string joinToString(const std::vector< T > &v, const T_BETWEEN &between, std::streamsize accuracy=gPrecision)
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
A class that stores a 2D geometrical boundary.
void add(double x, double y, double z=0)
Makes the boundary include the given coordinate.
static bool isReadable(std::string path)
Checks whether the given file is readable.
A handler which converts occuring elements and attributes into enums.
void needsCharacterData(const bool value=true)
void error(const XERCES_CPP_NAMESPACE::SAXParseException &exception)
Handler for XML-errors.
void setFileName(const std::string &name)
Sets the current file name.
static methods for processing the coordinates conversion for the current net
void cartesian2geo(Position &cartesian) const
Converts the given cartesian (shifted) position to its geo (lat/long) representation.
void moveConvertedBy(double x, double y)
Shifts the converted boundary by the given amounts.
static int getNumLoaded()
static void setLoaded(const GeoConvHelper &loaded)
sets the coordinate transformation loaded from a location element
bool usingGeoProjection() const
Returns whether a transformation from geo to metric coordinates will be performed.
static GeoConvHelper & getLoaded()
the coordinate transformation that was loaded fron an input file
static double naviDegree(const double angle)
NBEdge * retrieve(const std::string &id, bool retrieveExtracted=false) const
Returns the edge that has the given id.
bool wasIgnored(std::string id) const
Returns whether the edge with the id was ignored during parsing.
bool insert(NBEdge *edge, bool ignorePrunning=false)
Adds an edge to the dictionary.
The representation of a single edge during network building.
const std::vector< Connection > & getConnections() const
Returns the connections.
NBNode * getToNode() const
Returns the destination node of the edge.
static const double UNSPECIFIED_FRICTION
unspecified lane friction
Lane & getLaneStruct(int lane)
bool addLane2LaneConnection(int fromLane, NBEdge *dest, int toLane, Lane2LaneInfoType type, bool mayUseSameDestination=false, bool mayDefinitelyPass=false, KeepClear keepClear=KEEPCLEAR_UNSPECIFIED, double contPos=UNSPECIFIED_CONTPOS, double visibility=UNSPECIFIED_VISIBILITY_DISTANCE, double speed=UNSPECIFIED_SPEED, double friction=UNSPECIFIED_FRICTION, double length=myDefaultConnectionLength, const PositionVector &customShape=PositionVector::EMPTY, const bool uncontrolled=UNSPECIFIED_CONNECTION_UNCONTROLLED, SVCPermissions permissions=SVC_UNSPECIFIED, const bool indirectLeft=false, const std::string &edgeType="", SVCPermissions changeLeft=SVC_UNSPECIFIED, SVCPermissions changeRight=SVC_UNSPECIFIED, bool postProcess=false)
Adds a connection between the specified this edge's lane and an approached one.
const std::string & getID() const
static const double UNSPECIFIED_LOADED_LENGTH
no length override given
static const double UNSPECIFIED_CONTPOS
unspecified internal junction position
static const double UNSPECIFIED_VISIBILITY_DISTANCE
unspecified foe visibility for connections
static const double UNSPECIFIED_SPEED
unspecified lane speed
@ USER
The connection was given by the user.
@ VALIDATED
The connection was computed and validated.
NBNode * getFromNode() const
Returns the origin node of the edge.
static const double UNSPECIFIED_WIDTH
unspecified lane width
static const double UNSPECIFIED_OFFSET
unspecified lane offset
Instance responsible for building networks.
static bool transformCoordinates(PositionVector &from, bool includeInBoundary=true, GeoConvHelper *from_srs=nullptr)
NBNodeCont & getNodeCont()
Returns a reference to the node container.
NBEdgeCont & getEdgeCont()
NBTypeCont & getTypeCont()
Returns a reference to the type container.
NBTrafficLightLogicCont & getTLLogicCont()
Returns a reference to the traffic light logics container.
Container for nodes during the netbuilding process.
std::string createClusterId(const NodeSet &cluster, const std::string &prefix="cluster_")
generate id from cluster node ids
bool insert(const std::string &id, const Position &position, NBDistrict *district=0)
Inserts a node into the map.
NBNode * retrieve(const std::string &id) const
Returns the node with the given name.
bool extract(NBNode *node, bool remember=false)
Removes the given node but does not delete it.
Represents a single node (junction) during network building.
const std::set< NBTrafficLightDefinition * > & getControllingTLS() const
Returns the traffic lights that were assigned to this node (The set of tls that control this node)
void addTrafficLight(NBTrafficLightDefinition *tlDef)
Adds a traffic light to the list of traffic lights that control this node.
bool isTLControlled() const
Returns whether this node is controlled by any tls.
A traffic light logics which must be computed (only nodes/edges are given)
The base class for traffic light logic definitions.
bool insert(NBTrafficLightDefinition *logic, bool forceInsert=false)
Adds a logic definition to the dictionary.
A storage for available edgeTypes of edges.
double getEdgeTypeMaxWidth(const std::string &edgeType) const
Returns the maximum edge/lane widths of the given edgeType.
bool getEdgeTypeShallBeDiscarded(const std::string &edgeType) const
Returns the information whether edges of this edgeType shall be discarded.
double getEdgeTypeSpeed(const std::string &edgeType) const
Returns the maximal velocity for the given edgeType [m/s].
double getEdgeTypeWidth(const std::string &edgeType) const
Returns the lane width for the given edgeType [m].
SVCPermissions getEdgeTypePermissions(const std::string &edgeType) const
Returns allowed vehicle classes for the given edgeType.
double getEdgeTypeWidthResolution(const std::string &edgeType) const
Returns the resolution for interpreting edge/lane widths of the given edgeType.
bool knows(const std::string &edgeType) const
Returns whether the named edgeType is in the container.
A class for sorting lane sections by their s-value.
Importer for networks stored in openDrive format.
static void loadNetwork(const OptionsCont &oc, NBNetBuilder &nb)
Loads content of the optionally given SUMO file.
static void recomputeWidths(OpenDriveLaneSection &sec, double start, double end, double sectionStart, double sectionEnd)
static std::vector< double > discretizeOffsets(PositionVector &geom, const std::vector< OpenDriveLaneOffset > &offsets, const std::string &id)
transform Poly3 into a list of offsets, adding intermediate points to geom if needed
static void addOffsets(bool left, PositionVector &geom, const std::vector< OpenDriveLaneOffset > &offsets, const std::string &id, std::vector< double > &result)
static std::pair< NBEdge *, NBEdge * > retrieveSignalEdges(NBNetBuilder &nb, const std::string &fromID, const std::string &toID, const std::string &junction)
static PositionVector geomFromParamPoly(const OpenDriveEdge &e, const OpenDriveGeometry &g, double resolution)
void myEndElement(int element)
Called when a closing tag occurs.
static void calcPointOnCurve(double *ad_x, double *ad_y, double ad_centerX, double ad_centerY, double ad_r, double ad_length)
static bool myImportInternalShapes
OpenDriveXMLTag
Numbers representing openDrive-XML - element names.
@ OPENDRIVE_TAG_ELEVATION
@ OPENDRIVE_TAG_PARAMPOLY3
@ OPENDRIVE_TAG_LANEOFFSET
@ OPENDRIVE_TAG_SIGNALREFERENCE
@ OPENDRIVE_TAG_GEOREFERENCE
@ OPENDRIVE_TAG_SUCCESSOR
@ OPENDRIVE_TAG_PREDECESSOR
@ OPENDRIVE_TAG_LANESECTION
@ OPENDRIVE_TAG_CONNECTION
void addGeometryShape(GeometryType type, const std::vector< double > &vals)
static bool myImportWidths
static void setStraightConnections(std::vector< OpenDriveLane > &lanes)
std::string myCurrentConnectingRoad
static void setLaneAttributes(const OpenDriveEdge *e, NBEdge::Lane &sumoLane, const OpenDriveLane &odLane, bool saveOrigIDs, const NBTypeCont &tc)
std::vector< int > myElementStack
~NIImporter_OpenDrive()
Destructor.
static void buildConnectionsToOuter(const Connection &c, const std::map< std::string, OpenDriveEdge * > &innerEdges, const std::map< std::string, OpenDriveEdge * > &edges, const NBTypeCont &tc, std::vector< Connection > &into, std::set< Connection > &seen)
void myStartElement(int element, const SUMOSAXAttributes &attrs)
Called on the opening of a tag;.
static StringBijection< int >::Entry openDriveAttrs[]
The names of openDrive-XML attributes (for passing to GenericSAXHandler)
std::map< std::string, OpenDriveSignal > & getSignals()
std::map< std::string, OpenDriveSignal > mySignals
static bool laneSectionsConnected(OpenDriveEdge *edge, int in, int out)
void addLink(LinkType lt, const std::string &elementType, const std::string &elementID, const std::string &contactPoint)
@ OPENDRIVE_ATTR_REVMAJOR
@ OPENDRIVE_ATTR_CURVSTART
@ OPENDRIVE_ATTR_CONTACTPOINT
@ OPENDRIVE_ATTR_REVMINOR
@ OPENDRIVE_ATTR_ORIENTATION
@ OPENDRIVE_ATTR_INCOMINGROAD
@ OPENDRIVE_ATTR_CURVATURE
@ OPENDRIVE_ATTR_ELEMENTTYPE
@ OPENDRIVE_ATTR_JUNCTION
@ OPENDRIVE_ATTR_CONNECTINGROAD
@ OPENDRIVE_ATTR_WIDTHEND
@ OPENDRIVE_ATTR_FROMLANE
@ OPENDRIVE_ATTR_DISTANCE
@ OPENDRIVE_ATTR_ELEMENTID
@ OPENDRIVE_ATTR_WIDTHSTART
static PositionVector geomFromSpiral(const OpenDriveEdge &e, const OpenDriveGeometry &g, double resolution)
static PositionVector geomFromLine(const OpenDriveEdge &e, const OpenDriveGeometry &g, double resolution)
static NBNode * getOrBuildNode(const std::string &id, const Position &pos, NBNodeCont &nc)
Builds a node or returns the already built.
const NBTypeCont & myTypeContainer
NIImporter_OpenDrive(const NBTypeCont &tc, std::map< std::string, OpenDriveEdge * > &edges)
Constructor.
static Position calculateStraightEndPoint(double hdg, double length, const Position &start)
OpenDriveXMLTag myCurrentLaneDirection
static PositionVector geomFromPoly(const OpenDriveEdge &e, const OpenDriveGeometry &g, double resolution)
static void revisitLaneSections(const NBTypeCont &tc, std::map< std::string, OpenDriveEdge * > &edges)
Rechecks lane sections of the given edges.
Poly3 OpenDriveLaneOffset
OpenDriveEdge myCurrentEdge
static void sanitizeWidths(OpenDriveEdge *e)
GeometryType
OpenDrive geometry type enumeration.
@ OPENDRIVE_GT_PARAMPOLY3
static void computeShapes(std::map< std::string, OpenDriveEdge * > &edges)
Computes a polygon representation of each edge's geometry.
static void calculateCurveCenter(double *ad_x, double *ad_y, double ad_radius, double ad_hdg)
static std::string revertID(const std::string &id)
std::string myCurrentJunctionID
static void setEdgeLinks2(OpenDriveEdge &e, const std::map< std::string, OpenDriveEdge * > &edges)
std::string myCurrentIncomingRoad
static void splitMinWidths(OpenDriveEdge *e, const NBTypeCont &tc, double minDist)
bool myConnectionWasEmpty
static bool myImportAllTypes
void myCharacters(int element, const std::string &chars)
Callback method for characters to implement by derived classes.
static NBTrafficLightDefinition * getTLSSecure(NBEdge *inEdge, NBNetBuilder &nb)
static StringBijection< int >::Entry openDriveTags[]
The names of openDrive-XML elements (for passing to GenericSAXHandler)
Poly3 OpenDriveElevation
LaneOffset has the same fields as Elevation.
ContactPoint myCurrentContactPoint
static void findWidthSplit(const NBTypeCont &tc, std::vector< OpenDriveLane > &lanes, int section, double sectionStart, double sectionEnd, std::vector< double > &splitPositions)
static PositionVector geomFromArc(const OpenDriveEdge &e, const OpenDriveGeometry &g, double resolution)
static void setNodeSecure(NBNodeCont &nc, OpenDriveEdge &e, const std::string &nodeID, NIImporter_OpenDrive::LinkType lt, std::vector< NodeSet > &joinedNodeIDs)
LinkType
OpenDrive link type enumeration.
@ OPENDRIVE_LT_PREDECESSOR
static bool hasNonLinearElevation(OpenDriveEdge &e)
std::map< std::string, OpenDriveEdge * > & myEdges
const std::string & getID() const
Returns the id.
A storage for options typed value containers)
bool isSet(const std::string &name, bool failOnNonExistant=true) const
Returns the information whether the named option is set.
double getFloat(const std::string &name) const
Returns the double-value of the named option (only for Option_Float)
std::string getString(const std::string &name) const
Returns the string-value of the named option (only for Option_String)
bool isDefault(const std::string &name) const
Returns the information whether the named option has still the default value.
bool exists(const std::string &name) const
Returns the information whether the named option is known.
bool getBool(const std::string &name) const
Returns the boolean-value of the named option (only for Option_Bool)
const StringVector & getStringVector(const std::string &name) const
Returns the list of string-value of the named option (only for Option_StringVector)
static OptionsCont & getOptions()
Retrieves the options.
bool isUsableFileList(const std::string &name) const
Checks whether the named option is usable as a file list (with at least a single file)
Static storage of an output device and its base (abstract) implementation.
static OutputDevice & getDevice(const std::string &name, bool usePrefix=true)
Returns the described OutputDevice.
bool writeXMLHeader(const std::string &rootElement, const std::string &schemaFile, std::map< SumoXMLAttr, std::string > attrs=std::map< SumoXMLAttr, std::string >(), bool includeConfig=true)
Writes an XML header with optional configuration.
virtual void setParameter(const std::string &key, const std::string &value)
Sets a parameter.
void writeXML(OutputDevice &out, const bool geo=false, const double zOffset=0., const std::string laneID="", const double pos=0., const bool friendlyPos=false, const double posLat=0.) const
A point in 2D or 3D with translation and scaling methods.
void set(double x, double y)
set positions x and y
double distanceTo2D(const Position &p2) const
returns the euclidean distance in the x-y-plane
double x() const
Returns the x-position.
void add(const Position &pos)
Adds the given position to this one.
void mul(double val)
Multiplies both positions with the given value.
double y() const
Returns the y-position.
double length2D() const
Returns the length.
void append(const PositionVector &v, double sameThreshold=2.0)
void move2sideCustom(std::vector< double > amount, double maxExtension=100)
move position vector to side using a custom offset for each geometry point
void rotate2D(double angle)
double rotationAtOffset(double pos) const
Returns the rotation at the given length.
Position positionAtOffset(double pos, double lateralOffset=0) const
Returns the position at the given length.
void add(double xoff, double yoff, double zoff)
int indexOfClosest(const Position &p, bool twoD=false) const
void move2side(double amount, double maxExtension=100)
move position vector to side using certain ammount
PositionVector getSubpart2D(double beginOffset, double endOffset) const
get subpart of a position vector in two dimensions (Z is ignored)
Boundary getBoxBoundary() const
Returns a boundary enclosing this list of lines.
int insertAtClosest(const Position &p, bool interpolateZ)
inserts p between the two closest positions
void push_back_noDoublePos(const Position &p)
insert in back a non double position
void removeDoublePoints(double minDist=POSITION_EPS, bool assertLength=false, int beginOffset=0, int endOffset=0, bool resample=false)
Removes positions if too near.
PositionVector reverse() const
reverse position vector
Position positionAtOffset2D(double pos, double lateralOffset=0) const
Returns the position at the given length.
static const RGBColor YELLOW
void writeXML(OutputDevice &out, bool geo=false) const
Encapsulated SAX-Attributes.
T getOpt(int attr, const char *objectid, bool &ok, T defaultValue=T(), bool report=true) const
Tries to read given attribute assuming it is an int.
T get(int attr, const char *objectid, bool &ok, bool report=true) const
Tries to read given attribute assuming it is an int.
virtual bool hasAttribute(int id) const =0
Returns the information whether the named (by its enum-value) attribute is within the current list.
static StringBijection< TrafficLightType > TrafficLightTypes
traffic light types
T get(const std::string &str) const
static int toInt(const std::string &sData)
converts a string into the integer value described by it by calling the char-type converter,...
static bool runParser(GenericSAXHandler &handler, const std::string &file, const bool isNet=false, const bool isRoute=false)
Runs the given handler on the given file; returns if everything's ok.
NLOHMANN_BASIC_JSON_TPL_DECLARATION void swap(nlohmann::NLOHMANN_BASIC_JSON_TPL &j1, nlohmann::NLOHMANN_BASIC_JSON_TPL &j2) noexcept(//NOLINT(readability-inconsistent-declaration-parameter-name) is_nothrow_move_constructible< nlohmann::NLOHMANN_BASIC_JSON_TPL >::value &&//NOLINT(misc-redundant-expression) is_nothrow_move_assignable< nlohmann::NLOHMANN_BASIC_JSON_TPL >::value)
exchanges the values of two JSON objects
void odrSpiral(double s, double cDot, double *x, double *y, double *t)
A structure which describes a connection between edges or lanes.
An (internal) definition of a single lane of an edge.
double width
This lane's width.
PositionVector customShape
A custom shape for this lane set by the user.
std::string type
the type of this lane
double speed
The speed allowed on this lane.
SVCPermissions permissions
List of vehicle types that are allowed on this lane.
A connection between two roads.
std::string getDescription() const
Representation of an openDrive "link".
double length
The length of the edge.
std::vector< double > laneOffsets
std::string id
The id of the edge.
std::set< Connection > connections
std::string junction
The id of the junction the edge belongs to.
std::string streetName
The road name of the edge.
int getPriority(OpenDriveXMLTag dir) const
Returns the edge's priority, regarding the direction.
std::vector< OpenDriveLink > links
std::vector< OpenDriveSignal > signals
std::vector< OpenDriveLaneSection > laneSections
std::vector< OpenDriveLaneOffset > offsets
std::vector< OpenDriveObject > objects
std::vector< OpenDriveGeometry > geometries
std::vector< OpenDriveElevation > elevations
Representation of an OpenDrive geometry part.
std::vector< double > params
Representation of a lane.
std::vector< std::pair< double, double > > speeds
List of positions/speeds of speed changes.
std::vector< OpenDriveWidth > widthData
std::string type
The lane's type.
double speed
The lane's speed (set in post-processing)
Representation of a lane section.
double length
The length of this lane section.
std::map< OpenDriveXMLTag, std::vector< OpenDriveLane > > lanesByDir
The lanes, sorted by their direction.
std::map< int, int > laneMap
A mapping from OpenDrive to SUMO-index (the first is signed, the second unsigned)
OpenDriveLaneSection buildLaneSection(double startPos)
OpenDriveLaneSection(double sArg)
Constructor.
int rightLaneNumber
The number of lanes on the right and on the left side, respectively.
double sOrig
The original starting offset of this lane section (differs from s if the section had to be split)
void buildLaneMapping(const NBTypeCont &tc)
Build the mapping from OpenDrive to SUMO lanes.
std::map< int, int > getInnerConnections(OpenDriveXMLTag dir, const OpenDriveLaneSection &prev)
Returns the links from the previous to this lane section.
bool buildSpeedChanges(const NBTypeCont &tc, std::vector< OpenDriveLaneSection > &newSections)
double s
The starting offset of this lane section.
Representation of an OpenDrive link.
ContactPoint contactPoint
Representation of a signal.
int minLane
signal validity range
double computeAt(double pos) const