SUMO - Simulation of Urban MObility
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
NWWriter_SUMO.cpp
Go to the documentation of this file.
1 /****************************************************************************/
9 // Exporter writing networks using the SUMO format
10 /****************************************************************************/
11 // SUMO, Simulation of Urban MObility; see http://sumo.sourceforge.net/
12 // Copyright (C) 2001-2012 DLR (http://www.dlr.de/) and contributors
13 /****************************************************************************/
14 //
15 // This file is part of SUMO.
16 // SUMO is free software: you can redistribute it and/or modify
17 // it under the terms of the GNU General Public License as published by
18 // the Free Software Foundation, either version 3 of the License, or
19 // (at your option) any later version.
20 //
21 /****************************************************************************/
22 
23 
24 // ===========================================================================
25 // included modules
26 // ===========================================================================
27 #ifdef _MSC_VER
28 #include <windows_config.h>
29 #else
30 #include <config.h>
31 #endif
32 #include <cmath>
36 #include <utils/common/ToString.h>
38 #include <netbuild/NBEdge.h>
39 #include <netbuild/NBEdgeCont.h>
40 #include <netbuild/NBNode.h>
41 #include <netbuild/NBNodeCont.h>
42 #include <netbuild/NBNetBuilder.h>
44 #include <netbuild/NBDistrict.h>
45 #include "NWFrame.h"
46 #include "NWWriter_SUMO.h"
47 
48 #ifdef CHECK_MEMORY_LEAKS
49 #include <foreign/nvwa/debug_new.h>
50 #endif // CHECK_MEMORY_LEAKS
51 
52 
53 
54 // ===========================================================================
55 // method definitions
56 // ===========================================================================
57 // ---------------------------------------------------------------------------
58 // static methods
59 // ---------------------------------------------------------------------------
60 void
62  // check whether a matsim-file shall be generated
63  if (!oc.isSet("output-file")) {
64  return;
65  }
66  OutputDevice& device = OutputDevice::getDevice(oc.getString("output-file"));
67  device.writeXMLHeader("net", SUMOSAXAttributes::ENCODING, NWFrame::MAJOR_VERSION + " xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:noNamespaceSchemaLocation=\"http://sumo.sf.net/xsd/net_file.xsd\""); // street names may contain non-ascii chars
68  device.lf();
69  // get involved container
70  const NBNodeCont& nc = nb.getNodeCont();
71  const NBEdgeCont& ec = nb.getEdgeCont();
72  const NBDistrictCont& dc = nb.getDistrictCont();
73 
74  // write network offsets and projection
75  writeLocation(device);
76 
77  // write inner lanes
78  if (!oc.getBool("no-internal-links")) {
79  bool hadAny = false;
80  for (std::map<std::string, NBNode*>::const_iterator i = nc.begin(); i != nc.end(); ++i) {
81  hadAny |= writeInternalEdges(device, *(*i).second);
82  }
83  if (hadAny) {
84  device.lf();
85  }
86  }
87 
88  // write edges with lanes and connected edges
89  bool noNames = !oc.getBool("output.street-names");
90  for (std::map<std::string, NBEdge*>::const_iterator i = ec.begin(); i != ec.end(); ++i) {
91  writeEdge(device, *(*i).second, noNames);
92  }
93  device.lf();
94 
95  // write tls logics
96  writeTrafficLights(device, nb.getTLLogicCont());
97 
98  // write the nodes (junctions)
99  for (std::map<std::string, NBNode*>::const_iterator i = nc.begin(); i != nc.end(); ++i) {
100  writeJunction(device, *(*i).second);
101  }
102  device.lf();
103  const bool includeInternal = !oc.getBool("no-internal-links");
104  if (includeInternal) {
105  // ... internal nodes if not unwanted
106  bool hadAny = false;
107  for (std::map<std::string, NBNode*>::const_iterator i = nc.begin(); i != nc.end(); ++i) {
108  hadAny |= writeInternalNodes(device, *(*i).second);
109  }
110  if (hadAny) {
111  device.lf();
112  }
113  }
114 
115  // write the successors of lanes
116  unsigned int numConnections = 0;
117  for (std::map<std::string, NBEdge*>::const_iterator it_edge = ec.begin(); it_edge != ec.end(); it_edge++) {
118  NBEdge* from = it_edge->second;
120  const std::vector<NBEdge::Connection> connections = from->getConnections();
121  numConnections += (unsigned int)connections.size();
122  for (std::vector<NBEdge::Connection>::const_iterator it_c = connections.begin(); it_c != connections.end(); it_c++) {
123  writeConnection(device, *from, *it_c, includeInternal);
124  }
125  }
126  if (numConnections > 0) {
127  device.lf();
128  }
129  if (includeInternal) {
130  // ... internal successors if not unwanted
131  bool hadAny = false;
132  for (std::map<std::string, NBNode*>::const_iterator i = nc.begin(); i != nc.end(); ++i) {
133  hadAny |= writeInternalConnections(device, *(*i).second);
134  }
135  if (hadAny) {
136  device.lf();
137  }
138  }
139  // write loaded prohibitions
140  for (std::map<std::string, NBNode*>::const_iterator i = nc.begin(); i != nc.end(); ++i) {
141  writeProhibitions(device, i->second->getProhibitions());
142  }
143 
144  // write roundabout information
145  const std::vector<std::set<NBEdge*> > &roundabouts = nb.getRoundabouts();
146  for (std::vector<std::set<NBEdge*> >::const_iterator i = roundabouts.begin(); i != roundabouts.end(); ++i) {
147  writeRoundabout(device, *i);
148  }
149  if (roundabouts.size() != 0) {
150  device.lf();
151  }
152 
153  // write the districts
154  for (std::map<std::string, NBDistrict*>::const_iterator i = dc.begin(); i != dc.end(); i++) {
155  writeDistrict(device, *(*i).second);
156  }
157  if (dc.size() != 0) {
158  device.lf();
159  }
160  device.close();
161 }
162 
163 
164 bool
166  bool ret = false;
167  const EdgeVector& incoming = n.getIncomingEdges();
168  for (EdgeVector::const_iterator i = incoming.begin(); i != incoming.end(); i++) {
169  const std::vector<NBEdge::Connection> &elv = (*i)->getConnections();
170  for (std::vector<NBEdge::Connection>::const_iterator k = elv.begin(); k != elv.end(); ++k) {
171  if ((*k).toEdge == 0) {
172  continue;
173  }
174  writeInternalEdge(into, (*k).id, (*k).vmax, (*k).shape);
175  if ((*k).haveVia) {
176  writeInternalEdge(into, (*k).viaID, (*k).viaVmax, (*k).viaShape);
177  }
178  ret = true;
179  }
180  }
181  return ret;
182 }
183 
184 
185 void
186 NWWriter_SUMO::writeInternalEdge(OutputDevice& into, const std::string& id, SUMOReal vmax, const PositionVector& shape) {
187  SUMOReal length = MAX2(shape.length(), (SUMOReal)POSITION_EPS); // microsim needs positive length
188  into.openTag(SUMO_TAG_EDGE);
189  into.writeAttr(SUMO_ATTR_ID, id);
191  into.closeOpener();
192  into.openTag(SUMO_TAG_LANE);
193  into.writeAttr(SUMO_ATTR_ID, id + "_0");
194  into.writeAttr(SUMO_ATTR_INDEX, 0);
195  into.writeAttr(SUMO_ATTR_SPEED, vmax);
196  into.writeAttr(SUMO_ATTR_LENGTH, length);
197  into.writeAttr(SUMO_ATTR_SHAPE, shape);
198  into.closeTag(true);
199  into.closeTag();
200 }
201 
202 
203 void
204 NWWriter_SUMO::writeEdge(OutputDevice& into, const NBEdge& e, bool noNames) {
205  // write the edge's begin
208  into.writeAttr(SUMO_ATTR_TO, e.getToNode()->getID());
209  if (!noNames && e.getStreetName() != "") {
211  }
213  if (e.getTypeName() != "") {
215  }
216  if (e.isMacroscopicConnector()) {
218  }
219  // write the spread type if not default ("right")
222  }
223  if (e.hasLoadedLength()) {
225  }
226  if (!e.hasDefaultGeometry()) {
228  }
229  into.closeOpener();
230  // write the lanes
231  const std::vector<NBEdge::Lane> &lanes = e.getLanes();
232  SUMOReal length = e.getLoadedLength();
233  if (length <= 0) {
234  length = (SUMOReal) .1;
235  }
236  for (unsigned int i = 0; i < (unsigned int) lanes.size(); i++) {
237  writeLane(into, e.getID(), e.getLaneID(i), lanes[i], length, i);
238  }
239  // close the edge
240  into.closeTag();
241 }
242 
243 
244 void
245 NWWriter_SUMO::writeLane(OutputDevice& into, const std::string& eID, const std::string& lID, const NBEdge::Lane& lane, SUMOReal length, unsigned int index) {
246  // output the lane's attributes
248  // the first lane of an edge will be the depart lane
249  into.writeAttr(SUMO_ATTR_INDEX, index);
250  // write the list of allowed/disallowed vehicle classes
251  writePermissions(into, lane.permissions);
252  writePreferences(into, lane.preferred);
253  // some further information
254  if (lane.speed == 0) {
255  WRITE_WARNING("Lane #" + toString(index) + " of edge '" + eID + "' has a maximum velocity of 0.");
256  } else if (lane.speed < 0) {
257  throw ProcessError("Negative velocity (" + toString(lane.speed) + " on edge '" + eID + "' lane#" + toString(index) + ".");
258  }
259  if (lane.offset > 0) {
260  length = length - lane.offset;
261  }
262  into.writeAttr(SUMO_ATTR_SPEED, lane.speed);
263  into.writeAttr(SUMO_ATTR_LENGTH, length);
264  if (lane.offset > 0) {
266  }
267  if (lane.width != NBEdge::UNSPECIFIED_WIDTH) {
268  into.writeAttr(SUMO_ATTR_WIDTH, lane.width);
269  }
270  PositionVector shape = lane.shape;
271  if (lane.offset > 0) {
272  shape = shape.getSubpart(0, shape.length() - lane.offset);
273  }
274  into.writeAttr(SUMO_ATTR_SHAPE, shape);
275  into.closeTag(true);
276 }
277 
278 
279 void
281  // write the attributes
283  into.writeAttr(SUMO_ATTR_TYPE, n.getType());
285  // write the incoming lanes
286  std::string incLanes;
287  const std::vector<NBEdge*> &incoming = n.getIncomingEdges();
288  for (std::vector<NBEdge*>::const_iterator i = incoming.begin(); i != incoming.end(); ++i) {
289  unsigned int noLanes = (*i)->getNumLanes();
290  for (unsigned int j = 0; j < noLanes; j++) {
291  incLanes += (*i)->getLaneID(j);
292  if (i != incoming.end() - 1 || j < noLanes - 1) {
293  incLanes += ' ';
294  }
295  }
296  }
297  into.writeAttr(SUMO_ATTR_INCLANES, incLanes);
298  // write the internal lanes
299  std::string intLanes;
300  if (!OptionsCont::getOptions().getBool("no-internal-links")) {
301  unsigned int l = 0;
302  for (EdgeVector::const_iterator i = incoming.begin(); i != incoming.end(); i++) {
303  const std::vector<NBEdge::Connection> &elv = (*i)->getConnections();
304  for (std::vector<NBEdge::Connection>::const_iterator k = elv.begin(); k != elv.end(); ++k) {
305  if ((*k).toEdge == 0) {
306  continue;
307  }
308  if (l != 0) {
309  intLanes += ' ';
310  }
311  if (!(*k).haveVia) {
312  intLanes += (*k).id + "_0";
313  } else {
314  intLanes += (*k).viaID + "_0";
315  }
316  l++;
317  }
318  }
319  }
320  into.writeAttr(SUMO_ATTR_INTLANES, intLanes);
321  // close writing
323  if (n.getType() == NODETYPE_DEAD_END) {
324  into.closeTag(true);
325  } else {
326  into.closeOpener();
327  // write right-of-way logics
328  n.writeLogic(into);
329  into.closeTag();
330  }
331 }
332 
333 
334 bool
336  bool ret = false;
337  const std::vector<NBEdge*> &incoming = n.getIncomingEdges();
338  for (std::vector<NBEdge*>::const_iterator i = incoming.begin(); i != incoming.end(); i++) {
339  const std::vector<NBEdge::Connection> &elv = (*i)->getConnections();
340  for (std::vector<NBEdge::Connection>::const_iterator k = elv.begin(); k != elv.end(); ++k) {
341  if ((*k).toEdge == 0 || !(*k).haveVia) {
342  continue;
343  }
344  Position pos = (*k).shape[-1];
345  into.openTag(SUMO_TAG_JUNCTION).writeAttr(SUMO_ATTR_ID, (*k).viaID + "_0");
347  NWFrame::writePositionLong(pos, into);
348  std::string incLanes = (*k).id + "_0";
349  if ((*k).foeIncomingLanes.length() != 0) {
350  incLanes += " " + (*k).foeIncomingLanes;
351  }
352  into.writeAttr(SUMO_ATTR_INCLANES, incLanes);
353  into.writeAttr(SUMO_ATTR_INTLANES, (*k).foeInternalLanes);
354  into.closeTag(true);
355  ret = true;
356  }
357  }
358  return ret;
359 }
360 
361 
362 void
364  bool includeInternal, ConnectionStyle style) {
365  assert(c.toEdge != 0);
367  into.writeAttr(SUMO_ATTR_FROM, from.getID());
368  into.writeAttr(SUMO_ATTR_TO, c.toEdge->getID());
371 
372  if (style != PLAIN) {
373  if (includeInternal) {
374  into.writeAttr(SUMO_ATTR_VIA, c.id + "_0");
375  }
376  // set information about the controlling tl if any
377  if (c.tlID != "") {
378  into.writeAttr(SUMO_ATTR_TLID, c.tlID);
380  }
381  if (style == SUMONET) {
382  // write the direction information
383  LinkDirection dir = from.getToNode()->getDirection(&from, c.toEdge);
384  assert(dir != LINKDIR_NODIR);
385  into.writeAttr(SUMO_ATTR_DIR, toString(dir));
386  // write the state information
387  std::string stateCode;
388  if (c.tlID != "") {
389  stateCode = toString(LINKSTATE_TL_OFF_BLINKING);
390  } else {
391  stateCode = from.getToNode()->stateCode(&from, c.toEdge, c.toLane, c.mayDefinitelyPass);
392  }
393  into.writeAttr(SUMO_ATTR_STATE, stateCode);
394  }
395  }
396  into.closeTag(true);
397 }
398 
399 
400 bool
402  bool ret = false;
403  const std::vector<NBEdge*> &incoming = n.getIncomingEdges();
404  for (std::vector<NBEdge*>::const_iterator i = incoming.begin(); i != incoming.end(); ++i) {
405  NBEdge* from = *i;
406  const std::vector<NBEdge::Connection> &connections = from->getConnections();
407  for (std::vector<NBEdge::Connection>::const_iterator j = connections.begin(); j != connections.end(); ++j) {
408  const NBEdge::Connection& c = *j;
409  assert(c.toEdge != 0);
410  if (c.haveVia) {
411  // internal split
412  writeInternalConnection(into, c.id, c.toEdge->getID(), c.toLane, c.viaID + "_0");
413  writeInternalConnection(into, c.viaID, c.toEdge->getID(), c.toLane, "");
414  } else {
415  // no internal split
416  writeInternalConnection(into, c.id, c.toEdge->getID(), c.toLane, "");
417  }
418  ret = true;
419  }
420  }
421  return ret;
422 }
423 
424 
425 void
427  const std::string& from, const std::string& to, int toLane, const std::string& via) {
429  into.writeAttr(SUMO_ATTR_FROM, from);
430  into.writeAttr(SUMO_ATTR_TO, to);
432  into.writeAttr(SUMO_ATTR_TO_LANE, toLane);
433  if (via != "") {
434  into.writeAttr(SUMO_ATTR_VIA, via);
435  }
436  into.writeAttr(SUMO_ATTR_DIR, "s");
437  into.writeAttr(SUMO_ATTR_STATE, "M");
438  into.closeTag(true);
439 }
440 
441 
442 void
443 NWWriter_SUMO::writeRoundabout(OutputDevice& into, const std::set<NBEdge*> &r) {
444  std::set<std::string> nodes;
445  for (std::set<NBEdge*>::const_iterator j = r.begin(); j != r.end(); ++j) {
446  nodes.insert((*j)->getToNode()->getID());
447  }
448  std::string nodeString;
449  for (std::set<std::string>::const_iterator j = nodes.begin(); j != nodes.end(); ++j) {
450  if (j != nodes.begin()) {
451  nodeString += " ";
452  }
453  nodeString += *j;
454  }
456 }
457 
458 
459 void
461  std::vector<SUMOReal> sourceW = d.getSourceWeights();
463  std::vector<SUMOReal> sinkW = d.getSinkWeights();
465  // write the head and the id of the district
467  if (d.getShape().size() > 0) {
469  }
470  into.closeOpener();
471  size_t i;
472  // write all sources
473  const std::vector<NBEdge*> &sources = d.getSourceEdges();
474  for (i = 0; i < sources.size(); i++) {
475  // write the head and the id of the source
476  into.openTag(SUMO_TAG_TAZSOURCE).writeAttr(SUMO_ATTR_ID, sources[i]->getID()).writeAttr(SUMO_ATTR_WEIGHT, sourceW[i]);
477  into.closeTag(true);
478  }
479  // write all sinks
480  const std::vector<NBEdge*> &sinks = d.getSinkEdges();
481  for (i = 0; i < sinks.size(); i++) {
482  // write the head and the id of the sink
483  into.openTag(SUMO_TAG_TAZSINK).writeAttr(SUMO_ATTR_ID, sinks[i]->getID()).writeAttr(SUMO_ATTR_WEIGHT, sinkW[i]);
484  into.closeTag(true);
485  }
486  // write the tail
487  into.closeTag();
488 }
489 
490 
491 std::string
493  SUMOReal time = STEPS2TIME(steps);
494  if (time == std::floor(time)) {
495  return toString(int(time));
496  } else {
497  return toString(time);
498  }
499 }
500 
501 
502 void
504  for (NBConnectionProhibits::const_iterator j = prohibitions.begin(); j != prohibitions.end(); j++) {
505  NBConnection prohibited = (*j).first;
506  const NBConnectionVector& prohibiting = (*j).second;
507  for (NBConnectionVector::const_iterator k = prohibiting.begin(); k != prohibiting.end(); k++) {
508  NBConnection prohibitor = *k;
512  into.closeTag(true);
513  }
514  }
515 }
516 
517 
518 std::string
520  return c.getFrom()->getID() + "->" + c.getTo()->getID();
521 }
522 
523 
524 void
526  std::vector<NBTrafficLightLogic*> logics = tllCont.getComputed();
527  for (std::vector<NBTrafficLightLogic*>::iterator it = logics.begin(); it != logics.end(); it++) {
529  into.writeAttr(SUMO_ATTR_ID, (*it)->getID());
531  into.writeAttr(SUMO_ATTR_PROGRAMID, (*it)->getProgramID());
532  into.writeAttr(SUMO_ATTR_OFFSET, writeSUMOTime((*it)->getOffset()));
533  into.closeOpener();
534  // write the phases
535  const std::vector<NBTrafficLightLogic::PhaseDefinition> &phases = (*it)->getPhases();
536  for (std::vector<NBTrafficLightLogic::PhaseDefinition>::const_iterator j = phases.begin(); j != phases.end(); ++j) {
537  into.openTag(SUMO_TAG_PHASE);
538  into.writeAttr(SUMO_ATTR_DURATION, writeSUMOTime(j->duration));
539  into.writeAttr(SUMO_ATTR_STATE, j->state);
540  into.closeTag(true);
541  }
542  into.closeTag();
543  }
544  if (logics.size() > 0) {
545  into.lf();
546  }
547 }
548 
549 
550 void
552  const GeoConvHelper& geoConvHelper = GeoConvHelper::getFinal();
554  into.writeAttr(SUMO_ATTR_NET_OFFSET, geoConvHelper.getOffsetBase());
555  into.writeAttr(SUMO_ATTR_CONV_BOUNDARY, geoConvHelper.getConvBoundary());
556  if (geoConvHelper.usingGeoProjection()) {
558  }
559  into.writeAttr(SUMO_ATTR_ORIG_BOUNDARY, geoConvHelper.getOrigBoundary());
560  if (geoConvHelper.usingGeoProjection()) {
561  into.setPrecision();
562  }
563  into.writeAttr(SUMO_ATTR_ORIG_PROJ, geoConvHelper.getProjString());
564  into.closeTag(true);
565  into.lf();
566 }
567 
568 
569 void
571  if (permissions == SVCFreeForAll) {
572  return;
573  } else if (permissions == 0) {
574  // special case: since all-empty encodes FreeForAll we must list all disallowed
576  return;
577  } else {
578  std::pair<std::string, bool> encoding = getPermissionEncoding(permissions);
579  if (encoding.second) {
580  into.writeAttr(SUMO_ATTR_ALLOW, encoding.first);
581  } else {
582  into.writeAttr(SUMO_ATTR_DISALLOW, encoding.first);
583  }
584  }
585 }
586 
587 
588 void
590  if (preferred == SVCFreeForAll || preferred == 0) {
591  return;
592  } else {
594  }
595 }
596 /****************************************************************************/
597