00001
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #ifdef _MSC_VER
00025 #include <windows_config.h>
00026 #else
00027 #include <config.h>
00028 #endif
00029 #include <string>
00030 #include <cmath>
00031 #include <utils/xml/SUMOSAXHandler.h>
00032 #include <utils/common/UtilExceptions.h>
00033 #include <utils/common/TplConvert.h>
00034 #include <utils/common/ToString.h>
00035 #include <utils/common/MsgHandler.h>
00036 #include <netbuild/NBEdge.h>
00037 #include <netbuild/NBEdgeCont.h>
00038 #include <netbuild/NBNode.h>
00039 #include <netbuild/NBNodeCont.h>
00040 #include <netbuild/NBNetBuilder.h>
00041 #include <utils/xml/SUMOXMLDefinitions.h>
00042 #include "NIImporter_OpenDrive.h"
00043 #include <utils/geom/GeoConvHelper.h>
00044 #include <utils/geom/GeomConvHelper.h>
00045 #include <foreign/eulerspiral/euler.h>
00046 #include <utils/options/OptionsCont.h>
00047 #include <utils/common/FileHelpers.h>
00048 #include <utils/xml/XMLSubSys.h>
00049 #include <utils/geom/Boundary.h>
00050
00051 #ifdef CHECK_MEMORY_LEAKS
00052 #include <foreign/nvwa/debug_new.h>
00053 #endif // CHECK_MEMORY_LEAKS
00054
00055
00056
00057
00058
00059 #define C_LENGTH 10.
00060
00061
00062
00063
00064
00065
00066
00067
00068 void
00069 NIImporter_OpenDrive::loadNetwork(const OptionsCont &oc, NBNetBuilder &nb) {
00070
00071 if (!oc.isUsableFileList("opendrive")) {
00072 return;
00073 }
00074
00075 std::vector<OpenDriveEdge> innerEdges, outerEdges;
00076 NIImporter_OpenDrive handler(nb.getNodeCont(), innerEdges, outerEdges);
00077
00078 std::vector<std::string> files = oc.getStringVector("opendrive");
00079 for (std::vector<std::string>::const_iterator file=files.begin(); file!=files.end(); ++file) {
00080 if (!FileHelpers::exists(*file)) {
00081 MsgHandler::getErrorInstance()->inform("Could not open opendrive file '" + *file + "'.");
00082 return;
00083 }
00084 handler.setFileName(*file);
00085 MsgHandler::getMessageInstance()->beginProcessMsg("Parsing opendrive from '" + *file + "'...");
00086 XMLSubSys::runParser(handler, *file);
00087 MsgHandler::getMessageInstance()->endProcessMsg("done.");
00088 }
00089
00090 computeShapes(innerEdges);
00091 computeShapes(outerEdges);
00092
00093
00094
00095
00096
00097
00098
00099 std::map<std::string, Boundary> posMap;
00100 std::map<std::string, std::string> edge2junction;
00101
00102 for (std::vector<OpenDriveEdge>::iterator i=innerEdges.begin(); i!=innerEdges.end(); ++i) {
00103 OpenDriveEdge &e = *i;
00104 assert(e.junction!="-1" && e.junction!="");
00105 edge2junction[e.id] = e.junction;
00106 if (posMap.find(e.junction)==posMap.end()) {
00107 posMap[e.junction] = Boundary();
00108 }
00109 posMap[e.junction].add(e.geom.getBoxBoundary());
00110 }
00111
00112 for (std::map<std::string, Boundary>::iterator i=posMap.begin(); i!=posMap.end(); ++i) {
00113 if (!nb.getNodeCont().insert((*i).first, (*i).second.getCenter())) {
00114 throw ProcessError("Could not add node '" + (*i).first + "'.");
00115 }
00116 }
00117
00118 for (std::vector<OpenDriveEdge>::iterator i=outerEdges.begin(); i!=outerEdges.end(); ++i) {
00119 OpenDriveEdge &e = *i;
00120 for (std::vector<OpenDriveLink>::iterator j=e.links.begin(); j!=e.links.end(); ++j) {
00121 OpenDriveLink &l = *j;
00122 if (l.elementType!=OPENDRIVE_ET_ROAD) {
00123
00124 setNodeSecure(nb.getNodeCont(), e, l.elementID, l.linkType);
00125 continue;
00126 }
00127 if (edge2junction.find(l.elementID)!=edge2junction.end()) {
00128
00129 setNodeSecure(nb.getNodeCont(), e, edge2junction[l.elementID], l.linkType);
00130 continue;
00131 }
00132 }
00133 }
00134
00135
00136
00137
00138
00139 for (std::vector<OpenDriveEdge>::iterator i=outerEdges.begin(); i!=outerEdges.end(); ++i) {
00140 OpenDriveEdge &e = *i;
00141 for (std::vector<OpenDriveLink>::iterator j=e.links.begin(); j!=e.links.end(); ++j) {
00142 OpenDriveLink &l = *j;
00143 if (l.elementType!=OPENDRIVE_ET_ROAD || edge2junction.find(l.elementID)!=edge2junction.end()) {
00144
00145 continue;
00146 }
00147
00148 std::string id1 = e.id;
00149 std::string id2 = l.elementID;
00150 if (id1<id2) {
00151 std::swap(id1, id2);
00152 }
00153 std::string nid = id1+"."+id2;
00154 if (nb.getNodeCont().retrieve(nid)==0) {
00155
00156 Position2D pos = l.linkType==OPENDRIVE_LT_SUCCESSOR ? e.geom[e.geom.size()-1] : e.geom[0];
00157 if (!nb.getNodeCont().insert(nid, pos)) {
00158 throw ProcessError("Could not build node '" + nid + "'.");
00159 }
00160 }
00161
00162
00163
00164
00165
00166
00167 setNodeSecure(nb.getNodeCont(), e, nid, l.linkType);
00168 }
00169 }
00170
00171
00172
00173
00174
00175
00176 for (std::vector<OpenDriveEdge>::iterator i=outerEdges.begin(); i!=outerEdges.end(); ++i) {
00177 OpenDriveEdge &e = *i;
00178 if (e.to!=0&&e.from!=0) {
00179 continue;
00180 }
00181 for (std::vector<OpenDriveEdge>::iterator j=innerEdges.begin(); j!=innerEdges.end(); ++j) {
00182 OpenDriveEdge &ie = *j;
00183 for (std::vector<OpenDriveLink>::iterator k=ie.links.begin(); k!=ie.links.end(); ++k) {
00184 OpenDriveLink &il = *k;
00185 if (il.elementType!=OPENDRIVE_ET_ROAD || il.elementID!=e.id) {
00186
00187 continue;
00188 }
00189 std::string nid = edge2junction[ie.id];
00190 if (il.contactPoint==OPENDRIVE_CP_START) {
00191 setNodeSecure(nb.getNodeCont(), e, nid, OPENDRIVE_LT_PREDECESSOR);
00192 } else {
00193 setNodeSecure(nb.getNodeCont(), e, nid, OPENDRIVE_LT_SUCCESSOR);
00194 }
00195 }
00196 }
00197
00198 }
00199
00200
00201
00202
00203 for (std::vector<OpenDriveEdge>::iterator i=outerEdges.begin(); i!=outerEdges.end(); ++i) {
00204 OpenDriveEdge &e = *i;
00205 if (e.from==0) {
00206 std::string nid = e.id + ".begin";
00207 Position2D pos(e.geometries[0].x, e.geometries[0].y);
00208 e.from = getOrBuildNode(nid, e.geom[0], nb.getNodeCont());
00209 }
00210 if (e.to==0) {
00211 std::string nid = e.id + ".end";
00212 Position2D pos(e.geometries[e.geometries.size()-1].x, e.geometries[e.geometries.size()-1].y);
00213 e.to = getOrBuildNode(nid, e.geom[e.geom.size()-1], nb.getNodeCont());
00214 }
00215 }
00216
00217
00218
00219
00220
00221 std::map<NBEdge*, std::map<int, int> > fromLaneMap;
00222 std::map<NBEdge*, std::map<int, int> > toLaneMap;
00223
00224 for (std::vector<OpenDriveEdge>::iterator i=outerEdges.begin(); i!=outerEdges.end(); ++i) {
00225 OpenDriveEdge &e = *i;
00226 SUMOReal speed = nb.getTypeCont().getDefaultSpeed();
00227 int priority = nb.getTypeCont().getDefaultPriority();
00228 unsigned int nolanes = e.getMaxLaneNumber(SUMO_TAG_OPENDRIVE_RIGHT);
00229 if (nolanes>0) {
00230 NBEdge *nbe = new NBEdge("-" + e.id, e.from, e.to, "", speed, nolanes, priority, e.geom, NBEdge::LANESPREAD_RIGHT, true);
00231 if (!nb.getEdgeCont().insert(nbe)) {
00232 throw ProcessError("Could not add edge '" + std::string("-") + e.id + "'.");
00233 }
00234 fromLaneMap[nbe] = e.laneSections.back().buildLaneMapping(SUMO_TAG_OPENDRIVE_RIGHT);
00235 toLaneMap[nbe] = e.laneSections[0].buildLaneMapping(SUMO_TAG_OPENDRIVE_RIGHT);
00236 }
00237 nolanes = e.getMaxLaneNumber(SUMO_TAG_OPENDRIVE_LEFT);
00238 if (nolanes>0) {
00239 NBEdge *nbe = new NBEdge(e.id, e.to, e.from, "", speed, nolanes, priority, e.geom.reverse(), NBEdge::LANESPREAD_RIGHT, true);
00240 if (!nb.getEdgeCont().insert(nbe)) {
00241 throw ProcessError("Could not add edge '" + e.id + "'.");
00242 }
00243 fromLaneMap[nbe] = e.laneSections[0].buildLaneMapping(SUMO_TAG_OPENDRIVE_LEFT);
00244 toLaneMap[nbe] = e.laneSections.back().buildLaneMapping(SUMO_TAG_OPENDRIVE_LEFT);
00245 }
00246 }
00247
00248
00249
00250
00251
00252 std::vector<Connection> connections;
00253
00254
00255 for (std::vector<OpenDriveEdge>::iterator i=outerEdges.begin(); i!=outerEdges.end(); ++i) {
00256 OpenDriveEdge &e = *i;
00257 for (std::vector<OpenDriveLink>::iterator j=e.links.begin(); j!=e.links.end(); ++j) {
00258 OpenDriveLink &l = *j;
00259 if (l.elementType!=OPENDRIVE_ET_ROAD) {
00260
00261 continue;
00262 }
00263 if (edge2junction.find(l.elementID)!=edge2junction.end()) {
00264
00265 addViaConnectionSecure(nb.getEdgeCont(),
00266 nb.getNodeCont().retrieve(edge2junction[l.elementID]),
00267 e, l.linkType, l.elementID, connections);
00268 } else {
00269
00270 std::vector<OpenDriveEdge>::iterator p = std::find_if(outerEdges.begin(), outerEdges.end(), edge_by_id_finder(l.elementID));
00271 if (p==outerEdges.end()) {
00272 throw ProcessError("Could not find connection edge.");
00273 }
00274 std::string id1 = e.id;
00275 std::string id2 = (*p).id;
00276 if (id1<id2) {
00277 std::swap(id1, id2);
00278 }
00279 std::string nid = id1+"."+id2;
00280 if (l.linkType==OPENDRIVE_LT_PREDECESSOR) {
00281 addE2EConnectionsSecure(nb.getEdgeCont(), nb.getNodeCont().retrieve(nid), *p, e, connections);
00282 } else {
00283 addE2EConnectionsSecure(nb.getEdgeCont(), nb.getNodeCont().retrieve(nid), e, *p, connections);
00284 }
00285 }
00286 }
00287 }
00288
00289
00290
00291
00292
00293
00294
00295
00296
00297
00298
00299
00300
00301
00302
00303
00304
00305
00306
00307
00308
00309
00310
00311
00312
00313
00314
00315
00316
00317
00318
00319
00320
00321
00322
00323
00324
00325
00326
00327
00328
00329
00330
00331
00332
00333
00334
00335
00336
00337
00338
00339
00340
00341
00342
00343
00344
00345
00346
00347
00348
00349
00350
00351
00352
00353
00354
00355
00356
00357
00358
00359
00360
00361
00362
00363
00364
00365
00366
00367
00368
00369
00370 for (std::vector<Connection>::const_iterator i=connections.begin(); i!=connections.end(); ++i) {
00371 if ((*i).from==0 || (*i).to==0) {
00372 std::cout << "Nope." << std::endl;
00373 continue;
00374 }
00375 (*i).from->addEdge2EdgeConnection((*i).to);
00376 std::map<int, int> fromMap = fromLaneMap[(*i).from];
00377 std::map<int, int> toMap = fromLaneMap[(*i).to];
00378 for (std::vector<std::pair<int, int> >::const_iterator j=(*i).lanes.begin(); j!=(*i).lanes.end(); ++j) {
00379 int fromLane = fromMap[(*j).first];
00380 int toLane = toMap[(*j).second];
00381 if (fromLane>=(*i).from->getNoLanes()||fromLane<0) {
00382 std::cout << "False " << std::endl;
00383 }
00384 if (toLane>=(*i).to->getNoLanes()||toLane<0) {
00385 std::cout << "False " << std::endl;
00386 }
00387
00388 (*i).from->addLane2LaneConnection(fromLane, (*i).to, toLane, NBEdge::L2L_VALIDATED, true);
00389 }
00390 }
00391 }
00392
00393
00394 void
00395 NIImporter_OpenDrive::addViaConnectionSecure(const NBEdgeCont &ec,
00396 const NBNode * const node, const OpenDriveEdge &e,
00397 LinkType lt, const std::string &via,
00398 std::vector<NIImporter_OpenDrive::Connection> &connections) {
00399 NBEdge *from = 0;
00400 NBEdge *to = 0;
00401 if (node==e.to) {
00402
00403 if (lt==OPENDRIVE_LT_PREDECESSOR) {
00404
00405 to = ec.retrieve(e.id);
00406 } else {
00407
00408
00409 from = ec.retrieve("-" + e.id);
00410 }
00411 } else {
00412
00413 if (lt==OPENDRIVE_LT_PREDECESSOR) {
00414
00415 to = ec.retrieve("-" + e.id);
00416 } else {
00417
00418
00419 from = ec.retrieve(e.id);
00420 }
00421 }
00422 if (from==0&&to==0) {
00423 throw ProcessError("Missing edge");
00424 }
00425 Connection c(from, via, to);
00426 connections.push_back(c);
00427 }
00428
00429
00430 void
00431 NIImporter_OpenDrive::addE2EConnectionsSecure(const NBEdgeCont &ec, const NBNode * const node,
00432 const NIImporter_OpenDrive::OpenDriveEdge &from, const NIImporter_OpenDrive::OpenDriveEdge &to,
00433 std::vector<NIImporter_OpenDrive::Connection> &connections) {
00434
00435 NBEdge *fromEdge = ec.retrieve("-" + from.id);
00436 if (fromEdge==0||!node->hasIncoming(fromEdge)) {
00437 fromEdge = ec.retrieve(from.id);
00438 }
00439 NBEdge *toEdge = ec.retrieve("-" + to.id);
00440 if (toEdge==0||!node->hasOutgoing(toEdge)) {
00441 toEdge = ec.retrieve(to.id);
00442 }
00443 if (fromEdge!=0&&toEdge!=0) {
00444 Connection c(fromEdge, "", toEdge);
00445 setLaneConnections(c,
00446 from, c.from->getID()[0]!='-', c.from->getID()[0]=='-' ? SUMO_TAG_OPENDRIVE_RIGHT : SUMO_TAG_OPENDRIVE_LEFT,
00447 to, c.to->getID()[0]!='-', c.to->getID()[0]=='-' ? SUMO_TAG_OPENDRIVE_RIGHT : SUMO_TAG_OPENDRIVE_LEFT);
00448 connections.push_back(c);
00449 }
00450
00451 fromEdge = ec.retrieve("-" + from.id);
00452 if (fromEdge==0||!node->hasOutgoing(fromEdge)) {
00453 fromEdge = ec.retrieve(from.id);
00454 }
00455 toEdge = ec.retrieve("-" + to.id);
00456 if (toEdge==0||!node->hasIncoming(toEdge)) {
00457 toEdge = ec.retrieve(to.id);
00458 }
00459 if (fromEdge!=0&&toEdge!=0) {
00460 Connection c(toEdge, "", fromEdge);
00461 setLaneConnections(c,
00462 to, c.to->getID()[0]!='-', c.to->getID()[0]=='-' ? SUMO_TAG_OPENDRIVE_RIGHT : SUMO_TAG_OPENDRIVE_LEFT,
00463 from, c.from->getID()[0]!='-', c.from->getID()[0]=='-' ? SUMO_TAG_OPENDRIVE_RIGHT : SUMO_TAG_OPENDRIVE_LEFT);
00464 connections.push_back(c);
00465 }
00466 }
00467
00468
00469 void
00470 NIImporter_OpenDrive::setLaneConnections(NIImporter_OpenDrive::Connection &c,
00471 const OpenDriveEdge &from, bool fromAtBegin, SumoXMLTag fromLaneDir,
00472 const OpenDriveEdge &to, bool toAtEnd, SumoXMLTag toLaneDir) {
00473 const OpenDriveLaneSection &fromLS = fromAtBegin ? from.laneSections[0] : from.laneSections.back();
00474 const std::vector<OpenDriveLane> &fromLanes = fromLS.lanesByDir.find(fromLaneDir)->second;
00475 const OpenDriveLaneSection &toLS = toAtEnd ? to.laneSections.back() : to.laneSections[0];
00476 const std::vector<OpenDriveLane> &toLanes = toLS.lanesByDir.find(toLaneDir)->second;
00477
00478
00479
00480 for (std::vector<OpenDriveLane>::const_iterator i=fromLanes.begin(); i!=fromLanes.end(); ++i) {
00481 if ((*i).type!="driving") {
00482 continue;
00483 }
00484 if (!fromAtBegin && (*i).successor!=UNSET_CONNECTION) {
00485 c.lanes.push_back(std::make_pair((*i).id, (*i).successor));
00486 }
00487 if (fromAtBegin && (*i).predecessor!=UNSET_CONNECTION) {
00488 c.lanes.push_back(std::make_pair((*i).id, (*i).predecessor));
00489 }
00490 }
00491 for (std::vector<OpenDriveLane>::const_iterator i=toLanes.begin(); i!=toLanes.end(); ++i) {
00492 if ((*i).type!="driving") {
00493 continue;
00494 }
00495 if (!toAtEnd && (*i).predecessor!=UNSET_CONNECTION) {
00496 c.lanes.push_back(std::make_pair((*i).predecessor, (*i).id));
00497 }
00498 if (toAtEnd && (*i).successor!=UNSET_CONNECTION) {
00499 c.lanes.push_back(std::make_pair((*i).successor, (*i).id));
00500 }
00501 }
00502 }
00503
00504
00505 void
00506 NIImporter_OpenDrive::setLaneConnections(NIImporter_OpenDrive::Connection &c,
00507 const OpenDriveEdge &from, bool fromAtBegin, SumoXMLTag fromLaneDir,
00508 const OpenDriveEdge &via, bool viaIsReversed, SumoXMLTag viaLaneDir,
00509 const OpenDriveEdge &to, bool toAtEnd, SumoXMLTag toLaneDir) {
00510 Connection from2via(0, "", 0);
00511 setLaneConnections(from2via, from, fromAtBegin, fromLaneDir, via, viaIsReversed, viaLaneDir);
00512 Connection via2to(0, "", 0);
00513 setLaneConnections(via2to, via, viaIsReversed, viaLaneDir, to, toAtEnd, toLaneDir);
00514 for (std::vector<std::pair<int, int> >::const_iterator i=from2via.lanes.begin(); i!=from2via.lanes.end(); ++i) {
00515 int fromLane = (*i).first;
00516 int viaLane = (*i).second;
00517 for (std::vector<std::pair<int, int> >::const_iterator j=via2to.lanes.begin(); j!=via2to.lanes.end(); ++j) {
00518 if ((*j).first==viaLane) {
00519 c.lanes.push_back(std::make_pair(fromLane, (*j).second));
00520 break;
00521 }
00522 }
00523 }
00524 }
00525
00526
00527 NBNode *
00528 NIImporter_OpenDrive::getOrBuildNode(const std::string &id, Position2D &pos,
00529 NBNodeCont &nc) throw(ProcessError) {
00530 if (nc.retrieve(id)==0) {
00531
00532 if (!nc.insert(id, pos)) {
00533
00534 throw ProcessError("Could not add node '" + id + "'.");
00535 }
00536 }
00537 return nc.retrieve(id);
00538 }
00539
00540
00541 void
00542 NIImporter_OpenDrive::setNodeSecure(NBNodeCont &nc, OpenDriveEdge &e,
00543 const std::string &nodeID, NIImporter_OpenDrive::LinkType lt) throw(ProcessError) {
00544 NBNode *n = nc.retrieve(nodeID);
00545 if (n==0) {
00546 throw ProcessError("Could not find node '" + nodeID + "'.");
00547 }
00548 if (lt==OPENDRIVE_LT_SUCCESSOR) {
00549 if (e.to!=0&&e.to!=n) {
00550 throw ProcessError("Edge '" + e.id + "' has two end nodes.");
00551 }
00552 e.to = n;
00553 } else {
00554 if (e.from!=0&&e.from!=n) {
00555 throw ProcessError("Edge '" + e.id + "' has two start nodes.");
00556 }
00557 e.from = n;
00558 }
00559 }
00560
00561
00562
00563
00564
00565 NBEdge *
00566 NIImporter_OpenDrive::getOutgoingDirectionalEdge(const NBEdgeCont &ec,
00567 const NBNodeCont &nc,
00568 const std::string &edgeID,
00569 const std::string &nodeID) throw() {
00570 NBNode *node = nc.retrieve(nodeID);
00571 NBEdge *e = ec.retrieve(edgeID);
00572 if (e!=0 && node->hasOutgoing(e)) {
00573 return e;
00574 }
00575 e = ec.retrieve("-" + edgeID);
00576 if (e!=0 && node->hasOutgoing(e)) {
00577 return e;
00578 }
00579 return 0;
00580 }
00581
00582
00583 NBEdge *
00584 NIImporter_OpenDrive::getIncomingDirectionalEdge(const NBEdgeCont &ec,
00585 const NBNodeCont &nc,
00586 const std::string &edgeID,
00587 const std::string &nodeID) throw() {
00588 NBNode *node = nc.retrieve(nodeID);
00589 NBEdge *e = ec.retrieve(edgeID);
00590 if (e!=0 && node->hasIncoming(e)) {
00591 return e;
00592 }
00593 e = ec.retrieve("-" + edgeID);
00594 if (e!=0 && node->hasIncoming(e)) {
00595 return e;
00596 }
00597 return 0;
00598 }
00599
00600
00601 void
00602 NIImporter_OpenDrive::computeShapes(std::vector<OpenDriveEdge> &edges) throw() {
00603 for (std::vector<OpenDriveEdge>::iterator i=edges.begin(); i!=edges.end(); ++i) {
00604 OpenDriveEdge &e = *i;
00605 for (std::vector<OpenDriveGeometry>::iterator j=e.geometries.begin(); j!=e.geometries.end(); ++j) {
00606 OpenDriveGeometry &g = *j;
00607 std::vector<Position2D> geom;
00608 switch (g.type) {
00609 case OPENDRIVE_GT_UNKNOWN:
00610 break;
00611 case OPENDRIVE_GT_LINE:
00612 geom = geomFromLine(e, g);
00613 break;
00614 case OPENDRIVE_GT_SPIRAL:
00615 geom = geomFromSpiral(e, g);
00616 break;
00617 case OPENDRIVE_GT_ARC:
00618 geom = geomFromArc(e, g);
00619 break;
00620 case OPENDRIVE_GT_POLY3:
00621 geom = geomFromPoly(e, g);
00622 break;
00623 default:
00624 break;
00625 }
00626 for (std::vector<Position2D>::iterator k=geom.begin(); k!=geom.end(); ++k) {
00627 e.geom.push_back_noDoublePos(*k);
00628 }
00629 }
00630 for (unsigned int j=0; j<e.geom.size(); ++j) {
00631 if (!GeoConvHelper::x2cartesian(e.geom[j])) {
00632 MsgHandler::getErrorInstance()->inform("Unable to project coordinates for.");
00633 }
00634 }
00635 }
00636 }
00637
00638 std::vector<Position2D>
00639 NIImporter_OpenDrive::geomFromLine(const OpenDriveEdge &e, const OpenDriveGeometry &g) throw() {
00640 std::vector<Position2D> ret;
00641 ret.push_back(Position2D(g.x, g.y));
00642 ret.push_back(calculateStraightEndPoint(g.hdg, g.length, Position2D(g.x, g.y)));
00643 return ret;
00644 }
00645
00646
00647 std::vector<Position2D>
00648 NIImporter_OpenDrive::geomFromSpiral(const OpenDriveEdge &e, const OpenDriveGeometry &g) throw() {
00649 std::vector<Position2D> ret;
00650 SUMOReal curveStart = g.params[0];
00651 SUMOReal curveEnd = g.params[1];
00652 Point2D<double> end;
00653 EulerSpiral s(Point2D<double>(g.x, g.y), g.hdg, curveStart, (curveEnd-curveStart)/g.length, g.length);
00654 std::vector<Point2D<double> > into;
00655 s.computeSpiral(into, 1.);
00656 for (std::vector<Point2D<double> >::iterator i=into.begin(); i!=into.end(); ++i) {
00657 ret.push_back(Position2D((*i).getX(), (*i).getY()));
00658 }
00659 return ret;
00660 }
00661
00662
00663 std::vector<Position2D>
00664 NIImporter_OpenDrive::geomFromArc(const OpenDriveEdge &e, const OpenDriveGeometry &g) throw() {
00665 std::vector<Position2D> ret;
00666 SUMOReal dist = 0.0;
00667 SUMOReal centerX = g.x;
00668 SUMOReal centerY = g.y;
00669
00670 SUMOReal curvature = g.params[0];
00671 SUMOReal radius = 1. / curvature;
00672
00673 calculateCurveCenter(¢erX, ¢erY, radius, g.hdg);
00674 SUMOReal endX = g.x;
00675 SUMOReal endY = g.y;
00676 SUMOReal startX = g.x;
00677 SUMOReal startY = g.y;
00678 SUMOReal hdgS = g.hdg;
00679 SUMOReal hdgE;
00680 SUMOReal geo_posS = g.s;
00681 SUMOReal geo_posE = g.s;
00682 int index1 = 0;
00683 bool end = false;
00684 do {
00685 geo_posE += C_LENGTH;
00686
00687 if (geo_posE - g.s > g.length) {
00688 geo_posE = g.s + g.length;
00689 }
00690 if (geo_posE - g.s > g.length) {
00691 geo_posE = g.s + g.length;
00692 }
00693 calcPointOnCurve(&endX, &endY, centerX, centerY, radius, geo_posE - geo_posS);
00694
00695 dist += (geo_posE - geo_posS);
00696 if (curvature > 0.0) {
00697 hdgE = g.hdg + dist/fabs(radius);
00698 } else {
00699 hdgE = g.hdg - dist/fabs(radius);
00700 }
00701
00702 ret.push_back(Position2D(startX, startY));
00703
00704 startX = endX;
00705 startY = endY;
00706 geo_posS = geo_posE;
00707 hdgS = hdgE;
00708
00709 if (geo_posE - (g.s + g.length) < 0.001 && geo_posE - (g.s + g.length) > -0.001) {
00710 end = true;
00711 }
00712 } while (!end);
00713 return ret;
00714 }
00715
00716
00717 std::vector<Position2D>
00718 NIImporter_OpenDrive::geomFromPoly(const OpenDriveEdge &e, const OpenDriveGeometry &g) throw() {
00719 std::vector<Position2D> ret;
00720 return ret;
00721 }
00722
00723
00724 Position2D
00725 NIImporter_OpenDrive::calculateStraightEndPoint(double hdg, double length, const Position2D &start) throw() {
00726 double normx = 1.0f;
00727 double normy = 0.0f;
00728 double x2 = normx * cos(hdg) - normy * sin(hdg);
00729 double y2 = normx * sin(hdg) + normy * cos(hdg);
00730 normx = x2 * length;
00731 normy = y2 * length;
00732 return Position2D(start.x() + normx, start.y() + normy);
00733 }
00734
00735
00736
00737 void
00738 NIImporter_OpenDrive::calculateCurveCenter(SUMOReal *ad_x, SUMOReal *ad_y, SUMOReal ad_radius, SUMOReal ad_hdg) throw() {
00739 SUMOReal normX = 1.0;
00740 SUMOReal normY = 0.0;
00741 SUMOReal tmpX;
00742 SUMOReal turn;
00743 if (ad_radius > 0)
00744 turn = -1.0;
00745 else
00746 turn = 1.0;
00747
00748 tmpX = normX;
00749 normX = normX * cos(ad_hdg) + normY * sin(ad_hdg);
00750 normY = tmpX * sin(ad_hdg) + normY * cos(ad_hdg);
00751
00752
00753 tmpX = normX;
00754 normX = normX * cos(90 * PI / 180) + turn * normY * sin(90 * PI / 180);
00755 normY = -1 * turn * tmpX * sin(90 * PI / 180) + normY * cos(90 * PI / 180);
00756
00757
00758 normX = abs(ad_radius) * normX;
00759 normY = abs(ad_radius) * normY;
00760
00761
00762 *ad_x += normX;
00763 *ad_y += normY;
00764 }
00765
00766
00767 void
00768 NIImporter_OpenDrive::calcPointOnCurve(SUMOReal *ad_x, SUMOReal *ad_y, SUMOReal ad_centerX, SUMOReal ad_centerY,
00769 SUMOReal ad_r, SUMOReal ad_length) throw() {
00770
00771 double rotAngle = ad_length/abs(ad_r);
00772
00773 double vx = *ad_x - ad_centerX;
00774 double vy = *ad_y - ad_centerY;
00775 double tmpx;
00776
00777 double turn;
00778 if (ad_r > 0)
00779 turn = -1;
00780 else
00781 turn = 1;
00782 tmpx = vx;
00783
00784 vx = vx * cos(rotAngle) + turn * vy * sin(rotAngle);
00785 vy = -1 * turn * tmpx * sin(rotAngle) + vy * cos(rotAngle);
00786
00787 *ad_x = vx + ad_centerX;
00788 *ad_y = vy + ad_centerY;
00789 }
00790
00791
00792
00793
00794 NIImporter_OpenDrive::NIImporter_OpenDrive(NBNodeCont &nc,
00795 std::vector<OpenDriveEdge> &innerEdges,
00796 std::vector<OpenDriveEdge> &outerEdges)
00797 : SUMOSAXHandler("opendrive"), myCurrentEdge("", "", -1),
00798 myInnerEdges(innerEdges), myOuterEdges(outerEdges) {}
00799
00800
00801 NIImporter_OpenDrive::~NIImporter_OpenDrive() throw() {
00802 }
00803
00804
00805 void
00806 NIImporter_OpenDrive::myStartElement(SumoXMLTag element,
00807 const SUMOSAXAttributes &attrs) throw(ProcessError) {
00808 bool ok = true;
00809 switch (element) {
00810 case SUMO_TAG_OPENDRIVE_HEADER: {
00811 int majorVersion = attrs.getIntReporting(SUMO_ATTR_OPENDRIVE_REVMAJOR, "opendrive header", 0, ok);
00812 int minorVersion = attrs.getIntReporting(SUMO_ATTR_OPENDRIVE_REVMINOR, "opendrive header", 0, ok);
00813 if (majorVersion!=1||minorVersion!=2) {
00814 MsgHandler::getWarningInstance()->inform("Given openDrive file '" + getFileName() + "' uses version " + toString(majorVersion) + "." + toString(minorVersion) + ";\n Version 1.2 is supported.");
00815 }
00816 }
00817 break;
00818 case SUMO_TAG_OPENDRIVE_ROAD: {
00819 std::string id =
00820 attrs.hasAttribute(SUMO_ATTR_OPENDRIVE_ID)
00821 ? attrs.getStringReporting(SUMO_ATTR_OPENDRIVE_ID, "road", 0, ok)
00822 : attrs.getStringReporting(SUMO_ATTR_ID, "road", 0, ok);
00823 std::cout << "found edge '" << id << "'" << std::endl;
00824 std::string junction = attrs.getStringReporting(SUMO_ATTR_OPENDRIVE_JUNCTION, "road", id.c_str(), ok);
00825 SUMOReal length = attrs.getSUMORealReporting(SUMO_ATTR_OPENDRIVE_LENGTH, "road", id.c_str(), ok);
00826 myCurrentEdge = OpenDriveEdge(id, junction, length);
00827 }
00828 break;
00829 case SUMO_TAG_OPENDRIVE_PREDECESSOR: {
00830 if (myElementStack.size()>=2&&myElementStack[myElementStack.size()-2]==SUMO_TAG_OPENDRIVE_ROAD) {
00831 std::string elementType = attrs.getStringReporting(SUMO_ATTR_OPENDRIVE_ELEMENTTYPE, "predecessor", myCurrentEdge.id.c_str(), ok);
00832 std::string elementID = attrs.getStringReporting(SUMO_ATTR_OPENDRIVE_ELEMENTID, "predecessor", myCurrentEdge.id.c_str(), ok);
00833 std::string contactPoint = attrs.hasAttribute(SUMO_ATTR_OPENDRIVE_CONTACTPOINT)
00834 ? attrs.getStringReporting(SUMO_ATTR_OPENDRIVE_CONTACTPOINT, "predecessor", myCurrentEdge.id.c_str(), ok)
00835 : "end";
00836 addLink(OPENDRIVE_LT_PREDECESSOR, elementType, elementID, contactPoint);
00837 }
00838 if (myElementStack.size()>=2&&myElementStack[myElementStack.size()-2]==SUMO_TAG_OPENDRIVE_LANE||myElementStack[myElementStack.size()-2]==SUMO_TAG_LANE) {
00839 int no = attrs.getIntReporting(SUMO_ATTR_ID, "predecessor", myCurrentEdge.id.c_str(), ok);
00840 OpenDriveLane &l = myCurrentEdge.laneSections[myCurrentEdge.laneSections.size()-1].lanesByDir[myCurrentLaneDirection].back();
00841 l.predecessor = no;
00842 }
00843 }
00844 break;
00845 case SUMO_TAG_OPENDRIVE_SUCCESSOR: {
00846 if (myElementStack.size()>=2&&myElementStack[myElementStack.size()-2]==SUMO_TAG_OPENDRIVE_ROAD) {
00847 std::string elementType = attrs.getStringReporting(SUMO_ATTR_OPENDRIVE_ELEMENTTYPE, "successor", myCurrentEdge.id.c_str(), ok);
00848 std::string elementID = attrs.getStringReporting(SUMO_ATTR_OPENDRIVE_ELEMENTID, "successor", myCurrentEdge.id.c_str(), ok);
00849 std::string contactPoint = attrs.hasAttribute(SUMO_ATTR_OPENDRIVE_CONTACTPOINT)
00850 ? attrs.getStringReporting(SUMO_ATTR_OPENDRIVE_CONTACTPOINT, "successor", myCurrentEdge.id.c_str(), ok)
00851 : "start";
00852 addLink(OPENDRIVE_LT_SUCCESSOR, elementType, elementID, contactPoint);
00853 }
00854 if (myElementStack.size()>=2&&myElementStack[myElementStack.size()-2]==SUMO_TAG_OPENDRIVE_LANE||myElementStack[myElementStack.size()-2]==SUMO_TAG_LANE) {
00855 int no = attrs.getIntReporting(SUMO_ATTR_ID, "predecessor", myCurrentEdge.id.c_str(), ok);
00856 OpenDriveLane &l = myCurrentEdge.laneSections[myCurrentEdge.laneSections.size()-1].lanesByDir[myCurrentLaneDirection].back();
00857 l.successor = no;
00858 }
00859 }
00860 break;
00861 case SUMO_TAG_OPENDRIVE_GEOMETRY: {
00862 SUMOReal length = attrs.getSUMORealReporting(SUMO_ATTR_OPENDRIVE_LENGTH, "geometry", myCurrentEdge.id.c_str(), ok);
00863 SUMOReal s = attrs.getSUMORealReporting(SUMO_ATTR_OPENDRIVE_S, "geometry", myCurrentEdge.id.c_str(), ok);
00864 SUMOReal x = attrs.getSUMORealReporting(SUMO_ATTR_OPENDRIVE_X, "geometry", myCurrentEdge.id.c_str(), ok);
00865 SUMOReal y = attrs.getSUMORealReporting(SUMO_ATTR_OPENDRIVE_Y, "geometry", myCurrentEdge.id.c_str(), ok);
00866 SUMOReal hdg = attrs.getSUMORealReporting(SUMO_ATTR_OPENDRIVE_HDG, "geometry", myCurrentEdge.id.c_str(), ok);
00867 myCurrentEdge.geometries.push_back(OpenDriveGeometry(length, s, x, y, hdg));
00868 }
00869 break;
00870 case SUMO_TAG_OPENDRIVE_LINE: {
00871 std::vector<SUMOReal> vals;
00872 addGeometryShape(OPENDRIVE_GT_LINE, vals);
00873 }
00874 break;
00875 case SUMO_TAG_OPENDRIVE_SPIRAL: {
00876 std::vector<SUMOReal> vals;
00877 vals.push_back(attrs.getSUMORealReporting(SUMO_ATTR_OPENDRIVE_CURVSTART, "spiral", myCurrentEdge.id.c_str(), ok));
00878 vals.push_back(attrs.getSUMORealReporting(SUMO_ATTR_OPENDRIVE_CURVEND, "spiral", myCurrentEdge.id.c_str(), ok));
00879 addGeometryShape(OPENDRIVE_GT_SPIRAL, vals);
00880 }
00881 break;
00882 case SUMO_TAG_OPENDRIVE_ARC: {
00883 std::vector<SUMOReal> vals;
00884 vals.push_back(attrs.getSUMORealReporting(SUMO_ATTR_OPENDRIVE_CURVATURE, "arc", myCurrentEdge.id.c_str(), ok));
00885 addGeometryShape(OPENDRIVE_GT_ARC, vals);
00886 }
00887 break;
00888 case SUMO_TAG_OPENDRIVE_POLY3: {
00889 std::vector<SUMOReal> vals;
00890 vals.push_back(attrs.getSUMORealReporting(SUMO_ATTR_OPENDRIVE_A, "poly3", myCurrentEdge.id.c_str(), ok));
00891 vals.push_back(attrs.getSUMORealReporting(SUMO_ATTR_OPENDRIVE_B, "poly3", myCurrentEdge.id.c_str(), ok));
00892 vals.push_back(attrs.getSUMORealReporting(SUMO_ATTR_OPENDRIVE_C, "poly3", myCurrentEdge.id.c_str(), ok));
00893 vals.push_back(attrs.getSUMORealReporting(SUMO_ATTR_OPENDRIVE_D, "poly3", myCurrentEdge.id.c_str(), ok));
00894 addGeometryShape(OPENDRIVE_GT_POLY3, vals);
00895 }
00896 break;
00897 case SUMO_TAG_OPENDRIVE_LANESECTION: {
00898 SUMOReal s = attrs.getSUMORealReporting(SUMO_ATTR_OPENDRIVE_S, "geometry", myCurrentEdge.id.c_str(), ok);
00899 myCurrentEdge.laneSections.push_back(OpenDriveLaneSection(s));
00900 }
00901 break;
00902 case SUMO_TAG_OPENDRIVE_LEFT:
00903 case SUMO_TAG_OPENDRIVE_CENTER:
00904 case SUMO_TAG_OPENDRIVE_RIGHT:
00905 myCurrentLaneDirection = element;
00906 break;
00907 case SUMO_TAG_LANE:
00908 case SUMO_TAG_OPENDRIVE_LANE: {
00909 std::string type = attrs.getStringReporting(SUMO_ATTR_OPENDRIVE_TYPE, "lane", myCurrentEdge.id.c_str(), ok);
00910 int id = attrs.hasAttribute(SUMO_ATTR_OPENDRIVE_ID)
00911 ? attrs.getIntReporting(SUMO_ATTR_OPENDRIVE_ID, "lane", myCurrentEdge.id.c_str(), ok)
00912 : attrs.getIntReporting(SUMO_ATTR_ID, "lane", myCurrentEdge.id.c_str(), ok);
00913 int level = attrs.hasAttribute(SUMO_ATTR_OPENDRIVE_LEVEL)
00914 ? attrs.getIntReporting(SUMO_ATTR_OPENDRIVE_LEVEL, "lane", myCurrentEdge.id.c_str(), ok)
00915 : 0;
00916 OpenDriveLaneSection &ls = myCurrentEdge.laneSections[myCurrentEdge.laneSections.size()-1];
00917 ls.lanesByDir[myCurrentLaneDirection].push_back(OpenDriveLane(id, level, type));
00918 }
00919 default:
00920 break;
00921 }
00922 myElementStack.push_back(element);
00923 }
00924
00925
00926 void
00927 NIImporter_OpenDrive::myCharacters(SumoXMLTag element,
00928 const std::string &chars) throw(ProcessError) {
00929 }
00930
00931
00932
00933 void
00934 NIImporter_OpenDrive::myEndElement(SumoXMLTag element) throw(ProcessError) {
00935 myElementStack.pop_back();
00936 switch (element) {
00937 case SUMO_TAG_OPENDRIVE_ROAD:
00938 if (myCurrentEdge.junction=="" || myCurrentEdge.junction=="-1") {
00939 myOuterEdges.push_back(myCurrentEdge);
00940 } else {
00941 myInnerEdges.push_back(myCurrentEdge);
00942 }
00943 break;
00944 default:
00945 break;
00946 }
00947 }
00948
00949
00950
00951 void
00952 NIImporter_OpenDrive::addLink(LinkType lt, const std::string &elementType,
00953 const std::string &elementID,
00954 const std::string &contactPoint) throw(ProcessError) {
00955 OpenDriveLink l(lt, elementID);
00956
00957 if (elementType=="road") {
00958 l.elementType = OPENDRIVE_ET_ROAD;
00959 } else if (elementType=="junction") {
00960 l.elementType = OPENDRIVE_ET_JUNCTION;
00961 }
00962
00963 if (contactPoint=="start") {
00964 l.contactPoint = OPENDRIVE_CP_START;
00965 } else if (contactPoint=="end") {
00966 l.contactPoint = OPENDRIVE_CP_END;
00967 }
00968
00969 myCurrentEdge.links.push_back(l);
00970 }
00971
00972
00973 void
00974 NIImporter_OpenDrive::addGeometryShape(GeometryType type, const std::vector<SUMOReal> &vals) throw(ProcessError) {
00975
00976 if (myCurrentEdge.geometries.size()==0) {
00977 throw ProcessError("Mismatching paranthesis in geometry definition for road '" + myCurrentEdge.id + "'");
00978 }
00979 OpenDriveGeometry &last = myCurrentEdge.geometries[myCurrentEdge.geometries.size()-1];
00980 if (last.type!=OPENDRIVE_GT_UNKNOWN) {
00981 throw ProcessError("Double geometry information for road '" + myCurrentEdge.id + "'");
00982 }
00983
00984 last.type = type;
00985 last.params = vals;
00986 }
00987
00988
00989
00990