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