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