SUMO - Simulation of Urban MObility
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
NIImporter_OpenDrive.cpp
Go to the documentation of this file.
1 /****************************************************************************/
10 // Importer for networks stored in openDrive format
11 /****************************************************************************/
12 // SUMO, Simulation of Urban MObility; see http://sumo.sourceforge.net/
13 // Copyright (C) 2001-2012 DLR (http://www.dlr.de/) and contributors
14 /****************************************************************************/
15 //
16 // This file is part of SUMO.
17 // SUMO is free software: you can redistribute it and/or modify
18 // it under the terms of the GNU General Public License as published by
19 // the Free Software Foundation, either version 3 of the License, or
20 // (at your option) any later version.
21 //
22 /****************************************************************************/
23 
24 
25 // ===========================================================================
26 // included modules
27 // ===========================================================================
28 #ifdef _MSC_VER
29 #include <windows_config.h>
30 #else
31 #include <config.h>
32 #endif
33 #include <string>
34 #include <cmath>
38 #include <utils/common/ToString.h>
41 #include <netbuild/NBEdge.h>
42 #include <netbuild/NBEdgeCont.h>
43 #include <netbuild/NBNode.h>
44 #include <netbuild/NBNodeCont.h>
45 #include <netbuild/NBNetBuilder.h>
52 #include <utils/xml/XMLSubSys.h>
53 #include <utils/geom/Boundary.h>
54 #include "NILoader.h"
55 #include "NIImporter_OpenDrive.h"
56 
57 #ifdef CHECK_MEMORY_LEAKS
58 #include <foreign/nvwa/debug_new.h>
59 #endif // CHECK_MEMORY_LEAKS
60 
61 
62 // ===========================================================================
63 // definitions
64 // ===========================================================================
65 #define C_LENGTH 10.
66 
67 
68 // ===========================================================================
69 // static variables
70 // ===========================================================================
87 
89 };
90 
91 
116 
118 };
119 
120 
121 std::set<std::string> NIImporter_OpenDrive::myLaneTypes2Import;
122 
123 // ===========================================================================
124 // method definitions
125 // ===========================================================================
126 // ---------------------------------------------------------------------------
127 // static methods (interface in this case)
128 // ---------------------------------------------------------------------------
129 void
131  // check whether the option is set (properly)
132  if (!oc.isUsableFileList("opendrive-files")) {
133  return;
134  }
135  myLaneTypes2Import.insert("driving");
136  myLaneTypes2Import.insert("stop");
137  //myLaneTypes2Import.insert("mwyEntry");
138  //myLaneTypes2Import.insert("mwyExit");
139  myLaneTypes2Import.insert("special1");
140  myLaneTypes2Import.insert("parking");
141  // build the handler
142  std::vector<OpenDriveEdge> innerEdges, outerEdges;
143  NIImporter_OpenDrive handler(innerEdges, outerEdges);
144  // parse file(s)
145  std::vector<std::string> files = oc.getStringVector("opendrive-files");
146  for (std::vector<std::string>::const_iterator file = files.begin(); file != files.end(); ++file) {
147  if (!FileHelpers::exists(*file)) {
148  WRITE_ERROR("Could not open opendrive file '" + *file + "'.");
149  return;
150  }
151  handler.setFileName(*file);
152  PROGRESS_BEGIN_MESSAGE("Parsing opendrive from '" + *file + "'");
153  XMLSubSys::runParser(handler, *file);
155  }
156  // convert geometries into a discretised representation
157  computeShapes(innerEdges);
158  computeShapes(outerEdges);
159 
160  // -------------------------
161  // node building
162  // -------------------------
163  // build nodes#1
164  // look at all links which belong to a node, collect their bounding boxes
165  // and place the node in the middle of this bounding box
166  std::map<std::string, Boundary> posMap;
167  std::map<std::string, std::string> edge2junction;
168  // compute node positions
169  for (std::vector<OpenDriveEdge>::iterator i = innerEdges.begin(); i != innerEdges.end(); ++i) {
170  OpenDriveEdge& e = *i;
171  assert(e.junction != "-1" && e.junction != "");
172  edge2junction[e.id] = e.junction;
173  if (posMap.find(e.junction) == posMap.end()) {
174  posMap[e.junction] = Boundary();
175  }
176  posMap[e.junction].add(e.geom.getBoxBoundary());
177  }
178  // build nodes
179  for (std::map<std::string, Boundary>::iterator i = posMap.begin(); i != posMap.end(); ++i) {
180  if (!nb.getNodeCont().insert((*i).first, (*i).second.getCenter())) {
181  throw ProcessError("Could not add node '" + (*i).first + "'.");
182  }
183  }
184  // assign built nodes
185  for (std::vector<OpenDriveEdge>::iterator i = outerEdges.begin(); i != outerEdges.end(); ++i) {
186  OpenDriveEdge& e = *i;
187  for (std::vector<OpenDriveLink>::iterator j = e.links.begin(); j != e.links.end(); ++j) {
188  OpenDriveLink& l = *j;
189  if (l.elementType != OPENDRIVE_ET_ROAD) {
190  // set node information
192  continue;
193  }
194  if (edge2junction.find(l.elementID) != edge2junction.end()) {
195  // set node information of an internal road
196  setNodeSecure(nb.getNodeCont(), e, edge2junction[l.elementID], l.linkType);
197  continue;
198  }
199  }
200  }
201  // we should now have all nodes set for links which are not outer edge-to-outer edge links
202 
203 
204  // build nodes#2
205  // build nodes for all outer edge-to-outer edge connections
206  for (std::vector<OpenDriveEdge>::iterator i = outerEdges.begin(); i != outerEdges.end(); ++i) {
207  OpenDriveEdge& e = *i;
208  for (std::vector<OpenDriveLink>::iterator j = e.links.begin(); j != e.links.end(); ++j) {
209  OpenDriveLink& l = *j;
210  if (l.elementType != OPENDRIVE_ET_ROAD || edge2junction.find(l.elementID) != edge2junction.end()) {
211  // is a connection to an internal edge, or a node, skip
212  continue;
213  }
214  // we have a direct connection between to external edges
215  std::string id1 = e.id;
216  std::string id2 = l.elementID;
217  if (id1 < id2) {
218  std::swap(id1, id2);
219  }
220  std::string nid = id1 + "." + id2;
221  if (nb.getNodeCont().retrieve(nid) == 0) {
222  // not yet seen, build
223  Position pos = l.linkType == OPENDRIVE_LT_SUCCESSOR ? e.geom[(int)e.geom.size() - 1] : e.geom[0];
224  if (!nb.getNodeCont().insert(nid, pos)) {
225  throw ProcessError("Could not build node '" + nid + "'.");
226  }
227  }
228  /* debug-stuff
229  else {
230  Position pos = l.linkType==OPENDRIVE_LT_SUCCESSOR ? e.geom[e.geom.size()-1] : e.geom[0];
231  cout << nid << " " << pos << " " << nb.getNodeCont().retrieve(nid)->getPosition() << endl;
232  }
233  */
234  setNodeSecure(nb.getNodeCont(), e, nid, l.linkType);
235  }
236  }
237  // we should now have start/end nodes for all outer edge-to-outer edge connections
238 
239 
240  // build nodes#3
241  // assign further nodes generated from inner-edges
242  // these nodes have not been assigned earlier, because the connectiosn are referenced in inner-edges
243  for (std::vector<OpenDriveEdge>::iterator i = outerEdges.begin(); i != outerEdges.end(); ++i) {
244  OpenDriveEdge& e = *i;
245  if (e.to != 0 && e.from != 0) {
246  continue;
247  }
248  for (std::vector<OpenDriveEdge>::iterator j = innerEdges.begin(); j != innerEdges.end(); ++j) {
249  OpenDriveEdge& ie = *j;
250  for (std::vector<OpenDriveLink>::iterator k = ie.links.begin(); k != ie.links.end(); ++k) {
251  OpenDriveLink& il = *k;
252  if (il.elementType != OPENDRIVE_ET_ROAD || il.elementID != e.id) {
253  // not conneted to the currently investigated outer edge
254  continue;
255  }
256  std::string nid = edge2junction[ie.id];
257  if (il.contactPoint == OPENDRIVE_CP_START) {
259  } else {
261  }
262  }
263  }
264 
265  }
266 
267 
268  // build start/end nodes which were not defined previously
269  for (std::vector<OpenDriveEdge>::iterator i = outerEdges.begin(); i != outerEdges.end(); ++i) {
270  OpenDriveEdge& e = *i;
271  if (e.from == 0) {
272  std::string nid = e.id + ".begin";
273  Position pos(e.geometries[0].x, e.geometries[0].y);
274  e.from = getOrBuildNode(nid, e.geom[0], nb.getNodeCont());
275  }
276  if (e.to == 0) {
277  std::string nid = e.id + ".end";
278  Position pos(e.geometries[e.geometries.size() - 1].x, e.geometries[e.geometries.size() - 1].y);
279  e.to = getOrBuildNode(nid, e.geom[(int)e.geom.size() - 1], nb.getNodeCont());
280  }
281  }
282 
283 
284  // -------------------------
285  // edge building
286  // -------------------------
287  std::map<NBEdge*, std::map<int, int> > fromLaneMap;
288  std::map<NBEdge*, std::map<int, int> > toLaneMap;
289  //bool useLoadedLengths = oc.getBool("opendrive.use-given-lengths");
290  // build edges
291  for (std::vector<OpenDriveEdge>::iterator i = outerEdges.begin(); i != outerEdges.end(); ++i) {
292  OpenDriveEdge& e = *i;
293  SUMOReal speed = nb.getTypeCont().getSpeed("");
295  unsigned int noLanesRight = e.getMaxLaneNumber(OPENDRIVE_TAG_RIGHT);
296  unsigned int noLanesLeft = e.getMaxLaneNumber(OPENDRIVE_TAG_LEFT);
297  if (noLanesRight != 0 || noLanesLeft != 0) {
298  lsf = LANESPREAD_RIGHT;
299  } else {
300  WRITE_WARNING("Edge '" + e.id + "' has no lanes.");
301  }
302  if (noLanesRight > 0) {
303  int priority = e.getPriority(OPENDRIVE_TAG_RIGHT);
304  NBEdge* nbe = new NBEdge("-" + e.id, e.from, e.to, "", speed, noLanesRight, priority,
306  if (!nb.getEdgeCont().insert(nbe)) {
307  throw ProcessError("Could not add edge '" + std::string("-") + e.id + "'.");
308  }
309  for (unsigned int j = 0; j < noLanesRight; ++j) {
310  nbe->getLaneStruct(j).origID = e.id + " -" + toString(j + 1);
311  }
312  //if(useLoadedLengths) { nbe->setLoadedLength(e.length); }
313  fromLaneMap[nbe] = e.laneSections.back().buildLaneMapping(OPENDRIVE_TAG_RIGHT);
314  toLaneMap[nbe] = e.laneSections[0].buildLaneMapping(OPENDRIVE_TAG_RIGHT);
315  }
316  if (noLanesLeft > 0) {
317  int priority = e.getPriority(OPENDRIVE_TAG_LEFT);
318  NBEdge* nbe = new NBEdge(e.id, e.to, e.from, "", speed, noLanesLeft, priority,
320  if (!nb.getEdgeCont().insert(nbe)) {
321  throw ProcessError("Could not add edge '" + e.id + "'.");
322  }
323  //if(useLoadedLengths) { nbe->setLoadedLength(e.length); }
324  for (unsigned int j = 0; j < noLanesLeft; ++j) {
325  nbe->getLaneStruct(j).origID = e.id + " " + toString(j + 1);
326  }
327  fromLaneMap[nbe] = e.laneSections[0].buildLaneMapping(OPENDRIVE_TAG_LEFT);
328  toLaneMap[nbe] = e.laneSections.back().buildLaneMapping(OPENDRIVE_TAG_LEFT);
329  }
330  }
331 
332 
333  // -------------------------
334  // connections building
335  // -------------------------
336  std::vector<Connection> connections;
337  // connections#1
338  // build connections between outer-edges
339  for (std::vector<OpenDriveEdge>::iterator i = outerEdges.begin(); i != outerEdges.end(); ++i) {
340  OpenDriveEdge& e = *i;
341  for (std::vector<OpenDriveLink>::iterator j = e.links.begin(); j != e.links.end(); ++j) {
342  OpenDriveLink& l = *j;
343  if (l.elementType != OPENDRIVE_ET_ROAD) {
344  // we are not interested in connections to nodes
345  continue;
346  }
347  if (edge2junction.find(l.elementID) != edge2junction.end()) {
348  // connection via an inner-road
350  nb.getNodeCont().retrieve(edge2junction[l.elementID]),
351  e, l.linkType, l.elementID, connections);
352  } else {
353  // connection between two outer-edges; can be used directly
354  std::vector<OpenDriveEdge>::iterator p = std::find_if(outerEdges.begin(), outerEdges.end(), edge_by_id_finder(l.elementID));
355  if (p == outerEdges.end()) {
356  throw ProcessError("Could not find connection edge.");
357  }
358  std::string id1 = e.id;
359  std::string id2 = (*p).id;
360  if (id1 < id2) {
361  std::swap(id1, id2);
362  }
363  std::string nid = id1 + "." + id2;
365  addE2EConnectionsSecure(nb.getEdgeCont(), nb.getNodeCont().retrieve(nid), *p, e, connections);
366  } else {
367  addE2EConnectionsSecure(nb.getEdgeCont(), nb.getNodeCont().retrieve(nid), e, *p, connections);
368  }
369  }
370  }
371  }
372 
373  // build inner-edge connections
374  for (std::vector<OpenDriveEdge>::iterator i = innerEdges.begin(); i != innerEdges.end(); ++i) {
375  OpenDriveEdge& e = *i;
376  std::string pred, succ;
378  for (std::vector<OpenDriveLink>::iterator j = e.links.begin(); j != e.links.end(); ++j) {
379  OpenDriveLink& l = *j;
380  if (l.elementType != OPENDRIVE_ET_ROAD) {
381  // we are not interested in connections to nodes
382  std::cout << "unsupported" << std::endl;
383  continue;
384  }
385  if (edge2junction.find(l.elementID) != edge2junction.end()) {
386  // not supported
387  std::cout << "unsupported" << std::endl;
388  continue;
389  }
390  if (l.linkType == OPENDRIVE_LT_SUCCESSOR) {
391  if (succ != "") {
392  std::cout << "double succ" << std::endl;
393  }
394  succ = l.elementID;
395  succC = l.contactPoint;
396  } else {
397  if (pred != "") {
398  std::cout << "double pred" << std::endl;
399  }
400  pred = l.elementID;
401  predC = l.contactPoint;
402  }
403  }
404 
406  std::cout << "Both dirs given!" << std::endl;
407  }
408 
409  bool isReversed = false;
410  if (e.getMaxLaneNumber(OPENDRIVE_TAG_LEFT) != 0) {
411  // std::swap(pred, succ);
412  //std::swap(predC, succC);
413  isReversed = true;
414  }
415 
416  if (succ == "" || pred == "") {
417  std::cout << "Missing edge." << std::endl;
418  continue; // yes, occurs
419  }
420  std::vector<OpenDriveEdge>::iterator predEdge = std::find_if(outerEdges.begin(), outerEdges.end(), edge_by_id_finder(pred));
421  if (predEdge == outerEdges.end()) {
422  throw ProcessError("Could not find connection edge.");
423  }
424  std::vector<OpenDriveEdge>::iterator succEdge = std::find_if(outerEdges.begin(), outerEdges.end(), edge_by_id_finder(succ));
425  if (succEdge == outerEdges.end()) {
426  throw ProcessError("Could not find connection edge.");
427  }
428  NBEdge* fromEdge, *toEdge;
429  if (!isReversed) {
430  fromEdge = predC == OPENDRIVE_CP_END ? nb.getEdgeCont().retrieve("-" + pred) : nb.getEdgeCont().retrieve(pred);
431  toEdge = succC == OPENDRIVE_CP_START ? nb.getEdgeCont().retrieve("-" + succ) : nb.getEdgeCont().retrieve(succ);
432  } else {
433  fromEdge = predC != OPENDRIVE_CP_END ? nb.getEdgeCont().retrieve("-" + pred) : nb.getEdgeCont().retrieve(pred);
434  toEdge = succC != OPENDRIVE_CP_START ? nb.getEdgeCont().retrieve("-" + succ) : nb.getEdgeCont().retrieve(succ);
435  }
436  /*
437  Connection c(
438  n->hasIncoming(nb.getEdgeCont().retrieve("-" + pred)) ? nb.getEdgeCont().retrieve("-" + pred) : nb.getEdgeCont().retrieve(pred),
439  e.id,
440  n->hasOutgoing(nb.getEdgeCont().retrieve("-" + succ)) ? nb.getEdgeCont().retrieve("-" + succ) : nb.getEdgeCont().retrieve(succ));
441  */
442  Connection c(fromEdge, e.id, toEdge);
443  if (c.from == 0 || c.to == 0 || c.from == c.to) {
444  throw ProcessError("Something's false");
445  }
447  *predEdge, c.from->getID()[0] != '-', c.from->getID()[0] == '-' ? OPENDRIVE_TAG_RIGHT : OPENDRIVE_TAG_LEFT,
448  e, isReversed, !isReversed ? OPENDRIVE_TAG_RIGHT : OPENDRIVE_TAG_LEFT,
449  *succEdge, c.to->getID()[0] != '-', c.to->getID()[0] == '-' ? OPENDRIVE_TAG_RIGHT : OPENDRIVE_TAG_LEFT);
450  c.id = e.id;
451  connections.push_back(c);
452  }
453 
454  for (std::vector<Connection>::const_iterator i = connections.begin(); i != connections.end(); ++i) {
455  if ((*i).from == 0 || (*i).to == 0) {
456  std::cout << "Nope." << std::endl;
457  continue;
458  }
459  (*i).from->addEdge2EdgeConnection((*i).to);
460  std::map<int, int> fromMap = fromLaneMap[(*i).from];
461  std::map<int, int> toMap = fromLaneMap[(*i).to];
462  int index = 0;
463  for (std::vector<std::pair<int, int> >::const_iterator j = (*i).lanes.begin(); j != (*i).lanes.end(); ++j, --index) {
464  int fromLane = fromMap[(*j).first];
465  int toLane = toMap[(*j).second];
466  if (static_cast<unsigned int>(fromLane) >= (*i).from->getNumLanes() || fromLane < 0) {
467  std::cout << "False " << std::endl;
468  }
469  if (static_cast<unsigned int>(toLane) >= (*i).to->getNumLanes() || toLane < 0) {
470  std::cout << "False " << std::endl;
471  }
472 
473  (*i).from->addLane2LaneConnection(fromLane, (*i).to, toLane, NBEdge::L2L_VALIDATED, true, false);
474  if ((*i).id != "") {
475  std::vector<NBEdge::Connection>& cons = (*i).from->getConnections();
476  for (std::vector<NBEdge::Connection>::iterator k = cons.begin(); k != cons.end(); ++k) {
477  if ((*k).fromLane == fromLane && (*k).toEdge == (*i).to && (*k).toLane == toLane) {
478  (*k).origID = (*i).id + " " + toString(index);
479  break;
480  }
481  }
482  }
483  }
484  }
485 }
486 
487 
488 void
490  const NBNode* const node, const OpenDriveEdge& e,
491  LinkType lt, const std::string& via,
492  std::vector<NIImporter_OpenDrive::Connection>& connections) {
493  NBEdge* from = 0;
494  NBEdge* to = 0;
495  if (node == e.to) {
496  // the connection is at the end of the "positive" direction
497  if (lt == OPENDRIVE_LT_PREDECESSOR) {
498  // via -> edge
499  to = ec.retrieve(e.id);
500  } else {
501  // -edge -> via
502  // "ambigous?"
503  from = ec.retrieve("-" + e.id);
504  }
505  } else {
506  // the connection is at the begin of the "positive" direction
507  if (lt == OPENDRIVE_LT_PREDECESSOR) {
508  // via -> -edge
509  to = ec.retrieve("-" + e.id);
510  } else {
511  // edge -> via
512  // "ambigous?"
513  from = ec.retrieve(e.id);
514  }
515  }
516  if (from == 0 && to == 0) {
517  throw ProcessError("Missing edge");
518  }
519  Connection c(from, via, to);
520  connections.push_back(c);
521 }
522 
523 
524 void
527  std::vector<NIImporter_OpenDrive::Connection>& connections) {
528  // positive direction (from is incoming, to is outgoing)
529  NBEdge* fromEdge = ec.retrieve("-" + from.id);
530  if (fromEdge == 0 || !node->hasIncoming(fromEdge)) {
531  fromEdge = ec.retrieve(from.id);
532  }
533  NBEdge* toEdge = ec.retrieve("-" + to.id);
534  if (toEdge == 0 || !node->hasOutgoing(toEdge)) {
535  toEdge = ec.retrieve(to.id);
536  }
537  if (fromEdge != 0 && toEdge != 0) {
538  Connection c(fromEdge, "", toEdge);
540  from, c.from->getID()[0] != '-', c.from->getID()[0] == '-' ? OPENDRIVE_TAG_RIGHT : OPENDRIVE_TAG_LEFT,
541  to, c.to->getID()[0] != '-', c.to->getID()[0] == '-' ? OPENDRIVE_TAG_RIGHT : OPENDRIVE_TAG_LEFT);
542  connections.push_back(c);
543  }
544  // negative direction (to is incoming, from is outgoing)
545  fromEdge = ec.retrieve("-" + from.id);
546  if (fromEdge == 0 || !node->hasOutgoing(fromEdge)) {
547  fromEdge = ec.retrieve(from.id);
548  }
549  toEdge = ec.retrieve("-" + to.id);
550  if (toEdge == 0 || !node->hasIncoming(toEdge)) {
551  toEdge = ec.retrieve(to.id);
552  }
553  if (fromEdge != 0 && toEdge != 0) {
554  Connection c(toEdge, "", fromEdge);
556  to, c.to->getID()[0] != '-', c.to->getID()[0] == '-' ? OPENDRIVE_TAG_RIGHT : OPENDRIVE_TAG_LEFT,
557  from, c.from->getID()[0] != '-', c.from->getID()[0] == '-' ? OPENDRIVE_TAG_RIGHT : OPENDRIVE_TAG_LEFT);
558  connections.push_back(c);
559  }
560 }
561 
562 
563 void
565  const OpenDriveEdge& from, bool fromAtBegin, OpenDriveXMLTag fromLaneDir,
566  const OpenDriveEdge& to, bool toAtEnd, OpenDriveXMLTag toLaneDir) {
567  const OpenDriveLaneSection& fromLS = fromAtBegin ? from.laneSections[0] : from.laneSections.back();
568  const std::vector<OpenDriveLane>& fromLanes = fromLS.lanesByDir.find(fromLaneDir)->second;
569  const OpenDriveLaneSection& toLS = toAtEnd ? to.laneSections.back() : to.laneSections[0];
570  const std::vector<OpenDriveLane>& toLanes = toLS.lanesByDir.find(toLaneDir)->second;
571  // in the following, we are probably using the same information twice, stored once
572  // in the from-edge's successor field and in the to-edge's precessor field.
573  // though, we have no proof or information that this is always redundant
574  for (std::vector<OpenDriveLane>::const_iterator i = fromLanes.begin(); i != fromLanes.end(); ++i) {
575  if (myLaneTypes2Import.find((*i).type) == myLaneTypes2Import.end()) {
576  continue;
577  }
578  if (!fromAtBegin && (*i).successor != UNSET_CONNECTION) {
579  c.lanes.push_back(std::make_pair((*i).id, (*i).successor));
580  }
581  if (fromAtBegin && (*i).predecessor != UNSET_CONNECTION) {
582  c.lanes.push_back(std::make_pair((*i).id, (*i).predecessor));
583  }
584  }
585  for (std::vector<OpenDriveLane>::const_iterator i = toLanes.begin(); i != toLanes.end(); ++i) {
586  if (myLaneTypes2Import.find((*i).type) == myLaneTypes2Import.end()) {
587  continue;
588  }
589  if (!toAtEnd && (*i).predecessor != UNSET_CONNECTION) {
590  c.lanes.push_back(std::make_pair((*i).predecessor, (*i).id));
591  }
592  if (toAtEnd && (*i).successor != UNSET_CONNECTION) {
593  c.lanes.push_back(std::make_pair((*i).successor, (*i).id));
594  }
595  }
596 }
597 
598 
599 void
601  const OpenDriveEdge& from, bool fromAtBegin, OpenDriveXMLTag fromLaneDir,
602  const OpenDriveEdge& via, bool viaIsReversed, OpenDriveXMLTag viaLaneDir,
603  const OpenDriveEdge& to, bool toAtEnd, OpenDriveXMLTag toLaneDir) {
604  Connection from2via(0, "", 0);
605  setLaneConnections(from2via, from, fromAtBegin, fromLaneDir, via, viaIsReversed, viaLaneDir);
606  Connection via2to(0, "", 0);
607  setLaneConnections(via2to, via, viaIsReversed, viaLaneDir, to, toAtEnd, toLaneDir);
608  for (std::vector<std::pair<int, int> >::const_iterator i = from2via.lanes.begin(); i != from2via.lanes.end(); ++i) {
609  int fromLane = (*i).first;
610  int viaLane = (*i).second;
611  for (std::vector<std::pair<int, int> >::const_iterator j = via2to.lanes.begin(); j != via2to.lanes.end(); ++j) {
612  if ((*j).first == viaLane) {
613  c.lanes.push_back(std::make_pair(fromLane, (*j).second));
614  break;
615  }
616  }
617  }
618 }
619 
620 
621 NBNode*
622 NIImporter_OpenDrive::getOrBuildNode(const std::string& id, Position& pos,
623  NBNodeCont& nc) {
624  if (nc.retrieve(id) == 0) {
625  // not yet built; build now
626  if (!nc.insert(id, pos)) {
627  // !!! clean up
628  throw ProcessError("Could not add node '" + id + "'.");
629  }
630  }
631  return nc.retrieve(id);
632 }
633 
634 
635 void
637  const std::string& nodeID, NIImporter_OpenDrive::LinkType lt) {
638  NBNode* n = nc.retrieve(nodeID);
639  if (n == 0) {
640  throw ProcessError("Could not find node '" + nodeID + "'.");
641  }
642  if (lt == OPENDRIVE_LT_SUCCESSOR) {
643  if (e.to != 0 && e.to != n) {
644  throw ProcessError("Edge '" + e.id + "' has two end nodes.");
645  }
646  e.to = n;
647  } else {
648  if (e.from != 0 && e.from != n) {
649  throw ProcessError("Edge '" + e.id + "' has two start nodes.");
650  }
651  e.from = n;
652  }
653 }
654 
655 
656 
657 
658 
659 NBEdge*
661  const NBNodeCont& nc,
662  const std::string& edgeID,
663  const std::string& nodeID) {
664  NBNode* node = nc.retrieve(nodeID);
665  NBEdge* e = ec.retrieve(edgeID);
666  if (e != 0 && node->hasOutgoing(e)) {
667  return e;
668  }
669  e = ec.retrieve("-" + edgeID);
670  if (e != 0 && node->hasOutgoing(e)) {
671  return e;
672  }
673  return 0;
674 }
675 
676 
677 NBEdge*
679  const NBNodeCont& nc,
680  const std::string& edgeID,
681  const std::string& nodeID) {
682  NBNode* node = nc.retrieve(nodeID);
683  NBEdge* e = ec.retrieve(edgeID);
684  if (e != 0 && node->hasIncoming(e)) {
685  return e;
686  }
687  e = ec.retrieve("-" + edgeID);
688  if (e != 0 && node->hasIncoming(e)) {
689  return e;
690  }
691  return 0;
692 }
693 
694 
695 void
696 NIImporter_OpenDrive::computeShapes(std::vector<OpenDriveEdge>& edges) {
697  for (std::vector<OpenDriveEdge>::iterator i = edges.begin(); i != edges.end(); ++i) {
698  OpenDriveEdge& e = *i;
699  for (std::vector<OpenDriveGeometry>::iterator j = e.geometries.begin(); j != e.geometries.end(); ++j) {
700  OpenDriveGeometry& g = *j;
701  std::vector<Position> geom;
702  switch (g.type) {
704  break;
705  case OPENDRIVE_GT_LINE:
706  geom = geomFromLine(e, g);
707  break;
708  case OPENDRIVE_GT_SPIRAL:
709  geom = geomFromSpiral(e, g);
710  break;
711  case OPENDRIVE_GT_ARC:
712  geom = geomFromArc(e, g);
713  break;
714  case OPENDRIVE_GT_POLY3:
715  geom = geomFromPoly(e, g);
716  break;
717  default:
718  break;
719  }
720  for (std::vector<Position>::iterator k = geom.begin(); k != geom.end(); ++k) {
722  }
723  }
724  for (unsigned int j = 0; j < e.geom.size(); ++j) {
726  WRITE_ERROR("Unable to project coordinates for.");
727  }
728  }
729  }
730 }
731 
732 std::vector<Position>
734  UNUSED_PARAMETER(e);
735  std::vector<Position> ret;
736  ret.push_back(Position(g.x, g.y));
737  ret.push_back(calculateStraightEndPoint(g.hdg, g.length, Position(g.x, g.y)));
738  return ret;
739 }
740 
741 
742 std::vector<Position>
744  UNUSED_PARAMETER(e);
745  std::vector<Position> ret;
746  SUMOReal curveStart = g.params[0];
747  SUMOReal curveEnd = g.params[1];
748  Point2D<double> end;
749  EulerSpiral s(Point2D<double>(g.x, g.y), g.hdg, curveStart, (curveEnd - curveStart) / g.length, g.length);
750  std::vector<Point2D<double> > into;
751  s.computeSpiral(into, 1.);
752  for (std::vector<Point2D<double> >::iterator i = into.begin(); i != into.end(); ++i) {
753  ret.push_back(Position((*i).getX(), (*i).getY()));
754  }
755  return ret;
756 }
757 
758 
759 std::vector<Position>
761  UNUSED_PARAMETER(e);
762  std::vector<Position> ret;
763  SUMOReal dist = 0.0;
764  SUMOReal centerX = g.x;
765  SUMOReal centerY = g.y;
766  // left: positive value
767  SUMOReal curvature = g.params[0];
768  SUMOReal radius = 1. / curvature;
769  // center point
770  calculateCurveCenter(&centerX, &centerY, radius, g.hdg);
771  SUMOReal endX = g.x;
772  SUMOReal endY = g.y;
773  SUMOReal startX = g.x;
774  SUMOReal startY = g.y;
775  SUMOReal hdgS = g.hdg;
776  SUMOReal hdgE;
777  SUMOReal geo_posS = g.s;
778  SUMOReal geo_posE = g.s;
779  bool end = false;
780  do {
781  geo_posE += C_LENGTH;
782  if (geo_posE - g.s > g.length) {
783  geo_posE = g.s + g.length;
784  }
785  if (geo_posE - g.s > g.length) {
786  geo_posE = g.s + g.length;
787  }
788  calcPointOnCurve(&endX, &endY, centerX, centerY, radius, geo_posE - geo_posS);
789 
790  dist += (geo_posE - geo_posS);
791  if (curvature > 0.0) {
792  hdgE = g.hdg + dist / fabs(radius);
793  } else {
794  hdgE = g.hdg - dist / fabs(radius);
795  }
796  //
797  ret.push_back(Position(startX, startY));
798  //
799  startX = endX;
800  startY = endY;
801  geo_posS = geo_posE;
802  hdgS = hdgE;
803 
804  if (geo_posE - (g.s + g.length) < 0.001 && geo_posE - (g.s + g.length) > -0.001) {
805  end = true;
806  }
807  } while (!end);
808  return ret;
809 }
810 
811 
812 std::vector<Position>
814  UNUSED_PARAMETER(g);
815  UNUSED_PARAMETER(e);
816  std::vector<Position> ret;
817  return ret;
818 }
819 
820 
821 Position
822 NIImporter_OpenDrive::calculateStraightEndPoint(double hdg, double length, const Position& start) {
823  double normx = 1.0f;
824  double normy = 0.0f;
825  double x2 = normx * cos(hdg) - normy * sin(hdg);
826  double y2 = normx * sin(hdg) + normy * cos(hdg);
827  normx = x2 * length;
828  normy = y2 * length;
829  return Position(start.x() + normx, start.y() + normy);
830 }
831 
832 
833 void
835  SUMOReal normX = 1.0;
836  SUMOReal normY = 0.0;
837  SUMOReal tmpX;
838  SUMOReal turn;
839  if (ad_radius > 0) {
840  turn = -1.0;
841  } else {
842  turn = 1.0;
843  }
844 
845  tmpX = normX;
846  normX = normX * cos(ad_hdg) + normY * sin(ad_hdg);
847  normY = tmpX * sin(ad_hdg) + normY * cos(ad_hdg);
848 
849  tmpX = normX;
850  normX = normX * cos(90 * PI / 180) + turn * normY * sin(90 * PI / 180);
851  normY = -1 * turn * tmpX * sin(90 * PI / 180) + normY * cos(90 * PI / 180);
852 
853  normX = fabs(ad_radius) * normX;
854  normY = fabs(ad_radius) * normY;
855 
856  *ad_x += normX;
857  *ad_y += normY;
858 }
859 
860 
861 void
863  SUMOReal ad_r, SUMOReal ad_length) {
864  double rotAngle = ad_length / fabs(ad_r);
865  double vx = *ad_x - ad_centerX;
866  double vy = *ad_y - ad_centerY;
867  double tmpx;
868 
869  double turn;
870  if (ad_r > 0) {
871  turn = -1; //left
872  } else {
873  turn = 1; //right
874  }
875  tmpx = vx;
876  vx = vx * cos(rotAngle) + turn * vy * sin(rotAngle);
877  vy = -1 * turn * tmpx * sin(rotAngle) + vy * cos(rotAngle);
878  *ad_x = vx + ad_centerX;
879  *ad_y = vy + ad_centerY;
880 }
881 
882 
883 // ---------------------------------------------------------------------------
884 // section
885 // ---------------------------------------------------------------------------
887  lanesByDir[OPENDRIVE_TAG_LEFT] = std::vector<OpenDriveLane>();
888  lanesByDir[OPENDRIVE_TAG_RIGHT] = std::vector<OpenDriveLane>();
889  lanesByDir[OPENDRIVE_TAG_CENTER] = std::vector<OpenDriveLane>();
890 }
891 
892 
893 unsigned int
895  unsigned int laneNum = 0;
896  const std::vector<OpenDriveLane>& dirLanes = lanesByDir.find(dir)->second;
897  for (std::vector<OpenDriveLane>::const_iterator i = dirLanes.begin(); i != dirLanes.end(); ++i) {
898  if (myLaneTypes2Import.find((*i).type) != myLaneTypes2Import.end()) {
899  ++laneNum;
900  }
901  }
902  return laneNum;
903 }
904 
905 
906 std::map<int, int>
908  std::map<int, int> ret;
909  unsigned int sumoLane = 0;
910  const std::vector<OpenDriveLane>& dirLanes = lanesByDir.find(dir)->second;
911  if (dir == OPENDRIVE_TAG_RIGHT) {
912  for (std::vector<OpenDriveLane>::const_reverse_iterator i = dirLanes.rbegin(); i != dirLanes.rend(); ++i) {
913  if (myLaneTypes2Import.find((*i).type) != myLaneTypes2Import.end()) {
914  ret[(*i).id] = sumoLane++;
915  }
916  }
917  } else {
918  for (std::vector<OpenDriveLane>::const_iterator i = dirLanes.begin(); i != dirLanes.end(); ++i) {
919  if (myLaneTypes2Import.find((*i).type) != myLaneTypes2Import.end()) {
920  ret[(*i).id] = sumoLane++;
921  }
922  }
923  }
924  return ret;
925 }
926 
927 
928 // ---------------------------------------------------------------------------
929 // edge
930 // ---------------------------------------------------------------------------
931 unsigned int
933  unsigned int maxLaneNum = 0;
934  for (std::vector<OpenDriveLaneSection>::const_iterator i = laneSections.begin(); i != laneSections.end(); ++i) {
935  maxLaneNum = MAX2(maxLaneNum, (*i).getLaneNumber(dir));
936  }
937  return maxLaneNum;
938 }
939 
940 
941 int
943  int prio = 1;
944  SUMOReal lastPos = -1;
945  for (std::vector<OpenDriveSignal>::const_iterator i = signals.begin(); i != signals.end(); ++i) {
946  int tmp = 1;
947  if ((*i).type == "301" || (*i).type == "306") {
948  tmp = 2;
949  }
950  if ((*i).type == "205") {
951  tmp = 0;
952  }
953  if (tmp != 1 && dir == OPENDRIVE_TAG_RIGHT && (*i).orientation < 0) {
954  prio = tmp;
955  }
956  if (tmp != 1 && dir == OPENDRIVE_TAG_LEFT && (*i).orientation > 0) {
957  prio = tmp;
958  }
959 
960  }
961  return prio;
962 }
963 
964 
965 
966 // ---------------------------------------------------------------------------
967 // loader methods
968 // ---------------------------------------------------------------------------
970  std::vector<OpenDriveEdge>& innerEdges,
971  std::vector<OpenDriveEdge>& outerEdges)
973  myCurrentEdge("", "", -1), myInnerEdges(innerEdges), myOuterEdges(outerEdges) {
974 }
975 
976 
978 }
979 
980 
981 void
983  const SUMOSAXAttributes& attrs) {
984  bool ok = true;
985  switch (element) {
986  case OPENDRIVE_TAG_HEADER: {
987  int majorVersion = attrs.getIntReporting(OPENDRIVE_ATTR_REVMAJOR, 0, ok);
988  int minorVersion = attrs.getIntReporting(OPENDRIVE_ATTR_REVMINOR, 0, ok);
989  if (majorVersion != 1 || minorVersion != 2) {
990  WRITE_WARNING("Given openDrive file '" + getFileName() + "' uses version " + toString(majorVersion) + "." + toString(minorVersion) + ";\n Version 1.2 is supported.");
991  }
992  }
993  break;
994  case OPENDRIVE_TAG_ROAD: {
995  std::string id = attrs.getStringReporting(OPENDRIVE_ATTR_ID, 0, ok);
996  std::string junction = attrs.getStringReporting(OPENDRIVE_ATTR_JUNCTION, id.c_str(), ok);
997  SUMOReal length = attrs.getSUMORealReporting(OPENDRIVE_ATTR_LENGTH, id.c_str(), ok);
998  myCurrentEdge = OpenDriveEdge(id, junction, length);
999  }
1000  break;
1002  if (myElementStack.size() >= 2 && myElementStack[myElementStack.size() - 2] == OPENDRIVE_TAG_ROAD) {
1003  std::string elementType = attrs.getStringReporting(OPENDRIVE_ATTR_ELEMENTTYPE, myCurrentEdge.id.c_str(), ok);
1004  std::string elementID = attrs.getStringReporting(OPENDRIVE_ATTR_ELEMENTID, myCurrentEdge.id.c_str(), ok);
1005  std::string contactPoint = attrs.hasAttribute(OPENDRIVE_ATTR_CONTACTPOINT)
1007  : "end";
1008  addLink(OPENDRIVE_LT_PREDECESSOR, elementType, elementID, contactPoint);
1009  }
1010  if (myElementStack.size() >= 2 && myElementStack[myElementStack.size() - 2] == OPENDRIVE_TAG_LANE) {
1011  int no = attrs.getIntReporting(OPENDRIVE_ATTR_ID, myCurrentEdge.id.c_str(), ok);
1013  l.predecessor = no;
1014  }
1015  }
1016  break;
1017  case OPENDRIVE_TAG_SUCCESSOR: {
1018  if (myElementStack.size() >= 2 && myElementStack[myElementStack.size() - 2] == OPENDRIVE_TAG_ROAD) {
1019  std::string elementType = attrs.getStringReporting(OPENDRIVE_ATTR_ELEMENTTYPE, myCurrentEdge.id.c_str(), ok);
1020  std::string elementID = attrs.getStringReporting(OPENDRIVE_ATTR_ELEMENTID, myCurrentEdge.id.c_str(), ok);
1021  std::string contactPoint = attrs.hasAttribute(OPENDRIVE_ATTR_CONTACTPOINT)
1023  : "start";
1024  addLink(OPENDRIVE_LT_SUCCESSOR, elementType, elementID, contactPoint);
1025  }
1026  if (myElementStack.size() >= 2 && myElementStack[myElementStack.size() - 2] == OPENDRIVE_TAG_LANE) {
1027  int no = attrs.getIntReporting(OPENDRIVE_ATTR_ID, myCurrentEdge.id.c_str(), ok);
1029  l.successor = no;
1030  }
1031  }
1032  break;
1033  case OPENDRIVE_TAG_GEOMETRY: {
1039  myCurrentEdge.geometries.push_back(OpenDriveGeometry(length, s, x, y, hdg));
1040  }
1041  break;
1042  case OPENDRIVE_TAG_LINE: {
1043  std::vector<SUMOReal> vals;
1045  }
1046  break;
1047  case OPENDRIVE_TAG_SPIRAL: {
1048  std::vector<SUMOReal> vals;
1049  vals.push_back(attrs.getSUMORealReporting(OPENDRIVE_ATTR_CURVSTART, myCurrentEdge.id.c_str(), ok));
1050  vals.push_back(attrs.getSUMORealReporting(OPENDRIVE_ATTR_CURVEND, myCurrentEdge.id.c_str(), ok));
1052  }
1053  break;
1054  case OPENDRIVE_TAG_ARC: {
1055  std::vector<SUMOReal> vals;
1056  vals.push_back(attrs.getSUMORealReporting(OPENDRIVE_ATTR_CURVATURE, myCurrentEdge.id.c_str(), ok));
1058  }
1059  break;
1060  case OPENDRIVE_TAG_POLY3: {
1061  std::vector<SUMOReal> vals;
1062  vals.push_back(attrs.getSUMORealReporting(OPENDRIVE_ATTR_A, myCurrentEdge.id.c_str(), ok));
1063  vals.push_back(attrs.getSUMORealReporting(OPENDRIVE_ATTR_B, myCurrentEdge.id.c_str(), ok));
1064  vals.push_back(attrs.getSUMORealReporting(OPENDRIVE_ATTR_C, myCurrentEdge.id.c_str(), ok));
1065  vals.push_back(attrs.getSUMORealReporting(OPENDRIVE_ATTR_D, myCurrentEdge.id.c_str(), ok));
1067  }
1068  break;
1072  }
1073  break;
1074  case OPENDRIVE_TAG_LEFT:
1076  break;
1077  case OPENDRIVE_TAG_CENTER:
1079  break;
1080  case OPENDRIVE_TAG_RIGHT:
1082  break;
1083  case OPENDRIVE_TAG_LANE: {
1084  std::string type = attrs.getStringReporting(OPENDRIVE_ATTR_TYPE, myCurrentEdge.id.c_str(), ok);
1085  int id = attrs.getIntReporting(OPENDRIVE_ATTR_ID, myCurrentEdge.id.c_str(), ok);
1086  std::string level = attrs.hasAttribute(OPENDRIVE_ATTR_LEVEL)
1088  : "";
1090  ls.lanesByDir[myCurrentLaneDirection].push_back(OpenDriveLane(id, level, type));
1091  }
1092  break;
1093  case OPENDRIVE_TAG_SIGNAL: {
1094  int id = attrs.getIntReporting(OPENDRIVE_ATTR_ID, myCurrentEdge.id.c_str(), ok);
1095  std::string type = attrs.getStringReporting(OPENDRIVE_ATTR_TYPE, myCurrentEdge.id.c_str(), ok);
1096  int orientation = attrs.getStringReporting(OPENDRIVE_ATTR_ORIENTATION, myCurrentEdge.id.c_str(), ok) == "-" ? -1 : 1;
1098  bool dynamic = attrs.getStringReporting(OPENDRIVE_ATTR_DYNAMIC, myCurrentEdge.id.c_str(), ok) == "no" ? false : true;
1099  myCurrentEdge.signals.push_back(OpenDriveSignal(id, type, orientation, dynamic, s));
1100  }
1101  break;
1102  default:
1103  break;
1104  }
1105  myElementStack.push_back(element);
1106 }
1107 
1108 
1109 void
1111  myElementStack.pop_back();
1112  switch (element) {
1113  case OPENDRIVE_TAG_ROAD:
1114  if (myCurrentEdge.junction == "" || myCurrentEdge.junction == "-1") {
1115  myOuterEdges.push_back(myCurrentEdge);
1116  } else {
1117  myInnerEdges.push_back(myCurrentEdge);
1118  }
1119  break;
1120  default:
1121  break;
1122  }
1123 }
1124 
1125 
1126 
1127 void
1128 NIImporter_OpenDrive::addLink(LinkType lt, const std::string& elementType,
1129  const std::string& elementID,
1130  const std::string& contactPoint) {
1131  OpenDriveLink l(lt, elementID);
1132  // elementType
1133  if (elementType == "road") {
1135  } else if (elementType == "junction") {
1137  }
1138  // contact point
1139  if (contactPoint == "start") {
1141  } else if (contactPoint == "end") {
1143  }
1144  // add
1145  myCurrentEdge.links.push_back(l);
1146 }
1147 
1148 
1149 void
1150 NIImporter_OpenDrive::addGeometryShape(GeometryType type, const std::vector<SUMOReal>& vals) {
1151  // checks
1152  if (myCurrentEdge.geometries.size() == 0) {
1153  throw ProcessError("Mismatching paranthesis in geometry definition for road '" + myCurrentEdge.id + "'");
1154  }
1156  if (last.type != OPENDRIVE_GT_UNKNOWN) {
1157  throw ProcessError("Double geometry information for road '" + myCurrentEdge.id + "'");
1158  }
1159  // set
1160  last.type = type;
1161  last.params = vals;
1162 }
1163 
1164 
1165 /****************************************************************************/
1166