|
SUMO - Simulation of Urban MObility
|
00001 /****************************************************************************/ 00007 // Importer for networks stored in openDrive format 00008 /****************************************************************************/ 00009 // SUMO, Simulation of Urban MObility; see http://sumo.sourceforge.net/ 00010 // Copyright (C) 2001-2011 DLR (http://www.dlr.de/) and contributors 00011 /****************************************************************************/ 00012 // 00013 // This program is free software; you can redistribute it and/or modify 00014 // it under the terms of the GNU General Public License as published by 00015 // the Free Software Foundation; either version 2 of the License, or 00016 // (at your option) any later version. 00017 // 00018 /****************************************************************************/ 00019 00020 00021 // =========================================================================== 00022 // included modules 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 <utils/geom/GeoConvHelper.h> 00043 #include <utils/geom/GeomConvHelper.h> 00044 #include <foreign/eulerspiral/euler.h> 00045 #include <utils/options/OptionsCont.h> 00046 #include <utils/common/FileHelpers.h> 00047 #include <utils/xml/XMLSubSys.h> 00048 #include <utils/geom/Boundary.h> 00049 #include "NILoader.h" 00050 #include "NIImporter_OpenDrive.h" 00051 00052 #ifdef CHECK_MEMORY_LEAKS 00053 #include <foreign/nvwa/debug_new.h> 00054 #endif // CHECK_MEMORY_LEAKS 00055 00056 00057 // =========================================================================== 00058 // definitions 00059 // =========================================================================== 00060 #define C_LENGTH 10. 00061 00062 00063 // =========================================================================== 00064 // static variables 00065 // =========================================================================== 00066 StringBijection<int>::Entry NIImporter_OpenDrive::openDriveTags[] = { 00067 { "header", NIImporter_OpenDrive::OPENDRIVE_TAG_HEADER }, 00068 { "road", NIImporter_OpenDrive::OPENDRIVE_TAG_ROAD }, 00069 { "predecessor", NIImporter_OpenDrive::OPENDRIVE_TAG_PREDECESSOR }, 00070 { "successor", NIImporter_OpenDrive::OPENDRIVE_TAG_SUCCESSOR }, 00071 { "geometry", NIImporter_OpenDrive::OPENDRIVE_TAG_GEOMETRY }, 00072 { "line", NIImporter_OpenDrive::OPENDRIVE_TAG_LINE }, 00073 { "spiral", NIImporter_OpenDrive::OPENDRIVE_TAG_SPIRAL }, 00074 { "arc", NIImporter_OpenDrive::OPENDRIVE_TAG_ARC }, 00075 { "poly3", NIImporter_OpenDrive::OPENDRIVE_TAG_POLY3 }, 00076 { "laneSection", NIImporter_OpenDrive::OPENDRIVE_TAG_LANESECTION }, 00077 { "left", NIImporter_OpenDrive::OPENDRIVE_TAG_LEFT }, 00078 { "center", NIImporter_OpenDrive::OPENDRIVE_TAG_CENTER }, 00079 { "right", NIImporter_OpenDrive::OPENDRIVE_TAG_RIGHT }, 00080 { "lane", NIImporter_OpenDrive::OPENDRIVE_TAG_LANE }, 00081 00082 { "", NIImporter_OpenDrive::OPENDRIVE_TAG_NOTHING } 00083 }; 00084 00085 00086 StringBijection<int>::Entry NIImporter_OpenDrive::openDriveAttrs[] = { 00087 { "revMajor", NIImporter_OpenDrive::OPENDRIVE_ATTR_REVMAJOR }, 00088 { "revMinor", NIImporter_OpenDrive::OPENDRIVE_ATTR_REVMINOR }, 00089 { "id", NIImporter_OpenDrive::OPENDRIVE_ATTR_ID }, 00090 { "length", NIImporter_OpenDrive::OPENDRIVE_ATTR_LENGTH }, 00091 { "junction", NIImporter_OpenDrive::OPENDRIVE_ATTR_JUNCTION }, 00092 { "elementType", NIImporter_OpenDrive::OPENDRIVE_ATTR_ELEMENTTYPE }, 00093 { "elementId", NIImporter_OpenDrive::OPENDRIVE_ATTR_ELEMENTID }, 00094 { "contactPoint", NIImporter_OpenDrive::OPENDRIVE_ATTR_CONTACTPOINT }, 00095 { "s", NIImporter_OpenDrive::OPENDRIVE_ATTR_S }, 00096 { "x", NIImporter_OpenDrive::OPENDRIVE_ATTR_X }, 00097 { "y", NIImporter_OpenDrive::OPENDRIVE_ATTR_Y }, 00098 { "hdg", NIImporter_OpenDrive::OPENDRIVE_ATTR_HDG }, 00099 { "curvStart", NIImporter_OpenDrive::OPENDRIVE_ATTR_CURVSTART }, 00100 { "curvEnd", NIImporter_OpenDrive::OPENDRIVE_ATTR_CURVEND }, 00101 { "curvature", NIImporter_OpenDrive::OPENDRIVE_ATTR_CURVATURE }, 00102 { "a", NIImporter_OpenDrive::OPENDRIVE_ATTR_A }, 00103 { "b", NIImporter_OpenDrive::OPENDRIVE_ATTR_B }, 00104 { "c", NIImporter_OpenDrive::OPENDRIVE_ATTR_C }, 00105 { "d", NIImporter_OpenDrive::OPENDRIVE_ATTR_D }, 00106 { "type", NIImporter_OpenDrive::OPENDRIVE_ATTR_TYPE }, 00107 { "level", NIImporter_OpenDrive::OPENDRIVE_ATTR_LEVEL }, 00108 00109 { "", NIImporter_OpenDrive::OPENDRIVE_ATTR_NOTHING } 00110 }; 00111 00112 00113 // =========================================================================== 00114 // method definitions 00115 // =========================================================================== 00116 // --------------------------------------------------------------------------- 00117 // static methods (interface in this case) 00118 // --------------------------------------------------------------------------- 00119 void 00120 NIImporter_OpenDrive::loadNetwork(const OptionsCont& oc, NBNetBuilder& nb) { 00121 // check whether the option is set (properly) 00122 if (!oc.isUsableFileList("opendrive-files")) { 00123 return; 00124 } 00125 // build the handler 00126 std::vector<OpenDriveEdge> innerEdges, outerEdges; 00127 NIImporter_OpenDrive handler(innerEdges, outerEdges); 00128 // parse file(s) 00129 std::vector<std::string> files = oc.getStringVector("opendrive-files"); 00130 for (std::vector<std::string>::const_iterator file=files.begin(); file!=files.end(); ++file) { 00131 if (!FileHelpers::exists(*file)) { 00132 WRITE_ERROR("Could not open opendrive file '" + *file + "'."); 00133 return; 00134 } 00135 handler.setFileName(*file); 00136 PROGRESS_BEGIN_MESSAGE("Parsing opendrive from '" + *file + "'"); 00137 XMLSubSys::runParser(handler, *file); 00138 PROGRESS_DONE_MESSAGE(); 00139 } 00140 // convert geometries into a discretised representation 00141 computeShapes(innerEdges); 00142 computeShapes(outerEdges); 00143 00144 // ------------------------- 00145 // node building 00146 // ------------------------- 00147 // build nodes#1 00148 // look at all links which belong to a node, collect their bounding boxes 00149 // and place the node in the middle of this bounding box 00150 std::map<std::string, Boundary> posMap; 00151 std::map<std::string, std::string> edge2junction; 00152 // compute node positions 00153 for (std::vector<OpenDriveEdge>::iterator i=innerEdges.begin(); i!=innerEdges.end(); ++i) { 00154 OpenDriveEdge& e = *i; 00155 assert(e.junction!="-1" && e.junction!=""); 00156 edge2junction[e.id] = e.junction; 00157 if (posMap.find(e.junction)==posMap.end()) { 00158 posMap[e.junction] = Boundary(); 00159 } 00160 posMap[e.junction].add(e.geom.getBoxBoundary()); 00161 } 00162 // build nodes 00163 for (std::map<std::string, Boundary>::iterator i=posMap.begin(); i!=posMap.end(); ++i) { 00164 if (!nb.getNodeCont().insert((*i).first, (*i).second.getCenter())) { 00165 throw ProcessError("Could not add node '" + (*i).first + "'."); 00166 } 00167 } 00168 // assign built nodes 00169 for (std::vector<OpenDriveEdge>::iterator i=outerEdges.begin(); i!=outerEdges.end(); ++i) { 00170 OpenDriveEdge& e = *i; 00171 for (std::vector<OpenDriveLink>::iterator j=e.links.begin(); j!=e.links.end(); ++j) { 00172 OpenDriveLink& l = *j; 00173 if (l.elementType!=OPENDRIVE_ET_ROAD) { 00174 // set node information 00175 setNodeSecure(nb.getNodeCont(), e, l.elementID, l.linkType); 00176 continue; 00177 } 00178 if (edge2junction.find(l.elementID)!=edge2junction.end()) { 00179 // set node information of an internal road 00180 setNodeSecure(nb.getNodeCont(), e, edge2junction[l.elementID], l.linkType); 00181 continue; 00182 } 00183 } 00184 } 00185 // we should now have all nodes set for links which are not outer edge-to-outer edge links 00186 00187 00188 // build nodes#2 00189 // build nodes for all outer edge-to-outer edge connections 00190 for (std::vector<OpenDriveEdge>::iterator i=outerEdges.begin(); i!=outerEdges.end(); ++i) { 00191 OpenDriveEdge& e = *i; 00192 for (std::vector<OpenDriveLink>::iterator j=e.links.begin(); j!=e.links.end(); ++j) { 00193 OpenDriveLink& l = *j; 00194 if (l.elementType!=OPENDRIVE_ET_ROAD || edge2junction.find(l.elementID)!=edge2junction.end()) { 00195 // is a connection to an internal edge, or a node, skip 00196 continue; 00197 } 00198 // we have a direct connection between to external edges 00199 std::string id1 = e.id; 00200 std::string id2 = l.elementID; 00201 if (id1<id2) { 00202 std::swap(id1, id2); 00203 } 00204 std::string nid = id1+"."+id2; 00205 if (nb.getNodeCont().retrieve(nid)==0) { 00206 // not yet seen, build 00207 Position pos = l.linkType==OPENDRIVE_LT_SUCCESSOR ? e.geom[(int)e.geom.size()-1] : e.geom[0]; 00208 if (!nb.getNodeCont().insert(nid, pos)) { 00209 throw ProcessError("Could not build node '" + nid + "'."); 00210 } 00211 } 00212 /* debug-stuff 00213 else { 00214 Position pos = l.linkType==OPENDRIVE_LT_SUCCESSOR ? e.geom[e.geom.size()-1] : e.geom[0]; 00215 cout << nid << " " << pos << " " << nb.getNodeCont().retrieve(nid)->getPosition() << endl; 00216 } 00217 */ 00218 setNodeSecure(nb.getNodeCont(), e, nid, l.linkType); 00219 } 00220 } 00221 // we should now have start/end nodes for all outer edge-to-outer edge connections 00222 00223 00224 // build nodes#3 00225 // assign further nodes generated from inner-edges 00226 // these nodes have not been assigned earlier, because the connectiosn are referenced in inner-edges 00227 for (std::vector<OpenDriveEdge>::iterator i=outerEdges.begin(); i!=outerEdges.end(); ++i) { 00228 OpenDriveEdge& e = *i; 00229 if (e.to!=0&&e.from!=0) { 00230 continue; 00231 } 00232 for (std::vector<OpenDriveEdge>::iterator j=innerEdges.begin(); j!=innerEdges.end(); ++j) { 00233 OpenDriveEdge& ie = *j; 00234 for (std::vector<OpenDriveLink>::iterator k=ie.links.begin(); k!=ie.links.end(); ++k) { 00235 OpenDriveLink& il = *k; 00236 if (il.elementType!=OPENDRIVE_ET_ROAD || il.elementID!=e.id) { 00237 // not conneted to the currently investigated outer edge 00238 continue; 00239 } 00240 std::string nid = edge2junction[ie.id]; 00241 if (il.contactPoint==OPENDRIVE_CP_START) { 00242 setNodeSecure(nb.getNodeCont(), e, nid, OPENDRIVE_LT_PREDECESSOR); 00243 } else { 00244 setNodeSecure(nb.getNodeCont(), e, nid, OPENDRIVE_LT_SUCCESSOR); 00245 } 00246 } 00247 } 00248 00249 } 00250 // 00251 00252 00253 // build start/end nodes which were not defined previously 00254 for (std::vector<OpenDriveEdge>::iterator i=outerEdges.begin(); i!=outerEdges.end(); ++i) { 00255 OpenDriveEdge& e = *i; 00256 if (e.from==0) { 00257 std::string nid = e.id + ".begin"; 00258 Position pos(e.geometries[0].x, e.geometries[0].y); 00259 e.from = getOrBuildNode(nid, e.geom[0], nb.getNodeCont()); 00260 } 00261 if (e.to==0) { 00262 std::string nid = e.id + ".end"; 00263 Position pos(e.geometries[e.geometries.size()-1].x, e.geometries[e.geometries.size()-1].y); 00264 e.to = getOrBuildNode(nid, e.geom[(int)e.geom.size()-1], nb.getNodeCont()); 00265 } 00266 } 00267 00268 00269 // ------------------------- 00270 // edge building 00271 // ------------------------- 00272 std::map<NBEdge*, std::map<int, int> > fromLaneMap; 00273 std::map<NBEdge*, std::map<int, int> > toLaneMap; 00274 // build edges 00275 for (std::vector<OpenDriveEdge>::iterator i=outerEdges.begin(); i!=outerEdges.end(); ++i) { 00276 OpenDriveEdge& e = *i; 00277 SUMOReal speed = nb.getTypeCont().getSpeed(""); 00278 int priority = nb.getTypeCont().getPriority(""); 00279 LaneSpreadFunction lsf = LANESPREAD_CENTER; 00280 unsigned int noLanesRight = e.getMaxLaneNumber(OPENDRIVE_TAG_RIGHT); 00281 unsigned int noLanesLeft = e.getMaxLaneNumber(OPENDRIVE_TAG_LEFT); 00282 if (noLanesRight!=0&&noLanesLeft!=0) { 00283 lsf = LANESPREAD_RIGHT; 00284 } 00285 if (noLanesRight>0) { 00286 NBEdge* nbe = new NBEdge("-" + e.id, e.from, e.to, "", speed, noLanesRight, priority, -1, -1, e.geom, "", lsf, true); 00287 if (!nb.getEdgeCont().insert(nbe)) { 00288 throw ProcessError("Could not add edge '" + std::string("-") + e.id + "'."); 00289 } 00290 fromLaneMap[nbe] = e.laneSections.back().buildLaneMapping(OPENDRIVE_TAG_RIGHT); 00291 toLaneMap[nbe] = e.laneSections[0].buildLaneMapping(OPENDRIVE_TAG_RIGHT); 00292 } 00293 if (noLanesLeft>0) { 00294 NBEdge* nbe = new NBEdge(e.id, e.to, e.from, "", speed, noLanesLeft, priority, -1, -1, e.geom.reverse(), "", lsf, true); 00295 if (!nb.getEdgeCont().insert(nbe)) { 00296 throw ProcessError("Could not add edge '" + e.id + "'."); 00297 } 00298 fromLaneMap[nbe] = e.laneSections[0].buildLaneMapping(OPENDRIVE_TAG_LEFT); 00299 toLaneMap[nbe] = e.laneSections.back().buildLaneMapping(OPENDRIVE_TAG_LEFT); 00300 } 00301 } 00302 00303 00304 // ------------------------- 00305 // connections building 00306 // ------------------------- 00307 std::vector<Connection> connections; 00308 // connections#1 00309 // build connections between outer-edges 00310 for (std::vector<OpenDriveEdge>::iterator i=outerEdges.begin(); i!=outerEdges.end(); ++i) { 00311 OpenDriveEdge& e = *i; 00312 for (std::vector<OpenDriveLink>::iterator j=e.links.begin(); j!=e.links.end(); ++j) { 00313 OpenDriveLink& l = *j; 00314 if (l.elementType!=OPENDRIVE_ET_ROAD) { 00315 // we are not interested in connections to nodes 00316 continue; 00317 } 00318 if (edge2junction.find(l.elementID)!=edge2junction.end()) { 00319 // connection via an inner-road 00320 addViaConnectionSecure(nb.getEdgeCont(), 00321 nb.getNodeCont().retrieve(edge2junction[l.elementID]), 00322 e, l.linkType, l.elementID, connections); 00323 } else { 00324 // connection between two outer-edges; can be used directly 00325 std::vector<OpenDriveEdge>::iterator p = std::find_if(outerEdges.begin(), outerEdges.end(), edge_by_id_finder(l.elementID)); 00326 if (p==outerEdges.end()) { 00327 throw ProcessError("Could not find connection edge."); 00328 } 00329 std::string id1 = e.id; 00330 std::string id2 = (*p).id; 00331 if (id1<id2) { 00332 std::swap(id1, id2); 00333 } 00334 std::string nid = id1+"."+id2; 00335 if (l.linkType==OPENDRIVE_LT_PREDECESSOR) { 00336 addE2EConnectionsSecure(nb.getEdgeCont(), nb.getNodeCont().retrieve(nid), *p, e, connections); 00337 } else { 00338 addE2EConnectionsSecure(nb.getEdgeCont(), nb.getNodeCont().retrieve(nid), e, *p, connections); 00339 } 00340 } 00341 } 00342 } 00343 00344 // build inner-edge connections 00345 for (std::vector<OpenDriveEdge>::iterator i=innerEdges.begin(); i!=innerEdges.end(); ++i) { 00346 OpenDriveEdge& e = *i; 00347 std::string pred, succ; 00348 ContactPoint predC, succC; 00349 for (std::vector<OpenDriveLink>::iterator j=e.links.begin(); j!=e.links.end(); ++j) { 00350 OpenDriveLink& l = *j; 00351 if (l.elementType!=OPENDRIVE_ET_ROAD) { 00352 // we are not interested in connections to nodes 00353 std::cout << "unsupported" << std::endl; 00354 continue; 00355 } 00356 if (edge2junction.find(l.elementID)!=edge2junction.end()) { 00357 // not supported 00358 std::cout << "unsupported" << std::endl; 00359 continue; 00360 } 00361 if (l.linkType==OPENDRIVE_LT_SUCCESSOR) { 00362 if (succ!="") { 00363 std::cout << "double succ" << std::endl; 00364 } 00365 succ = l.elementID; 00366 succC = l.contactPoint; 00367 } else { 00368 if (pred!="") { 00369 std::cout << "double pred" << std::endl; 00370 } 00371 pred = l.elementID; 00372 predC = l.contactPoint; 00373 } 00374 } 00375 00376 if (e.getMaxLaneNumber(OPENDRIVE_TAG_LEFT)!=0&&e.getMaxLaneNumber(OPENDRIVE_TAG_RIGHT)!=0) { 00377 std::cout << "Both dirs given!" << std::endl; 00378 } 00379 00380 bool isReversed = false; 00381 if (e.getMaxLaneNumber(OPENDRIVE_TAG_LEFT)!=0) { 00382 // std::swap(pred, succ); 00383 //std::swap(predC, succC); 00384 isReversed = true; 00385 } 00386 00387 if (succ==""||pred=="") { 00388 std::cout << "Missing edge." << std::endl; 00389 continue; // yes, occurs 00390 } 00391 // !!!why edge2junction; e already has the junction... 00392 NBNode* n = nb.getNodeCont().retrieve(edge2junction[e.id]); 00393 std::vector<OpenDriveEdge>::iterator predEdge = std::find_if(outerEdges.begin(), outerEdges.end(), edge_by_id_finder(pred)); 00394 if (predEdge==outerEdges.end()) { 00395 throw ProcessError("Could not find connection edge."); 00396 } 00397 std::vector<OpenDriveEdge>::iterator succEdge = std::find_if(outerEdges.begin(), outerEdges.end(), edge_by_id_finder(succ)); 00398 if (succEdge==outerEdges.end()) { 00399 throw ProcessError("Could not find connection edge."); 00400 } 00401 NBEdge* fromEdge, *toEdge; 00402 if (!isReversed) { 00403 fromEdge = predC==OPENDRIVE_CP_END ? nb.getEdgeCont().retrieve("-" + pred) : nb.getEdgeCont().retrieve(pred); 00404 toEdge = succC==OPENDRIVE_CP_START ? nb.getEdgeCont().retrieve("-" + succ) : nb.getEdgeCont().retrieve(succ); 00405 } else { 00406 fromEdge = predC!=OPENDRIVE_CP_END ? nb.getEdgeCont().retrieve("-" + pred) : nb.getEdgeCont().retrieve(pred); 00407 toEdge = succC!=OPENDRIVE_CP_START ? nb.getEdgeCont().retrieve("-" + succ) : nb.getEdgeCont().retrieve(succ); 00408 } 00409 /* 00410 Connection c( 00411 n->hasIncoming(nb.getEdgeCont().retrieve("-" + pred)) ? nb.getEdgeCont().retrieve("-" + pred) : nb.getEdgeCont().retrieve(pred), 00412 e.id, 00413 n->hasOutgoing(nb.getEdgeCont().retrieve("-" + succ)) ? nb.getEdgeCont().retrieve("-" + succ) : nb.getEdgeCont().retrieve(succ)); 00414 */ 00415 Connection c(fromEdge, e.id, toEdge); 00416 if (c.from==0||c.to==0||c.from==c.to) { 00417 throw ProcessError("Something's false"); 00418 } 00419 setLaneConnections(c, 00420 *predEdge, c.from->getID()[0]!='-', c.from->getID()[0]=='-' ? OPENDRIVE_TAG_RIGHT : OPENDRIVE_TAG_LEFT, 00421 e, isReversed, !isReversed ? OPENDRIVE_TAG_RIGHT : OPENDRIVE_TAG_LEFT, 00422 *succEdge, c.to->getID()[0]!='-', c.to->getID()[0]=='-' ? OPENDRIVE_TAG_RIGHT : OPENDRIVE_TAG_LEFT); 00423 connections.push_back(c); 00424 } 00425 for (std::vector<Connection>::const_iterator i=connections.begin(); i!=connections.end(); ++i) { 00426 if ((*i).from==0 || (*i).to==0) { 00427 std::cout << "Nope." << std::endl; 00428 continue; 00429 } 00430 (*i).from->addEdge2EdgeConnection((*i).to); 00431 std::map<int, int> fromMap = fromLaneMap[(*i).from]; 00432 std::map<int, int> toMap = fromLaneMap[(*i).to]; 00433 for (std::vector<std::pair<int, int> >::const_iterator j=(*i).lanes.begin(); j!=(*i).lanes.end(); ++j) { 00434 int fromLane = fromMap[(*j).first]; 00435 int toLane = toMap[(*j).second]; 00436 if (static_cast<unsigned int>(fromLane)>=(*i).from->getNumLanes()||fromLane<0) { 00437 std::cout << "False " << std::endl; 00438 } 00439 if (static_cast<unsigned int>(toLane)>=(*i).to->getNumLanes()||toLane<0) { 00440 std::cout << "False " << std::endl; 00441 } 00442 00443 (*i).from->addLane2LaneConnection(fromLane, (*i).to, toLane, NBEdge::L2L_VALIDATED, true); 00444 } 00445 } 00446 } 00447 00448 00449 void 00450 NIImporter_OpenDrive::addViaConnectionSecure(const NBEdgeCont& ec, 00451 const NBNode* const node, const OpenDriveEdge& e, 00452 LinkType lt, const std::string& via, 00453 std::vector<NIImporter_OpenDrive::Connection> &connections) { 00454 NBEdge* from = 0; 00455 NBEdge* to = 0; 00456 if (node==e.to) { 00457 // the connection is at the end of the "positive" direction 00458 if (lt==OPENDRIVE_LT_PREDECESSOR) { 00459 // via -> edge 00460 to = ec.retrieve(e.id); 00461 } else { 00462 // -edge -> via 00463 // "ambigous?" 00464 from = ec.retrieve("-" + e.id); 00465 } 00466 } else { 00467 // the connection is at the begin of the "positive" direction 00468 if (lt==OPENDRIVE_LT_PREDECESSOR) { 00469 // via -> -edge 00470 to = ec.retrieve("-" + e.id); 00471 } else { 00472 // edge -> via 00473 // "ambigous?" 00474 from = ec.retrieve(e.id); 00475 } 00476 } 00477 if (from==0&&to==0) { 00478 throw ProcessError("Missing edge"); 00479 } 00480 Connection c(from, via, to); 00481 connections.push_back(c); 00482 } 00483 00484 00485 void 00486 NIImporter_OpenDrive::addE2EConnectionsSecure(const NBEdgeCont& ec, const NBNode* const node, 00487 const NIImporter_OpenDrive::OpenDriveEdge& from, const NIImporter_OpenDrive::OpenDriveEdge& to, 00488 std::vector<NIImporter_OpenDrive::Connection> &connections) { 00489 // positive direction (from is incoming, to is outgoing) 00490 NBEdge* fromEdge = ec.retrieve("-" + from.id); 00491 if (fromEdge==0||!node->hasIncoming(fromEdge)) { 00492 fromEdge = ec.retrieve(from.id); 00493 } 00494 NBEdge* toEdge = ec.retrieve("-" + to.id); 00495 if (toEdge==0||!node->hasOutgoing(toEdge)) { 00496 toEdge = ec.retrieve(to.id); 00497 } 00498 if (fromEdge!=0&&toEdge!=0) { 00499 Connection c(fromEdge, "", toEdge); 00500 setLaneConnections(c, 00501 from, c.from->getID()[0]!='-', c.from->getID()[0]=='-' ? OPENDRIVE_TAG_RIGHT : OPENDRIVE_TAG_LEFT, 00502 to, c.to->getID()[0]!='-', c.to->getID()[0]=='-' ? OPENDRIVE_TAG_RIGHT : OPENDRIVE_TAG_LEFT); 00503 connections.push_back(c); 00504 } 00505 // negative direction (to is incoming, from is outgoing) 00506 fromEdge = ec.retrieve("-" + from.id); 00507 if (fromEdge==0||!node->hasOutgoing(fromEdge)) { 00508 fromEdge = ec.retrieve(from.id); 00509 } 00510 toEdge = ec.retrieve("-" + to.id); 00511 if (toEdge==0||!node->hasIncoming(toEdge)) { 00512 toEdge = ec.retrieve(to.id); 00513 } 00514 if (fromEdge!=0&&toEdge!=0) { 00515 Connection c(toEdge, "", fromEdge); 00516 setLaneConnections(c, 00517 to, c.to->getID()[0]!='-', c.to->getID()[0]=='-' ? OPENDRIVE_TAG_RIGHT : OPENDRIVE_TAG_LEFT, 00518 from, c.from->getID()[0]!='-', c.from->getID()[0]=='-' ? OPENDRIVE_TAG_RIGHT : OPENDRIVE_TAG_LEFT); 00519 connections.push_back(c); 00520 } 00521 } 00522 00523 00524 void 00525 NIImporter_OpenDrive::setLaneConnections(NIImporter_OpenDrive::Connection& c, 00526 const OpenDriveEdge& from, bool fromAtBegin, OpenDriveXMLTag fromLaneDir, 00527 const OpenDriveEdge& to, bool toAtEnd, OpenDriveXMLTag toLaneDir) { 00528 const OpenDriveLaneSection& fromLS = fromAtBegin ? from.laneSections[0] : from.laneSections.back(); 00529 const std::vector<OpenDriveLane> &fromLanes = fromLS.lanesByDir.find(fromLaneDir)->second; 00530 const OpenDriveLaneSection& toLS = toAtEnd ? to.laneSections.back() : to.laneSections[0]; 00531 const std::vector<OpenDriveLane> &toLanes = toLS.lanesByDir.find(toLaneDir)->second; 00532 // in the following, we are probably using the same information twice, stored once 00533 // in the from-edge's successor field and in the to-edge's precessor field. 00534 // though, we have no proof or information that this is always redundant 00535 for (std::vector<OpenDriveLane>::const_iterator i=fromLanes.begin(); i!=fromLanes.end(); ++i) { 00536 if ((*i).type!="driving") { 00537 continue; 00538 } 00539 if (!fromAtBegin && (*i).successor!=UNSET_CONNECTION) { 00540 c.lanes.push_back(std::make_pair((*i).id, (*i).successor)); 00541 } 00542 if (fromAtBegin && (*i).predecessor!=UNSET_CONNECTION) { 00543 c.lanes.push_back(std::make_pair((*i).id, (*i).predecessor)); 00544 } 00545 } 00546 for (std::vector<OpenDriveLane>::const_iterator i=toLanes.begin(); i!=toLanes.end(); ++i) { 00547 if ((*i).type!="driving") { 00548 continue; 00549 } 00550 if (!toAtEnd && (*i).predecessor!=UNSET_CONNECTION) { 00551 c.lanes.push_back(std::make_pair((*i).predecessor, (*i).id)); 00552 } 00553 if (toAtEnd && (*i).successor!=UNSET_CONNECTION) { 00554 c.lanes.push_back(std::make_pair((*i).successor, (*i).id)); 00555 } 00556 } 00557 } 00558 00559 00560 void 00561 NIImporter_OpenDrive::setLaneConnections(NIImporter_OpenDrive::Connection& c, 00562 const OpenDriveEdge& from, bool fromAtBegin, OpenDriveXMLTag fromLaneDir, 00563 const OpenDriveEdge& via, bool viaIsReversed, OpenDriveXMLTag viaLaneDir, 00564 const OpenDriveEdge& to, bool toAtEnd, OpenDriveXMLTag toLaneDir) { 00565 Connection from2via(0, "", 0); 00566 setLaneConnections(from2via, from, fromAtBegin, fromLaneDir, via, viaIsReversed, viaLaneDir); 00567 Connection via2to(0, "", 0); 00568 setLaneConnections(via2to, via, viaIsReversed, viaLaneDir, to, toAtEnd, toLaneDir); 00569 for (std::vector<std::pair<int, int> >::const_iterator i=from2via.lanes.begin(); i!=from2via.lanes.end(); ++i) { 00570 int fromLane = (*i).first; 00571 int viaLane = (*i).second; 00572 for (std::vector<std::pair<int, int> >::const_iterator j=via2to.lanes.begin(); j!=via2to.lanes.end(); ++j) { 00573 if ((*j).first==viaLane) { 00574 c.lanes.push_back(std::make_pair(fromLane, (*j).second)); 00575 break; 00576 } 00577 } 00578 } 00579 } 00580 00581 00582 NBNode* 00583 NIImporter_OpenDrive::getOrBuildNode(const std::string& id, Position& pos, 00584 NBNodeCont& nc) throw(ProcessError) { 00585 if (nc.retrieve(id)==0) { 00586 // not yet built; build now 00587 if (!nc.insert(id, pos)) { 00588 // !!! clean up 00589 throw ProcessError("Could not add node '" + id + "'."); 00590 } 00591 } 00592 return nc.retrieve(id); 00593 } 00594 00595 00596 void 00597 NIImporter_OpenDrive::setNodeSecure(NBNodeCont& nc, OpenDriveEdge& e, 00598 const std::string& nodeID, NIImporter_OpenDrive::LinkType lt) throw(ProcessError) { 00599 NBNode* n = nc.retrieve(nodeID); 00600 if (n==0) { 00601 throw ProcessError("Could not find node '" + nodeID + "'."); 00602 } 00603 if (lt==OPENDRIVE_LT_SUCCESSOR) { 00604 if (e.to!=0&&e.to!=n) { 00605 throw ProcessError("Edge '" + e.id + "' has two end nodes."); 00606 } 00607 e.to = n; 00608 } else { 00609 if (e.from!=0&&e.from!=n) { 00610 throw ProcessError("Edge '" + e.id + "' has two start nodes."); 00611 } 00612 e.from = n; 00613 } 00614 } 00615 00616 00617 00618 00619 00620 NBEdge* 00621 NIImporter_OpenDrive::getOutgoingDirectionalEdge(const NBEdgeCont& ec, 00622 const NBNodeCont& nc, 00623 const std::string& edgeID, 00624 const std::string& nodeID) throw() { 00625 NBNode* node = nc.retrieve(nodeID); 00626 NBEdge* e = ec.retrieve(edgeID); 00627 if (e!=0 && node->hasOutgoing(e)) { 00628 return e; 00629 } 00630 e = ec.retrieve("-" + edgeID); 00631 if (e!=0 && node->hasOutgoing(e)) { 00632 return e; 00633 } 00634 return 0; 00635 } 00636 00637 00638 NBEdge* 00639 NIImporter_OpenDrive::getIncomingDirectionalEdge(const NBEdgeCont& ec, 00640 const NBNodeCont& nc, 00641 const std::string& edgeID, 00642 const std::string& nodeID) throw() { 00643 NBNode* node = nc.retrieve(nodeID); 00644 NBEdge* e = ec.retrieve(edgeID); 00645 if (e!=0 && node->hasIncoming(e)) { 00646 return e; 00647 } 00648 e = ec.retrieve("-" + edgeID); 00649 if (e!=0 && node->hasIncoming(e)) { 00650 return e; 00651 } 00652 return 0; 00653 } 00654 00655 00656 void 00657 NIImporter_OpenDrive::computeShapes(std::vector<OpenDriveEdge> &edges) throw() { 00658 for (std::vector<OpenDriveEdge>::iterator i=edges.begin(); i!=edges.end(); ++i) { 00659 OpenDriveEdge& e = *i; 00660 for (std::vector<OpenDriveGeometry>::iterator j=e.geometries.begin(); j!=e.geometries.end(); ++j) { 00661 OpenDriveGeometry& g = *j; 00662 std::vector<Position> geom; 00663 switch (g.type) { 00664 case OPENDRIVE_GT_UNKNOWN: 00665 break; 00666 case OPENDRIVE_GT_LINE: 00667 geom = geomFromLine(e, g); 00668 break; 00669 case OPENDRIVE_GT_SPIRAL: 00670 geom = geomFromSpiral(e, g); 00671 break; 00672 case OPENDRIVE_GT_ARC: 00673 geom = geomFromArc(e, g); 00674 break; 00675 case OPENDRIVE_GT_POLY3: 00676 geom = geomFromPoly(e, g); 00677 break; 00678 default: 00679 break; 00680 } 00681 for (std::vector<Position>::iterator k=geom.begin(); k!=geom.end(); ++k) { 00682 e.geom.push_back_noDoublePos(*k); 00683 } 00684 } 00685 for (unsigned int j=0; j<e.geom.size(); ++j) { 00686 if (!NILoader::transformCoordinates(e.geom[j])) { 00687 WRITE_ERROR("Unable to project coordinates for."); 00688 } 00689 } 00690 } 00691 } 00692 00693 std::vector<Position> 00694 NIImporter_OpenDrive::geomFromLine(const OpenDriveEdge& e, const OpenDriveGeometry& g) throw() { 00695 UNUSED_PARAMETER(e); 00696 std::vector<Position> ret; 00697 ret.push_back(Position(g.x, g.y)); 00698 ret.push_back(calculateStraightEndPoint(g.hdg, g.length, Position(g.x, g.y))); 00699 return ret; 00700 } 00701 00702 00703 std::vector<Position> 00704 NIImporter_OpenDrive::geomFromSpiral(const OpenDriveEdge& e, const OpenDriveGeometry& g) throw() { 00705 UNUSED_PARAMETER(e); 00706 std::vector<Position> ret; 00707 SUMOReal curveStart = g.params[0]; 00708 SUMOReal curveEnd = g.params[1]; 00709 Point2D<double> end; 00710 EulerSpiral s(Point2D<double>(g.x, g.y), g.hdg, curveStart, (curveEnd-curveStart)/g.length, g.length); 00711 std::vector<Point2D<double> > into; 00712 s.computeSpiral(into, 1.); 00713 for (std::vector<Point2D<double> >::iterator i=into.begin(); i!=into.end(); ++i) { 00714 ret.push_back(Position((*i).getX(), (*i).getY())); 00715 } 00716 return ret; 00717 } 00718 00719 00720 std::vector<Position> 00721 NIImporter_OpenDrive::geomFromArc(const OpenDriveEdge& e, const OpenDriveGeometry& g) throw() { 00722 UNUSED_PARAMETER(e); 00723 std::vector<Position> ret; 00724 SUMOReal dist = 0.0; 00725 SUMOReal centerX = g.x; 00726 SUMOReal centerY = g.y; 00727 // left: positive value 00728 SUMOReal curvature = g.params[0]; 00729 SUMOReal radius = 1. / curvature; 00730 // center point 00731 calculateCurveCenter(¢erX, ¢erY, radius, g.hdg); 00732 SUMOReal endX = g.x; 00733 SUMOReal endY = g.y; 00734 SUMOReal startX = g.x; 00735 SUMOReal startY = g.y; 00736 SUMOReal hdgS = g.hdg; 00737 SUMOReal hdgE; 00738 SUMOReal geo_posS = g.s; 00739 SUMOReal geo_posE = g.s; 00740 bool end = false; 00741 do { 00742 geo_posE += C_LENGTH; 00743 if (geo_posE - g.s > g.length) { 00744 geo_posE = g.s + g.length; 00745 } 00746 if (geo_posE - g.s > g.length) { 00747 geo_posE = g.s + g.length; 00748 } 00749 calcPointOnCurve(&endX, &endY, centerX, centerY, radius, geo_posE - geo_posS); 00750 00751 dist += (geo_posE - geo_posS); 00752 if (curvature > 0.0) { 00753 hdgE = g.hdg + dist/fabs(radius); 00754 } else { 00755 hdgE = g.hdg - dist/fabs(radius); 00756 } 00757 // 00758 ret.push_back(Position(startX, startY)); 00759 // 00760 startX = endX; 00761 startY = endY; 00762 geo_posS = geo_posE; 00763 hdgS = hdgE; 00764 00765 if (geo_posE - (g.s + g.length) < 0.001 && geo_posE - (g.s + g.length) > -0.001) { 00766 end = true; 00767 } 00768 } while (!end); 00769 return ret; 00770 } 00771 00772 00773 std::vector<Position> 00774 NIImporter_OpenDrive::geomFromPoly(const OpenDriveEdge& e, const OpenDriveGeometry& g) throw() { 00775 UNUSED_PARAMETER(g); 00776 UNUSED_PARAMETER(e); 00777 std::vector<Position> ret; 00778 return ret; 00779 } 00780 00781 00782 Position 00783 NIImporter_OpenDrive::calculateStraightEndPoint(double hdg, double length, const Position& start) throw() { 00784 double normx = 1.0f; 00785 double normy = 0.0f; 00786 double x2 = normx * cos(hdg) - normy * sin(hdg); 00787 double y2 = normx * sin(hdg) + normy * cos(hdg); 00788 normx = x2 * length; 00789 normy = y2 * length; 00790 return Position(start.x() + normx, start.y() + normy); 00791 } 00792 00793 00794 void 00795 NIImporter_OpenDrive::calculateCurveCenter(SUMOReal* ad_x, SUMOReal* ad_y, SUMOReal ad_radius, SUMOReal ad_hdg) throw() { 00796 SUMOReal normX = 1.0; 00797 SUMOReal normY = 0.0; 00798 SUMOReal tmpX; 00799 SUMOReal turn; 00800 if (ad_radius > 0) { 00801 turn = -1.0; 00802 } else { 00803 turn = 1.0; 00804 } 00805 00806 tmpX = normX; 00807 normX = normX * cos(ad_hdg) + normY * sin(ad_hdg); 00808 normY = tmpX * sin(ad_hdg) + normY * cos(ad_hdg); 00809 00810 tmpX = normX; 00811 normX = normX * cos(90 * PI / 180) + turn * normY * sin(90 * PI / 180); 00812 normY = -1 * turn * tmpX * sin(90 * PI / 180) + normY * cos(90 * PI / 180); 00813 00814 normX = fabs(ad_radius) * normX; 00815 normY = fabs(ad_radius) * normY; 00816 00817 *ad_x += normX; 00818 *ad_y += normY; 00819 } 00820 00821 00822 void 00823 NIImporter_OpenDrive::calcPointOnCurve(SUMOReal* ad_x, SUMOReal* ad_y, SUMOReal ad_centerX, SUMOReal ad_centerY, 00824 SUMOReal ad_r, SUMOReal ad_length) throw() { 00825 double rotAngle = ad_length/fabs(ad_r); 00826 double vx = *ad_x - ad_centerX; 00827 double vy = *ad_y - ad_centerY; 00828 double tmpx; 00829 00830 double turn; 00831 if (ad_r > 0) { 00832 turn = -1; //left 00833 } else { 00834 turn = 1; //right 00835 } 00836 tmpx = vx; 00837 vx = vx * cos(rotAngle) + turn * vy * sin(rotAngle); 00838 vy = -1 * turn * tmpx * sin(rotAngle) + vy * cos(rotAngle); 00839 *ad_x = vx + ad_centerX; 00840 *ad_y = vy + ad_centerY; 00841 } 00842 00843 // --------------------------------------------------------------------------- 00844 // loader methods 00845 // --------------------------------------------------------------------------- 00846 NIImporter_OpenDrive::NIImporter_OpenDrive( 00847 std::vector<OpenDriveEdge> &innerEdges, 00848 std::vector<OpenDriveEdge> &outerEdges) 00849 : GenericSAXHandler(openDriveTags, OPENDRIVE_TAG_NOTHING, openDriveAttrs, OPENDRIVE_ATTR_NOTHING, "opendrive"), 00850 myCurrentEdge("", "", -1), myInnerEdges(innerEdges), myOuterEdges(outerEdges) { 00851 } 00852 00853 00854 NIImporter_OpenDrive::~NIImporter_OpenDrive() throw() { 00855 } 00856 00857 00858 void 00859 NIImporter_OpenDrive::myStartElement(int element, 00860 const SUMOSAXAttributes& attrs) throw(ProcessError) { 00861 bool ok = true; 00862 switch (element) { 00863 case OPENDRIVE_TAG_HEADER: { 00864 int majorVersion = attrs.getIntReporting(OPENDRIVE_ATTR_REVMAJOR, 0, ok); 00865 int minorVersion = attrs.getIntReporting(OPENDRIVE_ATTR_REVMINOR, 0, ok); 00866 if (majorVersion!=1||minorVersion!=2) { 00867 WRITE_WARNING("Given openDrive file '" + getFileName() + "' uses version " + toString(majorVersion) + "." + toString(minorVersion) + ";\n Version 1.2 is supported."); 00868 } 00869 } 00870 break; 00871 case OPENDRIVE_TAG_ROAD: { 00872 std::string id = attrs.getStringReporting(OPENDRIVE_ATTR_ID, 0, ok); 00873 std::string junction = attrs.getStringReporting(OPENDRIVE_ATTR_JUNCTION, id.c_str(), ok); 00874 SUMOReal length = attrs.getSUMORealReporting(OPENDRIVE_ATTR_LENGTH, id.c_str(), ok); 00875 myCurrentEdge = OpenDriveEdge(id, junction, length); 00876 } 00877 break; 00878 case OPENDRIVE_TAG_PREDECESSOR: { 00879 if (myElementStack.size()>=2&&myElementStack[myElementStack.size()-2]==OPENDRIVE_TAG_ROAD) { 00880 std::string elementType = attrs.getStringReporting(OPENDRIVE_ATTR_ELEMENTTYPE, myCurrentEdge.id.c_str(), ok); 00881 std::string elementID = attrs.getStringReporting(OPENDRIVE_ATTR_ELEMENTID, myCurrentEdge.id.c_str(), ok); 00882 std::string contactPoint = attrs.hasAttribute(OPENDRIVE_ATTR_CONTACTPOINT) 00883 ? attrs.getStringReporting(OPENDRIVE_ATTR_CONTACTPOINT, myCurrentEdge.id.c_str(), ok) 00884 : "end"; 00885 addLink(OPENDRIVE_LT_PREDECESSOR, elementType, elementID, contactPoint); 00886 } 00887 if (myElementStack.size()>=2&&myElementStack[myElementStack.size()-2]==OPENDRIVE_TAG_LANE) { 00888 int no = attrs.getIntReporting(OPENDRIVE_ATTR_ID, myCurrentEdge.id.c_str(), ok); 00889 OpenDriveLane& l = myCurrentEdge.laneSections[myCurrentEdge.laneSections.size()-1].lanesByDir[myCurrentLaneDirection].back(); 00890 l.predecessor = no; 00891 } 00892 } 00893 break; 00894 case OPENDRIVE_TAG_SUCCESSOR: { 00895 if (myElementStack.size()>=2&&myElementStack[myElementStack.size()-2]==OPENDRIVE_TAG_ROAD) { 00896 std::string elementType = attrs.getStringReporting(OPENDRIVE_ATTR_ELEMENTTYPE, myCurrentEdge.id.c_str(), ok); 00897 std::string elementID = attrs.getStringReporting(OPENDRIVE_ATTR_ELEMENTID, myCurrentEdge.id.c_str(), ok); 00898 std::string contactPoint = attrs.hasAttribute(OPENDRIVE_ATTR_CONTACTPOINT) 00899 ? attrs.getStringReporting(OPENDRIVE_ATTR_CONTACTPOINT, myCurrentEdge.id.c_str(), ok) 00900 : "start"; 00901 addLink(OPENDRIVE_LT_SUCCESSOR, elementType, elementID, contactPoint); 00902 } 00903 if (myElementStack.size()>=2&&myElementStack[myElementStack.size()-2]==OPENDRIVE_TAG_LANE) { 00904 int no = attrs.getIntReporting(OPENDRIVE_ATTR_ID, myCurrentEdge.id.c_str(), ok); 00905 OpenDriveLane& l = myCurrentEdge.laneSections[myCurrentEdge.laneSections.size()-1].lanesByDir[myCurrentLaneDirection].back(); 00906 l.successor = no; 00907 } 00908 } 00909 break; 00910 case OPENDRIVE_TAG_GEOMETRY: { 00911 SUMOReal length = attrs.getSUMORealReporting(OPENDRIVE_ATTR_LENGTH, myCurrentEdge.id.c_str(), ok); 00912 SUMOReal s = attrs.getSUMORealReporting(OPENDRIVE_ATTR_S, myCurrentEdge.id.c_str(), ok); 00913 SUMOReal x = attrs.getSUMORealReporting(OPENDRIVE_ATTR_X, myCurrentEdge.id.c_str(), ok); 00914 SUMOReal y = attrs.getSUMORealReporting(OPENDRIVE_ATTR_Y, myCurrentEdge.id.c_str(), ok); 00915 SUMOReal hdg = attrs.getSUMORealReporting(OPENDRIVE_ATTR_HDG, myCurrentEdge.id.c_str(), ok); 00916 myCurrentEdge.geometries.push_back(OpenDriveGeometry(length, s, x, y, hdg)); 00917 } 00918 break; 00919 case OPENDRIVE_TAG_LINE: { 00920 std::vector<SUMOReal> vals; 00921 addGeometryShape(OPENDRIVE_GT_LINE, vals); 00922 } 00923 break; 00924 case OPENDRIVE_TAG_SPIRAL: { 00925 std::vector<SUMOReal> vals; 00926 vals.push_back(attrs.getSUMORealReporting(OPENDRIVE_ATTR_CURVSTART, myCurrentEdge.id.c_str(), ok)); 00927 vals.push_back(attrs.getSUMORealReporting(OPENDRIVE_ATTR_CURVEND, myCurrentEdge.id.c_str(), ok)); 00928 addGeometryShape(OPENDRIVE_GT_SPIRAL, vals); 00929 } 00930 break; 00931 case OPENDRIVE_TAG_ARC: { 00932 std::vector<SUMOReal> vals; 00933 vals.push_back(attrs.getSUMORealReporting(OPENDRIVE_ATTR_CURVATURE, myCurrentEdge.id.c_str(), ok)); 00934 addGeometryShape(OPENDRIVE_GT_ARC, vals); 00935 } 00936 break; 00937 case OPENDRIVE_TAG_POLY3: { 00938 std::vector<SUMOReal> vals; 00939 vals.push_back(attrs.getSUMORealReporting(OPENDRIVE_ATTR_A, myCurrentEdge.id.c_str(), ok)); 00940 vals.push_back(attrs.getSUMORealReporting(OPENDRIVE_ATTR_B, myCurrentEdge.id.c_str(), ok)); 00941 vals.push_back(attrs.getSUMORealReporting(OPENDRIVE_ATTR_C, myCurrentEdge.id.c_str(), ok)); 00942 vals.push_back(attrs.getSUMORealReporting(OPENDRIVE_ATTR_D, myCurrentEdge.id.c_str(), ok)); 00943 addGeometryShape(OPENDRIVE_GT_POLY3, vals); 00944 } 00945 break; 00946 case OPENDRIVE_TAG_LANESECTION: { 00947 SUMOReal s = attrs.getSUMORealReporting(OPENDRIVE_ATTR_S, myCurrentEdge.id.c_str(), ok); 00948 myCurrentEdge.laneSections.push_back(OpenDriveLaneSection(s)); 00949 } 00950 break; 00951 case OPENDRIVE_TAG_LEFT: 00952 myCurrentLaneDirection = OPENDRIVE_TAG_LEFT; 00953 break; 00954 case OPENDRIVE_TAG_CENTER: 00955 myCurrentLaneDirection = OPENDRIVE_TAG_CENTER; 00956 break; 00957 case OPENDRIVE_TAG_RIGHT: 00958 myCurrentLaneDirection = OPENDRIVE_TAG_RIGHT; 00959 break; 00960 case OPENDRIVE_TAG_LANE: { 00961 std::string type = attrs.getStringReporting(OPENDRIVE_ATTR_TYPE, myCurrentEdge.id.c_str(), ok); 00962 int id = attrs.getIntReporting(OPENDRIVE_ATTR_ID, myCurrentEdge.id.c_str(), ok); 00963 std::string level = attrs.hasAttribute(OPENDRIVE_ATTR_LEVEL) 00964 ? attrs.getStringReporting(OPENDRIVE_ATTR_LEVEL, myCurrentEdge.id.c_str(), ok) 00965 : ""; 00966 OpenDriveLaneSection& ls = myCurrentEdge.laneSections[myCurrentEdge.laneSections.size()-1]; 00967 ls.lanesByDir[myCurrentLaneDirection].push_back(OpenDriveLane(id, level, type)); 00968 } 00969 break; 00970 default: 00971 break; 00972 } 00973 myElementStack.push_back(element); 00974 } 00975 00976 00977 void 00978 NIImporter_OpenDrive::myCharacters(int element, 00979 const std::string& chars) throw(ProcessError) { 00980 UNUSED_PARAMETER(element); 00981 UNUSED_PARAMETER(chars); 00982 } 00983 00984 00985 00986 void 00987 NIImporter_OpenDrive::myEndElement(int element) throw(ProcessError) { 00988 myElementStack.pop_back(); 00989 switch (element) { 00990 case OPENDRIVE_TAG_ROAD: 00991 if (myCurrentEdge.junction=="" || myCurrentEdge.junction=="-1") { 00992 myOuterEdges.push_back(myCurrentEdge); 00993 } else { 00994 myInnerEdges.push_back(myCurrentEdge); 00995 } 00996 break; 00997 default: 00998 break; 00999 } 01000 } 01001 01002 01003 01004 void 01005 NIImporter_OpenDrive::addLink(LinkType lt, const std::string& elementType, 01006 const std::string& elementID, 01007 const std::string& contactPoint) throw(ProcessError) { 01008 OpenDriveLink l(lt, elementID); 01009 // elementType 01010 if (elementType=="road") { 01011 l.elementType = OPENDRIVE_ET_ROAD; 01012 } else if (elementType=="junction") { 01013 l.elementType = OPENDRIVE_ET_JUNCTION; 01014 } 01015 // contact point 01016 if (contactPoint=="start") { 01017 l.contactPoint = OPENDRIVE_CP_START; 01018 } else if (contactPoint=="end") { 01019 l.contactPoint = OPENDRIVE_CP_END; 01020 } 01021 // add 01022 myCurrentEdge.links.push_back(l); 01023 } 01024 01025 01026 void 01027 NIImporter_OpenDrive::addGeometryShape(GeometryType type, const std::vector<SUMOReal> &vals) throw(ProcessError) { 01028 // checks 01029 if (myCurrentEdge.geometries.size()==0) { 01030 throw ProcessError("Mismatching paranthesis in geometry definition for road '" + myCurrentEdge.id + "'"); 01031 } 01032 OpenDriveGeometry& last = myCurrentEdge.geometries[myCurrentEdge.geometries.size()-1]; 01033 if (last.type!=OPENDRIVE_GT_UNKNOWN) { 01034 throw ProcessError("Double geometry information for road '" + myCurrentEdge.id + "'"); 01035 } 01036 // set 01037 last.type = type; 01038 last.params = vals; 01039 } 01040 01041 01042 /****************************************************************************/ 01043