66#define DEBUG_COND(road) ((road)->id == DEBUG_ID)
67#define DEBUG_COND2(edgeID) (StringUtils::startsWith((edgeID), DEBUG_ID))
68#define DEBUG_COND3(roadID) (roadID == DEBUG_ID)
208 const bool customLaneShapes = oc.
getBool(
"opendrive.lane-shapes");
212 std::map<std::string, OpenDriveEdge*> edges;
216 for (
const std::string& file : oc.
getStringVector(
"opendrive-files")) {
223 for (
auto& item : edges) {
225 if (signal.type ==
"") {
226 if (handler.
getSignals().count(signal.id) == 0) {
230 signal.type = ref.
type;
231 signal.name = ref.
name;
240 std::map<std::string, OpenDriveEdge*> innerEdges, outerEdges;
241 for (std::map<std::string, OpenDriveEdge*>::iterator i = edges.begin(); i != edges.end(); ++i) {
242 if ((*i).second->isInner) {
243 innerEdges[(*i).first] = (*i).second;
245 outerEdges[(*i).first] = (*i).second;
260 std::map<std::string, Boundary> posMap;
261 std::map<std::string, std::string> edge2junction;
262 std::vector<NodeSet> joinedNodeIDs;
264 for (std::map<std::string, OpenDriveEdge*>::iterator i = innerEdges.begin(); i != innerEdges.end(); ++i) {
268 if (posMap.find(e->
junction) == posMap.end()) {
274 for (std::map<std::string, Boundary>::iterator i = posMap.begin(); i != posMap.end(); ++i) {
281 for (std::map<std::string, OpenDriveEdge*>::iterator i = outerEdges.begin(); i != outerEdges.end(); ++i) {
283 for (std::vector<OpenDriveLink>::iterator j = e->
links.begin(); j != e->
links.end(); ++j) {
298 if (edge2junction.find(l.
elementID) != edge2junction.end()) {
310 for (std::map<std::string, OpenDriveEdge*>::iterator i = outerEdges.begin(); i != outerEdges.end(); ++i) {
312 for (std::vector<OpenDriveLink>::iterator j = e->
links.begin(); j != e->
links.end(); ++j) {
319 std::string id1 = e->
id;
324 std::string nid = id1 +
"." + id2;
347 for (std::map<std::string, OpenDriveEdge*>::iterator i = outerEdges.begin(); i != outerEdges.end(); ++i) {
349 if (e->
to !=
nullptr && e->
from !=
nullptr) {
352 for (std::map<std::string, OpenDriveEdge*>::iterator j = innerEdges.begin(); j != innerEdges.end(); ++j) {
354 for (std::vector<OpenDriveLink>::iterator k = ie->
links.begin(); k != ie->
links.end(); ++k) {
360 std::string nid = edge2junction[ie->
id];
372 for (std::map<std::string, OpenDriveEdge*>::iterator i = outerEdges.begin(); i != outerEdges.end(); ++i) {
374 if ((e->
from ==
nullptr || e->
to ==
nullptr) && e->
geom.size() == 0) {
377 if (e->
from ==
nullptr) {
378 const std::string nid = e->
id +
".begin";
381 if (e->
to ==
nullptr) {
382 const std::string nid = e->
id +
".end";
387 std::map<NBNode*, NBNode*> joinedNodes;
388 for (
NodeSet& joined : joinedNodeIDs) {
390 for (
NBNode* j : joined) {
391 joinedPos.
add(j->getPosition());
393 joinedPos.
mul(1. / (
double)joined.size());
395 if (!nc.
insert(joinedID, joinedPos)) {
399 for (
NBNode* j : joined) {
403 for (std::map<std::string, OpenDriveEdge*>::iterator i = outerEdges.begin(); i != outerEdges.end(); ++i) {
405 if (joinedNodes.count(e->
from) != 0) {
409 if (joinedNodes.count(e->
to) != 0) {
411 e->
to = joinedNodes[e->
to];
423 std::map<std::pair<NBEdge*, int>,
int> laneIndexMap;
425 for (std::map<std::string, OpenDriveEdge*>::iterator i = outerEdges.begin(); i != outerEdges.end(); ++i) {
427 if (e->
geom.size() < 2) {
431 bool lanesBuilt =
false;
457 std::cout <<
" geomWithOffset=" << geomWithOffset <<
"\n";
460 const double length2D = geomWithOffset.
length2D();
461 double cF = length2D == 0 ? 1 : e->
length / length2D;
462 NBEdge* prevRight =
nullptr;
463 NBEdge* prevLeft =
nullptr;
471 WRITE_WARNING(
"Edge '" + e->
id +
"' has to be split as it connects same junctions.")
475 const double minDist = oc.
getFloat(
"opendrive.curve-resolution");
480 int sectionIndex = 0;
487 double nextS = (j + 1)->s;
488 const std::string nodeID = e->
id + (positionIDs ?
"." +
toString(nextS) :
"#" +
toString(sectionIndex + 1));
496 std::string
id = e->
id;
498 if (sFrom != e->
from || sTo != e->
to) {
504 id =
id +
"#" +
toString(sectionIndex++);
506#ifdef DEBUG_VARIABLE_WIDTHS
508 std::cout <<
" id=" <<
id <<
" sB=" << sB <<
" sE=" << sE <<
" geom=" << geom <<
"\n";
513 NBEdge* currRight =
nullptr;
514 if ((*j).rightLaneNumber > 0) {
515 std::vector<double> offsets(geom.size(), 0);
516 bool useOffsets =
false;
523 rightGeom.
move2side((*j).discardedInnerWidthRight);
526 std::cout <<
" -" <<
id <<
"_geom=" << geom <<
" -" <<
id <<
"_rightGeom=" << rightGeom <<
"\n";
535 std::sort(lanes.begin(), lanes.end(),
LaneSorter());
537 std::map<int, int>::const_iterator lp = (*j).laneMap.find(odl.id);
538 if (lp != (*j).laneMap.end()) {
539 int sumoLaneIndex = lp->second;
541 laneIndexMap[std::make_pair(currRight, sumoLaneIndex)] = odl.id;
547 }
else if (customLaneShapes) {
550 if (customLaneShapes) {
561 if (prevRight !=
nullptr) {
563 for (std::map<int, int>::const_iterator k = connections.begin(); k != connections.end(); ++k) {
564#ifdef DEBUG_CONNECTIONS
566 std::cout <<
"addCon1 from=" << prevRight->
getID() <<
"_" << (*k).first <<
" to=" << currRight->
getID() <<
"_" << (*k).second <<
"\n";
572 prevRight = currRight;
577 NBEdge* currLeft =
nullptr;
578 if ((*j).leftLaneNumber > 0) {
579 std::vector<double> offsets(geom.size(), 0);
580 bool useOffsets =
false;
582 leftGeom.
move2side(-(*j).discardedInnerWidthLeft);
586 std::cout <<
" " <<
id <<
"_geom=" << geom <<
" " <<
id <<
"_leftGeom=" << leftGeom <<
"\n";
593 std::sort(lanes.begin(), lanes.end(),
LaneSorter());
594 for (std::vector<OpenDriveLane>::const_iterator k = lanes.begin(); k != lanes.end(); ++k) {
595 std::map<int, int>::const_iterator lp = (*j).laneMap.find((*k).id);
596 if (lp != (*j).laneMap.end()) {
597 int sumoLaneIndex = lp->second;
599 laneIndexMap[std::make_pair(currLeft, sumoLaneIndex)] = (*k).id;
605 }
else if (customLaneShapes) {
608 if (customLaneShapes) {
619 if (prevLeft !=
nullptr) {
620 std::map<int, int> connections = (*j).getInnerConnections(
OPENDRIVE_TAG_LEFT, *(j - 1));
621 for (std::map<int, int>::const_iterator k = connections.begin(); k != connections.end(); ++k) {
622#ifdef DEBUG_CONNECTIONS
624 std::cout <<
"addCon2 from=" << currLeft->
getID() <<
"_" << (*k).first <<
" to=" << prevLeft->
getID() <<
"_" << (*k).second <<
"\n";
639 if (oc.
isSet(
"polygon-output")) {
646 if (oc.
isSet(
"polygon-output")) {
647 for (
auto item : innerEdges) {
656 for (std::map<std::string, OpenDriveEdge*>::iterator i = edges.begin(); i != edges.end(); ++i) {
660 std::vector<Connection> connections2;
661 for (std::map<std::string, OpenDriveEdge*>::iterator j = edges.begin(); j != edges.end(); ++j) {
662 const std::set<Connection>& conns = (*j).second->connections;
664 for (std::set<Connection>::const_iterator i = conns.begin(); i != conns.end(); ++i) {
665 if (innerEdges.find((*i).fromEdge) != innerEdges.end()) {
669 if (innerEdges.find((*i).toEdge) != innerEdges.end()) {
670 std::set<Connection> seen;
673 connections2.push_back(*i);
678 for (std::vector<Connection>::const_iterator i = connections2.begin(); i != connections2.end(); ++i) {
679#ifdef DEBUG_CONNECTIONS
680 std::cout <<
"connections2 " << (*i).getDescription() <<
"\n";
682 std::string fromEdge = (*i).fromEdge;
683 if (edges.find(fromEdge) == edges.end()) {
684 WRITE_WARNINGF(
TL(
"While setting connections: from-edge '%' is not known."), fromEdge);
688 int fromLane = (*i).fromLane;
692 std::string toEdge = (*i).toEdge;
693 if (edges.find(toEdge) == edges.end()) {
694 WRITE_WARNINGF(
TL(
"While setting connections: to-edge '%' is not known."), toEdge);
699 int toLane = (*i).toLane;
719 if (from ==
nullptr) {
720 WRITE_WARNINGF(
TL(
"Could not find fromEdge representation of '%' in connection '%'."), fromEdge, (*i).origID);
723 WRITE_WARNINGF(
TL(
"Could not find fromEdge representation of '%' in connection '%'."), toEdge, (*i).origID);
725 if (from ==
nullptr || to ==
nullptr) {
729#ifdef DEBUG_CONNECTIONS
731 std::cout <<
"addCon3 from=" << from->
getID() <<
"_" << fromLane <<
" to=" << to->
getID() <<
"_" << toLane <<
"\n";
743 if ((*i).origID !=
"" && saveOrigIDs) {
746 for (std::vector<NBEdge::Connection>::iterator k = cons.begin(); k != cons.end(); ++k) {
747 if ((*k).fromLane == fromLane && (*k).toEdge == to && (*k).toLane == toLane) {
759 std::map<std::string, std::string> signal2junction;
760 std::map<std::string, OpenDriveController>& controllers = handler.
getControllers();
762 for (
const auto& it : edges) {
765 if (signal.controller.size() == 0) {
768 std::string junctionID;
770 if ((connection.fromLane < 0 && signal.orientation < 0) || (connection.fromLane > 0 && signal.orientation > 0)) {
773 if ((signal.minLane == 0 && signal.maxLane == 0) || (signal.maxLane >= connection.fromLane && signal.minLane <= connection.fromLane)) {
774 const OpenDriveEdge* connectedEdge = edges[connection.toEdge];
775 if (controllers[signal.controller].junction.size() > 0 && controllers[signal.controller].junction != connectedEdge->
junction) {
776 WRITE_WARNINGF(
TL(
"Controlling multiple junctions by the same controller '%' is currently not implemented."), signal.controller);
778 controllers[signal.controller].junction = connectedEdge->
junction;
784 const bool importSignalGroups = oc.
getBool(
"opendrive.signal-groups");
785 for (std::map<std::string, OpenDriveEdge*>::iterator i = edges.begin(); i != edges.end(); ++i) {
792 if (intType < 1000001 || (intType > 1000013 && intType != 1000020) || intType == 1000008) {
800 std::vector<OpenDriveLaneSection>::iterator k = e->
laneSections.begin();
803 if (signal.s > (*k).s && signal.s <= (*(k + 1)).s) {
810 std::string
id = (*k).sumoID;
815 std::string fromID, toID;
816 for (std::vector<OpenDriveLink>::const_iterator l = e->
links.begin(); l != e->
links.end(); ++l) {
824 if (signal.orientation < 0) {
825 fromID =
"-" + fromID;
829 if (signal.orientation > 0) {
830 fromID =
"-" + fromID;
848 if (from ==
nullptr) {
849 WRITE_WARNINGF(
TL(
"Could not find edge '%' for signal '%'."), fromID, signal.id);
854 if (signal.maxLane != 0) {
855 bool fromForward = from->
getID()[0] ==
'-';
856 bool lanesForward = signal.maxLane < 0;
857 if (fromForward != lanesForward) {
861 from = signalFromTo.first;
862 to = signalFromTo.second;
863 if (from ==
nullptr) {
864 WRITE_WARNINGF(
TL(
"Could not find edge '%' for signal '%'."), fromID, signal.id);
870 if (c.toEdge == to) {
871 int odLane = laneIndexMap[std::make_pair(from, c.fromLane)];
873 if (signal.minLane == 0 || (signal.minLane <= odLane && signal.maxLane >= odLane)) {
874 if (c.hasParameter(
"signalID")) {
875 c.setParameter(
"signalID", c.getParameter(
"signalID") +
" " + signal.id);
877 c.setParameter(
"signalID", signal.id);
881 if (importSignalGroups) {
883 if (controller.
id !=
"") {
884 if (c.getParameter(
"controllerID") !=
"") {
885 WRITE_WARNINGF(
TL(
"The signaling of the connection from '%' to '%' (controller '%') is ambiguous because it is overwritten signal '%' and with controller '%'."), from->
getID(), c.toEdge->getID(), c.getParameter(
"controllerID"), signal.id, controller.
id);
889 c.tlLinkIndex = tlIndex;
890 c.setParameter(
"controllerID", controller.
id);
900 WRITE_WARNINGF(
TL(
"Found a traffic light signal on an unknown edge (original edge id='%')."), e->
id);
905 if (signal.orientation == 1) {
910 if (edge ==
nullptr) {
911 WRITE_WARNINGF(
TL(
"Could not find edge '%' for signal '%'."),
id, signal.id);
917 int odLane = laneIndexMap[std::make_pair(edge, c.fromLane)];
918 if (signal.minLane == 0 || (signal.minLane <= odLane && signal.maxLane >= odLane)) {
919 if (c.hasParameter(
"signalID")) {
920 c.setParameter(
"signalID", c.getParameter(
"signalID") +
" " + signal.id);
922 c.setParameter(
"signalID", signal.id);
927 if (importSignalGroups) {
929 if (controller.
id !=
"") {
930 if (c.getParameter(
"controllerID") !=
"") {
931 WRITE_WARNINGF(
TL(
"The signaling of the connection from '%' to '%' (controller '%') is ambiguous because it is overwritten with signal '%' and controller '%'."), edge->
getID(), c.toEdge->getID(), c.getParameter(
"controllerID"), signal.id, controller.
id);
935 c.tlLinkIndex = tlIndex;
936 c.setParameter(
"controllerID", controller.
id);
952 for (std::map<std::string, OpenDriveEdge*>::iterator i = edges.begin(); i != edges.end(); ++i) {
974 POI.setParameter(
"name", o.name);
975 POI.writeXML(dev, writeGeo);
979 centerLine.push_back(
Position(-o.length / 2, 0));
980 centerLine.push_back(
Position(o.length / 2, 0));
982 centerLine.
rotate2D(roadHdg + o.hdg);
1007std::pair<NBEdge*, NBEdge*>
1018 if (from ==
nullptr) {
1021 if (to ==
nullptr) {
1027 }
else if (fromReverse !=
nullptr && toReverse !=
nullptr && fromReverse->
getToNode() == toReverse->
getFromNode() && signalMinLane <= 0) {
1042 return std::make_pair(from, to);
1080 if (sumoLane.
width >= 0 && widthResolution > 0) {
1081 sumoLane.
width = floor(sumoLane.
width / widthResolution + 0.5) * widthResolution;
1083 sumoLane.
width -= widthResolution;
1084 if (sumoLane.
width <= 0) {
1087 }
else if (sumoLane.
width == 0) {
1089 sumoLane.
width = widthResolution;
1095 if (forbiddenNarrow) {
1103 const std::map<std::string, OpenDriveEdge*>& innerEdges,
1104 const std::map<std::string, OpenDriveEdge*>& edges,
1106 std::vector<Connection>& into, std::set<Connection>& seen) {
1109#ifdef DEBUG_CONNECTIONS
1111 std::cout <<
" buildConnectionsToOuter " << c.
getDescription() <<
"\n";
1112 std::cout <<
" dest=" << (dest ==
nullptr ?
"NULL" : dest->
id) <<
" seenlist=";
1113 for (std::set<Connection>::const_iterator i = seen.begin(); i != seen.end(); ++i) {
1114 std::cout <<
" " << (*i).fromEdge <<
"," << (*i).toEdge <<
" ";
1119 if (dest ==
nullptr) {
1125 auto innerEdgesIt = innerEdges.find(destCon.toEdge);
1126#ifdef DEBUG_CONNECTIONS
1128 std::cout <<
" toInner=" << (innerEdgesIt != innerEdges.end()) <<
" destCon " << destCon.getDescription() <<
"\n";
1131 if (innerEdgesIt != innerEdges.end()) {
1132 std::vector<Connection> t;
1133 if (seen.count(destCon) == 0) {
1135 for (std::vector<Connection>::const_iterator j = t.begin(); j != t.end(); ++j) {
1143 cn.shape = innerEdgesIt->second->geom + c.
shape;
1152 int out = destCon.fromLane;
1157#ifdef DEBUG_CONNECTIONS
1159 std::cout <<
" laneSectionsConnected dest=" << dest->
id <<
" in=" << in <<
" out=" << out
1176 int referenceLane = 0;
1177 int offsetFactor = 1;
1181 for (
const auto& destLane : dest->
laneSections.front().lanesByDir[lanesDir]) {
1182 if (destLane.successor == c.
fromLane) {
1183 referenceLane = destLane.id;
1189 for (
const auto& destLane : dest->
laneSections.front().lanesByDir[lanesDir]) {
1190 if (destLane.predecessor == c.
fromLane) {
1191 referenceLane = destLane.id;
1200 std::vector<double> offsets(dest->
geom.size(), 0);
1204#ifdef DEBUG_INTERNALSHAPES
1205 std::string destPred;
1209 for (
int laneSectionIndex = 0; laneSectionIndex < (int)dest->
laneSections.size(); laneSectionIndex++) {
1211 const double nextS = laneSectionIndex + 1 < (int)dest->
laneSections.size() ? dest->
laneSections[laneSectionIndex + 1].s : std::numeric_limits<double>::max();
1214 int finalI = iShape;
1217 double sectionS = 0;
1220#ifdef DEBUG_INTERNALSHAPES
1221 destPred +=
" lane=" +
toString(destLane.id)
1222 +
" pred=" +
toString(destLane.predecessor)
1223 +
" succ=" +
toString(destLane.successor)
1224 +
" wStart=" + (destLane.widthData.empty() ?
"?" :
toString(destLane.widthData.front().computeAt(0)))
1225 +
" wEnd=" + (destLane.widthData.empty() ?
"?" :
toString(destLane.widthData.front().computeAt(
cn.shape.length2D())))
1226 +
" width=" +
toString(destLane.width) +
"\n";
1228 if (abs(destLane.id) <= abs(referenceLane) || abs(destLane.id) == abs(c.
toLane)) {
1229 const double multiplier = offsetFactor * (destLane.id == referenceLane ? 0.5 : 1);
1230#ifdef DEBUG_INTERNALSHAPES
1231 destPred +=
" multiplier=" +
toString(multiplier) +
"\n";
1233 int widthDataIndex = 0;
1234 while (s < nextS && i < (
int)
cn.shape.size()) {
1236 const double dist =
cn.shape[i - 1].distanceTo2D(
cn.shape[i]);
1241 while (widthDataIndex + 1 < (
int)destLane.widthData.size()
1242 && sectionS >= destLane.widthData[widthDataIndex + 1].s) {
1246 if (destLane.widthData.size() > 0) {
1247 width = destLane.widthData[widthDataIndex].computeAt(sectionS);
1249#ifdef DEBUG_INTERNALSHAPES
1250 std::cout <<
" missing width data at inner edge " << dest->
id <<
" to=" <<
cn.toEdge <<
"_" <<
cn.toLane <<
" cp=" <<
cn.toCP <<
"\n";
1257 if (outerToLane.id ==
cn.toLane && outerToLane.width > 0) {
1258#ifdef DEBUG_INTERNALSHAPES
1259 std::cout <<
" using toLane width " << width <<
"\n";
1265 offsets[i] += width * multiplier;
1273 }
else if (finalS == s) {
1275 while (s < nextS && i < (
int)
cn.shape.size()) {
1277 const double dist =
cn.shape[i - 1].distanceTo2D(
cn.shape[i]);
1293 cn.shape.move2sideCustom(offsets);
1298#ifdef DEBUG_INTERNALSHAPES
1299 std::cout <<
"internalShape "
1301 <<
" dest=" << dest->
id
1302 <<
" refLane=" << referenceLane
1303 <<
"\n destPred=" << destPred
1304 <<
"\n offsets=" << offsets
1305 <<
"\n shape=" << dest->
geom
1306 <<
"\n shape2=" <<
cn.shape
1313#ifdef DEBUG_CONNECTIONS
1315 std::cout <<
" added connection\n";
1335 if (lane.id == in) {
1336 in = lane.successor;
1343 if (lane.id == in) {
1344 in = lane.successor;
1357 for (std::vector<OpenDriveLink>::iterator i = e.
links.begin(); i != e.
links.end(); ++i) {
1364 std::string connectedEdge = l.
elementID;
1365 std::string edgeID = e.
id;
1368 const std::map<int, int>& laneMap = laneSection.
laneMap;
1369#ifdef DEBUG_CONNECTIONS
1371 std::cout <<
"edge=" << e.
id <<
" eType=" << l.
elementType <<
" lType=" << l.
linkType <<
" connectedEdge=" << connectedEdge <<
" laneSection=" << laneSection.
s <<
" map:\n";
1377 for (std::vector<OpenDriveLane>::const_iterator j = lanes.begin(); j != lanes.end(); ++j) {
1386 c.
toEdge = connectedEdge;
1395 if (edges.find(c.
fromEdge) == edges.end()) {
1400#ifdef DEBUG_CONNECTIONS
1402 std::cout <<
"insertConRight from=" << src->
id <<
"_" << c.
fromLane <<
" to=" << c.
toEdge <<
"_" << c.
toLane <<
"\n";
1410 for (std::vector<OpenDriveLane>::const_iterator j = lanes.begin(); j != lanes.end(); ++j) {
1428 if (edges.find(c.
fromEdge) == edges.end()) {
1433#ifdef DEBUG_CONNECTIONS
1435 std::cout <<
"insertConLeft from=" << src->
id <<
"_" << c.
fromLane <<
" to=" << c.
toEdge <<
"_" << c.
toLane <<
"\n";
1447 return edgeID[0] ==
'-' ? edgeID.substr(1) :
"-" + edgeID;
1456 if (!nc.
insert(
id, pos)) {
1472 NBNode* toJoin =
nullptr;
1474 if (e.
to !=
nullptr && e.
to != n) {
1479 if (e.
from !=
nullptr && e.
from != n) {
1484 if (toJoin !=
nullptr) {
1488 for (
NodeSet& joined : joinedNodeIDs) {
1489 if (joined.count(toJoin) != 0) {
1492 if (joined.count(n) != 0) {
1496 if (set1 ==
nullptr && set2 ==
nullptr) {
1497 joinedNodeIDs.push_back(
NodeSet());
1498 joinedNodeIDs.back().insert(n);
1499 joinedNodeIDs.back().insert(toJoin);
1500 }
else if (set1 ==
nullptr && set2 !=
nullptr) {
1501 set2->insert(toJoin);
1502 }
else if (set1 !=
nullptr && set2 ==
nullptr) {
1505 set1->insert(set2->begin(), set2->end());
1506 joinedNodeIDs.erase(std::find(joinedNodeIDs.begin(), joinedNodeIDs.end(), *set2));
1517 if (el.c != 0 || el.d != 0) {
1527 const double res = oc.
getFloat(
"opendrive.curve-resolution");
1528 for (
const auto& i : edges) {
1562 WRITE_WARNINGF(
TL(
"Mismatched geometry for edge '%' between geometry segments % and %."), e.
id, index - 1, index);
1567 for (PositionVector::iterator k = geom.begin(); k != geom.end(); ++k) {
1574 if (e.
geom.size() == 1 && e.
geom.front() != last) {
1576 e.
geom.push_back(last);
1580 std::cout << e.
id <<
" initialGeom=" << e.
geom <<
"\n";
1583 if (oc.
exists(
"geometry.min-dist") && !oc.
isDefault(
"geometry.min-dist")) {
1586 if (e.
geom.size() > 4) {
1592 std::cout << e.
id <<
" reducedGeom=" << e.
geom <<
"\n";
1603 for (std::vector<OpenDriveElevation>::iterator j = e.
elevations.begin(); j != e.
elevations.end(); ++j) {
1605 const double sNext = (j + 1) == e.
elevations.end() ? std::numeric_limits<double>::max() : (*(j + 1)).s;
1606 while (k < (
int)e.
geom.size() && pos < sNext) {
1611 if (k < (
int)e.
geom.size()) {
1614 pos += e.
geom[k - 1].distanceTo2D(e.
geom[k]);
1632 std::vector<double> laneOffsets;
1648 for (
auto j = offsets.begin(); j != offsets.end(); ++j) {
1650 const double sNext = (j + 1) == offsets.end() ? std::numeric_limits<double>::max() : (*(j + 1)).s;
1651 while (kk < (
int)geom.size() && ppos < sNext) {
1652 const double offset = el.
computeAt(ppos);
1653 laneOffsets.push_back(fabs(offset) > POSITION_EPS ? -offset : 0);
1655 if (kk < (
int)geom.size()) {
1658 ppos += geom[kk - 1].distanceTo2D(geom[kk]);
1678 double interpolatedOffset = 0;
1680 interpolatedOffset = result.front();
1681 }
else if (at == (
int)geom.size() - 1) {
1682 interpolatedOffset = result.back();
1684 interpolatedOffset = (result[at - 1] + result[at]) / 2;
1686 result.insert(result.begin() + at, interpolatedOffset);
1692 const int sign = left ? -1 : 1;
1693 for (
auto j = offsets.begin(); j != offsets.end(); ++j) {
1695 const double sNext = (j + 1) == offsets.end() ? std::numeric_limits<double>::max() : (*(j + 1)).s;
1696 while (kk < (
int)geom.size() && ppos < sNext) {
1697 const double offset = el.
computeAt(ppos);
1698 result[kk] += fabs(offset) > POSITION_EPS ? sign * offset : 0;
1700 if (kk < (
int)geom.size()) {
1703 ppos += geom[kk - 1].distanceTo2D(geom[kk]);
1712 for (
const auto& i : edges) {
1714#ifdef DEBUG_VARIABLE_SPEED
1717 std::cout <<
"revisitLaneSections e=" << e.
id <<
"\n";
1721 std::vector<OpenDriveLaneSection> newSections;
1723 std::vector<OpenDriveLaneSection> splitSections;
1724 const bool splitByAttrChange = section.buildAttributeChanges(tc, splitSections);
1725 if (!splitByAttrChange) {
1726 newSections.push_back(section);
1728 std::copy(splitSections.begin(), splitSections.end(), back_inserter(newSections));
1737 if (section.s <= lastS) {
1753 if ((j + 1)->s - j->s < POSITION_EPS) {
1754 WRITE_WARNINGF(
TL(
"Almost duplicate s-value '%' for lane sections occurred at edge '%'; first entry was removed."),
toString(j->s), e.
id);
1761#ifdef DEBUG_VARIABLE_SPEED
1774 if (resolution > 0 && g.
length > 0) {
1775 const int numPoints = (int)ceil(g.
length / resolution) + 1;
1776 double dx = (end.
x() - start.
x()) / (numPoints - 1);
1777 double dy = (end.
y() - start.
y()) / (numPoints - 1);
1778 for (
int i = 0; i < numPoints; i++) {
1779 ret.push_back(
Position(g.
x + i * dx, g.
y + i * dy));
1782 ret.push_back(start);
1793 double curveStart = g.
params[0];
1794 double curveEnd = g.
params[1];
1796 double cDot = (curveEnd - curveStart) / g.
length;
1797 if (cDot == 0 || g.
length == 0) {
1802 double sStart = curveStart / cDot;
1803 double sEnd = curveEnd / cDot;
1809 odrSpiral(sStart, cDot, &x, &y, &tStart);
1810 for (s = sStart; s <= sEnd; s += resolution) {
1821 assert(ret.size() >= 2);
1822 assert(ret[0] != ret[1]);
1825 ret.
add(ret.front() * -1);
1831 << std::setprecision(4)
1832 <<
"edge=" << e.
id <<
" s=" << g.
s
1833 <<
" cStart=" << curveStart
1834 <<
" cEnd=" << curveEnd
1836 <<
" sStart=" << sStart
1840 <<
"\n beforeShift=" << ret1
1841 <<
"\n beforeRot=" << ret2
1845 ret.
add(g.
x, g.
y, 0);
1846 }
catch (
const std::runtime_error&
error) {
1858 double centerX = g.
x;
1859 double centerY = g.
y;
1861 double curvature = g.
params[0];
1862 double radius = 1. / curvature;
1867 double startX = g.
x;
1868 double startY = g.
y;
1869 double geo_posS = g.
s;
1870 double geo_posE = g.
s;
1873 geo_posE += resolution;
1874 if (geo_posE - g.
s > g.
length) {
1877 if (geo_posE - g.
s > g.
length) {
1880 calcPointOnCurve(&endX, &endY, centerX, centerY, radius, geo_posE - geo_posS);
1881 ret.push_back(
Position(startX, startY));
1885 geo_posS = geo_posE;
1887 if (geo_posE - (g.
s + g.
length) < 0.001 && geo_posE - (g.
s + g.
length) > -0.001) {
1891 ret.push_back(
Position(startX, startY));
1899 const double s = sin(g.
hdg);
1900 const double c = cos(g.
hdg);
1902 for (
double off = 0; off < g.
length + 2.; off += resolution) {
1905 double xnew = x * c - y * s;
1906 double ynew = x * s + y * c;
1907 ret.push_back(
Position(g.
x + xnew, g.
y + ynew));
1916 const double s = sin(g.
hdg);
1917 const double c = cos(g.
hdg);
1919 const double pStep = pMax / ceil(g.
length / resolution);
1921 for (
double p = 0; p <= pMax + pStep; p += pStep) {
1924 double xnew = x * c - y * s;
1925 double ynew = x * s + y * c;
1926 ret.push_back(
Position(g.
x + xnew, g.
y + ynew));
1934 double normx = 1.0f;
1935 double normy = 0.0f;
1936 double x2 = normx * cos(hdg) - normy * sin(hdg);
1937 double y2 = normx * sin(hdg) + normy * cos(hdg);
1938 normx = x2 * length;
1939 normy = y2 * length;
1940 return Position(start.
x() + normx, start.
y() + normy);
1950 if (ad_radius > 0) {
1957 normX = normX * cos(ad_hdg) + normY * sin(ad_hdg);
1958 normY = tmpX * sin(ad_hdg) + normY * cos(ad_hdg);
1961 normX = turn * normY;
1962 normY = -turn * tmpX;
1964 normX = fabs(ad_radius) * normX;
1965 normY = fabs(ad_radius) * normY;
1974 double ad_r,
double ad_length) {
1975 double rotAngle = ad_length / fabs(ad_r);
1976 double vx = *ad_x - ad_centerX;
1977 double vy = *ad_y - ad_centerY;
1987 vx = vx * cos(rotAngle) + turn * vy * sin(rotAngle);
1988 vy = -1 * turn * tmpx * sin(rotAngle) + vy * cos(rotAngle);
1989 *ad_x = vx + ad_centerX;
1990 *ad_y = vy + ad_centerY;
2006 discardedInnerWidthRight = 0;
2008 bool singleType =
true;
2009 std::vector<std::string> types;
2010 const std::vector<OpenDriveLane>& dirLanesR = lanesByDir.find(
OPENDRIVE_TAG_RIGHT)->second;
2011 for (std::vector<OpenDriveLane>::const_reverse_iterator i = dirLanesR.rbegin(); i != dirLanesR.rend(); ++i) {
2013 discardedInnerWidthRight = 0;
2014 laneMap[(*i).id] = sumoLane++;
2015 types.push_back((*i).type);
2016 if (types.front() != types.back()) {
2020 discardedInnerWidthRight += (*i).width;
2023 discardedInnerWidthLeft = 0;
2024 rightLaneNumber = sumoLane;
2025 rightType = sumoLane > 0 ? (singleType ? types.front() :
joinToString(types,
"|")) :
"";
2029 const std::vector<OpenDriveLane>& dirLanesL = lanesByDir.find(
OPENDRIVE_TAG_LEFT)->second;
2030 for (std::vector<OpenDriveLane>::const_iterator i = dirLanesL.begin(); i != dirLanesL.end(); ++i) {
2032 discardedInnerWidthLeft = 0;
2033 laneMap[(*i).id] = sumoLane++;
2034 types.push_back((*i).type);
2035 if (types.front() != types.back()) {
2039 discardedInnerWidthLeft += (*i).width;
2042 leftLaneNumber = sumoLane;
2043 leftType = sumoLane > 0 ? (singleType ? types.front() :
joinToString(types,
"|")) :
"";
2049 std::map<int, int> ret;
2050 const std::vector<OpenDriveLane>& dirLanes = lanesByDir.find(dir)->second;
2051 for (std::vector<OpenDriveLane>::const_reverse_iterator i = dirLanes.rbegin(); i != dirLanes.rend(); ++i) {
2052 std::map<int, int>::const_iterator toP = laneMap.find((*i).id);
2053 if (toP == laneMap.end()) {
2057 int to = (*toP).second;
2060 from = (*i).predecessor;
2063 std::map<int, int>::const_iterator fromP = prev.
laneMap.find(from);
2064 if (fromP != prev.
laneMap.end()) {
2065 from = (*fromP).second;
2071 if (ret.find(from) != ret.end()) {
2096 l.
speed = (*it).second.speed;
2106 l.
speed = (*it).second.speed;
2116 const std::vector<std::string>& denied)
const {
2118 if (allowed.size() > 0 && denied.size() > 0) {
2119 WRITE_WARNING(
TL(
"Will discard access settings as both denied and allowed classes have been specified."));
2120 }
else if (allowed.size() > 0) {
2122 for (
const std::string& allow : allowed) {
2123 if (allow ==
"simulator") {
2126 }
else if (allow ==
"autonomousTraffic" || allow ==
"autonomous traffic" || allow ==
"throughTraffic") {
2129 }
else if (allow ==
"pedestrian") {
2131 }
else if (allow ==
"passengerCar") {
2133 }
else if (allow ==
"bus") {
2135 }
else if (allow ==
"delivery") {
2137 }
else if (allow ==
"emergency") {
2139 }
else if (allow ==
"taxi") {
2141 }
else if (allow ==
"bicycle") {
2143 }
else if (allow ==
"motorcycle") {
2145 }
else if (allow ==
"truck" || allow ==
"trucks") {
2150 }
else if (denied.size() > 0) {
2151 for (
const std::string& deny : denied) {
2152 if (deny ==
"none") {
2155 }
else if (deny ==
"autonomousTraffic" || deny ==
"autonomous traffic" || deny ==
"throughTraffic") {
2158 }
else if (deny ==
"pedestrian") {
2159 perms &= ~SVC_PEDESTRIAN;
2160 }
else if (deny ==
"passengerCar") {
2161 perms &= ~SVC_PASSENGER;
2162 }
else if (deny ==
"bus") {
2164 }
else if (deny ==
"delivery") {
2165 perms &= ~SVC_DELIVERY;
2166 }
else if (deny ==
"emergency") {
2167 perms &= ~SVC_EMERGENCY;
2168 }
else if (deny ==
"taxi") {
2170 }
else if (deny ==
"bicycle") {
2171 perms &= ~SVC_BICYCLE;
2172 }
else if (deny ==
"motorcycle") {
2173 perms &= ~SVC_MOTORCYCLE;
2174 }
else if (deny ==
"truck" || deny ==
"trucks") {
2175 perms &= ~SVC_TRUCK;
2176 perms &= ~SVC_TRAILER;
2186 std::set<double> attributeChangePositions;
2189 for (std::vector<std::pair<double, LaneAttributeChange> >::const_iterator l = (*k).attributeChanges.begin(); l != (*k).attributeChanges.end(); ++l) {
2190 attributeChangePositions.insert((*l).first);
2191 if ((*l).first == 0) {
2192 (*k).speed = (*l).second.speed;
2193 (*k).permission = (*k).computePermission(tc, (*l).second.allowed, (*l).second.denied);
2198 for (std::vector<std::pair<double, LaneAttributeChange> >::const_iterator l = (*k).attributeChanges.begin(); l != (*k).attributeChanges.end(); ++l) {
2199 attributeChangePositions.insert((*l).first);
2200 if ((*l).first == 0) {
2201 (*k).speed = (*l).second.speed;
2202 (*k).permission = (*k).computePermission(tc, (*l).second.allowed, (*l).second.denied);
2208 if (attributeChangePositions.size() == 0) {
2212 if (*attributeChangePositions.begin() > 0) {
2213 attributeChangePositions.insert(0);
2215#ifdef DEBUG_VARIABLE_SPEED
2217 <<
" buildSpeedChanges sectionStart=" << s
2218 <<
" speedChangePositions=" <<
joinToString(speedChangePositions,
", ")
2221 for (std::set<double>::iterator i = attributeChangePositions.begin(); i != attributeChangePositions.end(); ++i) {
2222 if (i == attributeChangePositions.begin()) {
2223 newSections.push_back(*
this);
2225 newSections.push_back(buildLaneSection(tc, *i));
2229 for (
int i = 0; i != (int)newSections.size(); ++i) {
2230 for (
auto& k : newSections[i].lanesByDir) {
2231 for (
int j = 0; j != (int)k.second.size(); ++j) {
2235 l.
speed = newSections[i - 1].lanesByDir[k.first][j].speed;
2242 l.
permission = newSections[i - 1].lanesByDir[k.first][j].permission;
2243 l.
type = newSections[i - 1].lanesByDir[k.first][j].type;
2263 for (std::vector<OpenDriveSignal>::const_iterator i = signals.begin(); i != signals.end(); ++i) {
2265 if ((*i).type ==
"301" || (*i).type ==
"306") {
2268 if ((*i).type ==
"205" ) {
2289 myTypeContainer(tc),
myCurrentEdge(
"",
"",
"", -1),
myCurrentController(
"",
""),
myEdges(edges),
myOffset(0, 0),
2311 if (majorVersion == 1 && minorVersion > 4) {
2392 std::vector<double> vals;
2398 std::vector<double> vals;
2405 std::vector<double> vals;
2411 std::vector<double> vals;
2420 std::vector<double> vals;
2430 if (pRange ==
"normalized") {
2431 vals.push_back(1.0);
2432 }
else if (pRange ==
"arcLength") {
2433 vals.push_back(-1.0);
2436 vals.push_back(1.0);
2485 int orientationCode = orientation ==
"-" ? -1 : orientation ==
"+" ? 1 : 0;
2496 int orientationCode = orientation ==
"-" ? -1 : orientation ==
"+" ? 1 : 0;
2561 WRITE_ERRORF(
TL(
"In laneLink-element: incoming road '%' is not known."), c.fromEdge);
2577 l.width =
MAX2(l.width, a);
2579#ifdef DEBUG_VARIABLE_WIDTHS
2586 <<
" type=" << l.type
2587 <<
" width=" << l.width
2593 <<
" entries=" << l.widthData.size()
2607 std::vector<std::pair<double, LaneAttributeChange> >::iterator i = std::find_if(attributeChanges.begin(), attributeChanges.end(),
same_position_finder(pos));
2608 if (i != attributeChanges.end()) {
2609 if (rule ==
"allow") {
2610 (*i).second.allowed.push_back(vClass);
2611 }
else if (rule ==
"deny") {
2612 (*i).second.denied.push_back(vClass);
2616 if (rule ==
"allow") {
2617 lac.
allowed.push_back(vClass);
2618 }
else if (rule ==
"deny") {
2619 lac.
denied.push_back(vClass);
2621 attributeChanges.push_back(std::make_pair(pos, lac));
2633 if (!unit.empty()) {
2635 if (unit ==
"km/h") {
2638 if (unit ==
"mph") {
2639 speed *= 1.609344 / 3.6;
2644 std::vector<std::pair<double, LaneAttributeChange> >::iterator i = std::find_if(attributeChanges.begin(), attributeChanges.end(),
same_position_finder(pos));
2645 if (i != attributeChanges.end()) {
2646 (*i).second.speed = speed;
2649 attributeChanges.push_back(std::make_pair(pos, lac));
2678 const std::string baseID = o.
id;
2693 for (
double x = 0; x <= length + NUMERICAL_EPS; x += dist) {
2695 const double a = x / length;
2696 o.
width = wStart * (1 - a) + wEnd * a;
2697 o.
t = tStart * (1 - a) + tEnd * a;
2725 size_t i = cdata.find(
"+proj");
2726 if (i != std::string::npos) {
2727 const std::string proj = cdata.substr(i);
2737 WRITE_ERRORF(
TL(
"Could not set projection (%). This can be ignored with --ignore-errors."), std::string(e.what()));
2741 WRITE_WARNINGF(
TL(
"geoReference format '%' currently not supported"), cdata);
2792 if (intType < 1000001 || (intType > 1000013 && intType != 1000020) || intType == 1000008) {
2799 bool foundDrivingType =
false;
2801 if (ls.s <= s && ls.s + ls.length > s) {
2804 if ((minLane < 0 && l.id >= minLane && l.id <= maxLane) && l.type ==
"driving") {
2805 foundDrivingType =
true;
2810 if ((minLane > 0 && l.id >= minLane && l.id <= maxLane) && l.type ==
"driving") {
2811 foundDrivingType =
true;
2817 if (!foundDrivingType) {
2832 const std::string& elementID,
2833 const std::string& contactPoint) {
2836 if (elementType ==
"road") {
2838 }
else if (elementType ==
"junction") {
2842 if (contactPoint ==
"start") {
2844 }
else if (contactPoint ==
"end") {
2884#ifdef DEBUG_VARIABLE_WIDTHS
2887 std::cout <<
"sanitizeWidths e=" << e->
id <<
" sections=" << e->
laneSections.size() <<
"\n";
2893 if (sec.rightLaneNumber > 0) {
2896 if (sec.leftLaneNumber > 0) {
2905 if (l.widthData.size() > 0) {
2906 auto& wd = l.widthData;
2907 const double threshold = POSITION_EPS;
2908 double maxNoShort = -std::numeric_limits<double>::max();
2910 for (
int i = 0; i < (int)wd.size(); i++) {
2911 const double wdLength = i < (int)wd.size() - 1 ? wd[i + 1].s - wd[i].s : length - seen;
2913 if (wdLength > threshold) {
2914 maxNoShort =
MAX2(maxNoShort, wd[i].a);
2917 if (maxNoShort > 0) {
2918 l.width = maxNoShort;
2919#ifdef DEBUG_VARIABLE_WIDTHS
2921 std::cout <<
" lane=" << l.id <<
" width=" << l.width <<
"\n";
2932 std::vector<OpenDriveLaneSection> newSections;
2933#ifdef DEBUG_VARIABLE_WIDTHS
2936 std::cout <<
"splitMinWidths e=" << e->
id <<
" sections=" << e->
laneSections.size() <<
"\n";
2941 std::vector<double> splitPositions;
2942 const double sectionEnd = (j + 1) == e->
laneSections.end() ? e->
length : (*(j + 1)).s;
2943 const int section = (int)(j - e->
laneSections.begin());
2944#ifdef DEBUG_VARIABLE_WIDTHS
2946 std::cout <<
" findWidthSplit section=" << section <<
" sectionStart=" << sec.
s <<
" sectionOrigStart=" << sec.
sOrig <<
" sectionEnd=" << sectionEnd <<
"\n";
2955 newSections.push_back(sec);
2956 std::sort(splitPositions.begin(), splitPositions.end());
2958 double prevSplit = sec.
s;
2959 for (std::vector<double>::iterator it = splitPositions.begin(); it != splitPositions.end();) {
2960 if ((*it) - prevSplit < minDist || sectionEnd - (*it) < minDist) {
2962#ifdef DEBUG_VARIABLE_WIDTHS
2964 std::cout <<
" skip close split=" << (*it) <<
" prevSplit=" << prevSplit <<
"\n";
2967 it = splitPositions.erase(it);
2968 }
else if ((*it) < sec.
s) {
2970#ifdef DEBUG_VARIABLE_WIDTHS
2972 std::cout <<
" skip early split=" << (*it) <<
" s=" << sec.
s <<
"\n";
2975 it = splitPositions.erase(it);
2982 if (splitPositions.size() > 0) {
2983#ifdef DEBUG_VARIABLE_WIDTHS
2985 std::cout <<
" road=" << e->
id <<
" splitMinWidths section=" << section
2986 <<
" start=" << sec.
s
2987 <<
" origStart=" << sec.
sOrig
2988 <<
" end=" << sectionEnd <<
" minDist=" << minDist
2989 <<
" splitPositions=" <<
toString(splitPositions) <<
"\n";
2992#ifdef DEBUG_VARIABLE_WIDTHS
2994 std::cout <<
"first section...\n";
2998 for (std::vector<double>::iterator it = splitPositions.begin(); it != splitPositions.end(); ++it) {
3001#ifdef DEBUG_VARIABLE_WIDTHS
3003 std::cout <<
"splitAt " << secNew.
s <<
"\n";
3006 newSections.push_back(secNew);
3013 double end = (it + 1) == splitPositions.end() ? sectionEnd : *(it + 1);
3025 int section,
double sectionStart,
double sectionEnd,
3026 std::vector<double>& splitPositions) {
3031 double sPrev = l.widthData.front().s;
3032 double wPrev = l.widthData.front().computeAt(sPrev);
3033#ifdef DEBUG_VARIABLE_WIDTHS
3035 <<
"findWidthSplit section=" << section
3036 <<
" sectionStart=" << sectionStart
3037 <<
" sectionEnd=" << sectionEnd
3039 <<
" type=" << l.type
3040 <<
" widthEntries=" << l.widthData.size() <<
"\n"
3045 for (std::vector<OpenDriveWidth>::const_iterator it_w = l.widthData.begin(); it_w != l.widthData.end(); ++it_w) {
3046 double sEnd = (it_w + 1) != l.widthData.end() ? (*(it_w + 1)).s : sectionEnd - sectionStart;
3047 double w = (*it_w).computeAt(sEnd);
3048#ifdef DEBUG_VARIABLE_WIDTHS
3051 <<
" s=" << (*it_w).s
3052 <<
" a=" << (*it_w).a <<
" b=" << (*it_w).b <<
" c=" << (*it_w).c <<
" d=" << (*it_w).d
3056 const double changeDist = fabs(
myMinWidth - wPrev);
3059 double splitPos = sPrev + (sEnd - sPrev) / fabs(w - wPrev) * changeDist;
3060 double wSplit = (*it_w).computeAt(splitPos);
3061#ifdef DEBUG_VARIABLE_WIDTHS
3063 std::cout <<
" candidate splitPos=" << splitPos <<
" w=" << wSplit <<
"\n";
3070 splitPos -= POSITION_EPS;
3071 if (splitPos < sPrev) {
3072#ifdef DEBUG_VARIABLE_WIDTHS
3074 std::cout <<
" aborting search splitPos=" << splitPos <<
" wSplit=" << wSplit <<
" sPrev=" << sPrev <<
" wPrev=" << wPrev <<
"\n";
3082 splitPos += POSITION_EPS;
3083 if (splitPos > sEnd) {
3084#ifdef DEBUG_VARIABLE_WIDTHS
3086 std::cout <<
" aborting search splitPos=" << splitPos <<
" wSplit=" << wSplit <<
" sEnd=" << sEnd <<
" w=" << w <<
"\n";
3093 wSplit = (*it_w).computeAt(splitPos);
3094#ifdef DEBUG_VARIABLE_WIDTHS
3096 std::cout <<
" refined splitPos=" << splitPos <<
" w=" << wSplit <<
"\n";
3100 splitPositions.push_back(sectionStart + splitPos);
3118 for (std::vector<OpenDriveLane>::iterator k = lanes.begin(); k != lanes.end(); ++k) {
3119 (*k).predecessor = (*k).id;
3137 for (std::vector<OpenDriveLane>::iterator k = lanes.begin(); k != lanes.end(); ++k) {
3140#ifdef DEBUG_VARIABLE_WIDTHS
3142 <<
"recomputeWidths lane=" << l.
id
3143 <<
" type=" << l.
type
3144 <<
" start=" << start
3146 <<
" sectionStart=" << sectionStart
3147 <<
" sectionEnd=" << sectionEnd
3148 <<
" widthEntries=" << l.
widthData.size() <<
"\n"
3153 double sPrevAbs = sPrev + sectionStart;
3154 for (std::vector<OpenDriveWidth>::iterator it_w = l.
widthData.begin(); it_w != l.
widthData.end(); ++it_w) {
3155 double sEnd = (it_w + 1) != l.
widthData.end() ? (*(it_w + 1)).s : sectionEnd - sectionStart;
3156 double sEndAbs = sEnd + sectionStart;
3157#ifdef DEBUG_VARIABLE_WIDTHS
3159 <<
" sPrev=" << sPrev <<
" sPrevAbs=" << sPrevAbs
3160 <<
" sEnd=" << sEnd <<
" sEndAbs=" << sEndAbs
3161 <<
" widthData s=" << (*it_w).s
3162 <<
" a=" << (*it_w).a
3163 <<
" b=" << (*it_w).b
3164 <<
" c=" << (*it_w).c
3165 <<
" d=" << (*it_w).d
3168 if (sPrevAbs <= start && sEndAbs >= start) {
3169#ifdef DEBUG_VARIABLE_WIDTHS
3171 std::cout <<
" atStart=" << start <<
" pos=" << start - sectionStart <<
" w=" << (*it_w).computeAt(start - sectionStart) <<
"\n";
3174 l.
width =
MAX2(l.
width, (*it_w).computeAt(start - sectionStart));
3176 if (sPrevAbs <= end && sEndAbs >= end) {
3177#ifdef DEBUG_VARIABLE_WIDTHS
3179 std::cout <<
" atEnd=" << end <<
" pos=" << end - sectionStart <<
" w=" << (*it_w).computeAt(end - sectionStart) <<
"\n";
3184 if (start <= sPrevAbs && end >= sPrevAbs) {
3185#ifdef DEBUG_VARIABLE_WIDTHS
3187 std::cout <<
" atSPrev=" << sPrev <<
" w=" << (*it_w).computeAt(sPrev) <<
"\n";
3192 if (start <= sEndAbs && end >= sEndAbs) {
3193#ifdef DEBUG_VARIABLE_WIDTHS
3195 std::cout <<
" atSEnd=" << sEnd <<
" w=" << (*it_w).computeAt(sEnd) <<
"\n";
3200#ifdef DEBUG_VARIABLE_WIDTHS
3202 std::cout <<
" sPrev=" << sPrev <<
" sEnd=" << sEnd <<
" l.width=" << l.
width <<
"\n";
#define WRITE_WARNINGF(...)
#define WRITE_ERRORF(...)
#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)
long long int SVCPermissions
bitset where each bit declares whether a certain SVC may use this edge/lane
@ SVC_TRUCK
vehicle is a large transport vehicle
@ SVC_IGNORING
vehicles ignoring classes
@ SVC_PASSENGER
vehicle is a passenger car (a "normal" car)
@ SVC_BICYCLE
vehicle is a bicycle
@ SVC_TRAILER
vehicle is a large transport vehicle
@ SVC_DELIVERY
vehicle is a small delivery vehicle
@ SVC_MOTORCYCLE
vehicle is a motorcycle
@ SVC_EMERGENCY
public emergency vehicles
@ SVC_AUTHORITY
authorities vehicles
@ SVC_TAXI
vehicle is a taxi
@ SVC_BUS
vehicle is a bus
@ SVC_PEDESTRIAN
pedestrian
const std::string SUMO_PARAM_ORIGID
int gPrecision
the precision for floating point outputs
bool gDebugFlag1
global utility flags for debugging
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 isAbsolute(const std::string &path)
Returns the information whether the given path is absolute.
static std::string getConfigurationRelative(const std::string &configPath, const std::string &path)
Returns the second path as a relative path to the first file.
A handler which converts occurring 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.
const std::string & getFileName() const
returns 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 void writeRoadObjects(const OpenDriveEdge *e)
static PositionVector geomFromParamPoly(const OpenDriveEdge &e, const OpenDriveGeometry &g, double resolution)
void myEndElement(int element)
Called when a closing tag occurs.
static SequentialStringBijection::Entry openDriveAttrs[]
The names of openDrive-XML attributes (for passing to GenericSAXHandler)
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_SEMANTICS
@ OPENDRIVE_TAG_ELEVATION
@ OPENDRIVE_TAG_CONTROLLER
@ 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
OpenDriveController myCurrentController
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;.
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)
static OpenDriveController myDummyController
@ OPENDRIVE_ATTR_REVMAJOR
@ OPENDRIVE_ATTR_SIGNALID
@ 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_RESTRICTION
@ 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)
static bool hasNonLinearElevation(const OpenDriveEdge &e)
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
static bool myIgnoreMisplacedSignals
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)
std::string myCurrentJunctionID
static void setEdgeLinks2(OpenDriveEdge &e, const std::map< std::string, OpenDriveEdge * > &edges)
static std::pair< NBEdge *, NBEdge * > retrieveSignalEdges(NBNetBuilder &nb, const std::string &fromID, const std::string &toID, int signalMinLane)
std::string myCurrentIncomingRoad
static void splitMinWidths(OpenDriveEdge *e, const NBTypeCont &tc, double minDist)
bool myConnectionWasEmpty
static bool myImportAllTypes
std::map< std::string, OpenDriveController > myControllers
void myCharacters(int element, const std::string &chars)
Callback method for characters to implement by derived classes.
static std::string reversedEdgeID(const std::string &id)
static NBTrafficLightDefinition * getTLSSecure(NBEdge *inEdge, NBNetBuilder &nb)
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 SequentialStringBijection::Entry openDriveTags[]
The names of openDrive-XML elements (for passing to GenericSAXHandler)
static PositionVector geomFromArc(const OpenDriveEdge &e, const OpenDriveGeometry &g, double resolution)
std::map< std::string, OpenDriveController > & getControllers()
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
std::map< std::string, OpenDriveEdge * > & myEdges
int getTLIndexForController(std::string controllerID)
const OpenDriveController & getController(std::string signalID)
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.
C++ TraCI client API implementation.
virtual void setParameter(const std::string &key, const std::string &value)
Sets a parameter.
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 position 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 amount
bool almostSame(const PositionVector &v2, double maxDiv=POSITION_EPS) const
check if the two vectors have the same length and pairwise similar positions
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
const PositionVector simplified2(const bool closed, const double eps=NUMERICAL_EPS) const
Position positionAtOffset2D(double pos, double lateralOffset=0, bool extrapolateBeyond=false) const
Returns the position at the given length.
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
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
static StringBijection< POIIcon > POIIcons
POI icon values.
const std::string & getString(const T key) const
get string
T get(const std::string &str) const
get key
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, const bool isExternal=false, const bool catchExceptions=true)
Runs the given handler on the given file; returns if everything's ok.
#define UNUSED_PARAMETER(x)
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
Attribute set applied at a certain position along a lane.
std::vector< std::string > allowed
std::vector< std::string > denied
Representation of a signal group.
std::vector< std::string > signalIDs
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< OpenDriveWidth > widthData
std::vector< std::pair< double, LaneAttributeChange > > attributeChanges
List of permission and speed changes.
std::string type
The lane's type.
double speed
The lane's speed (set in post-processing)
SVCPermissions computePermission(const NBTypeCont &tc, const std::vector< std::string > &allowed, const std::vector< std::string > &denied) const
compute the actual SUMO lane permissions given the lane type as a start solution
SVCPermissions permission
The access permissions (set in post-processing)
Representation of a lane section.
OpenDriveLaneSection buildLaneSection(const NBTypeCont &tc, double startPos)
bool buildAttributeChanges(const NBTypeCont &tc, std::vector< OpenDriveLaneSection > &newSections)
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(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.
double s
The starting offset of this lane section.
Representation of an OpenDrive link.
ContactPoint contactPoint
Representation of a signal.
std::string controller
the controller ID
double computeAt(double pos) const