SUMO - Simulation of Urban MObility
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
NWWriter_OpenDrive.cpp
Go to the documentation of this file.
1 /****************************************************************************/
7 // Exporter writing networks using the openDRIVE format
8 /****************************************************************************/
9 // SUMO, Simulation of Urban MObility; see http://sumo.sourceforge.net/
10 // Copyright (C) 2001-2012 DLR (http://www.dlr.de/) and contributors
11 /****************************************************************************/
12 //
13 // This file is part of SUMO.
14 // SUMO is free software: you can redistribute it and/or modify
15 // it under the terms of the GNU General Public License as published by
16 // the Free Software Foundation, either version 3 of the License, or
17 // (at your option) any later version.
18 //
19 /****************************************************************************/
20 
21 
22 // ===========================================================================
23 // included modules
24 // ===========================================================================
25 #ifdef _MSC_VER
26 #include <windows_config.h>
27 #else
28 #include <config.h>
29 #endif
30 
31 #include <ctime>
32 #include "NWWriter_OpenDrive.h"
34 #include <netbuild/NBEdge.h>
35 #include <netbuild/NBEdgeCont.h>
36 #include <netbuild/NBNode.h>
37 #include <netbuild/NBNodeCont.h>
38 #include <netbuild/NBNetBuilder.h>
42 #include <utils/common/StdDefs.h>
45 
46 #ifdef CHECK_MEMORY_LEAKS
47 #include <foreign/nvwa/debug_new.h>
48 #endif // CHECK_MEMORY_LEAKS
49 
50 
51 
52 // ===========================================================================
53 // method definitions
54 // ===========================================================================
55 // ---------------------------------------------------------------------------
56 // static methods
57 // ---------------------------------------------------------------------------
58 void
60  // check whether an opendrive-file shall be generated
61  if (!oc.isSet("opendrive-output")) {
62  return;
63  }
64  // some internal mapping containers
65  int edgeID = 0;
66  int nodeID = 0;
67  StringBijection<int> edgeMap;
68  StringBijection<int> nodeMap;
69  //
70  OutputDevice& device = OutputDevice::getDevice(oc.getString("opendrive-output"));
71  device << "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n";
72  device << "<OpenDRIVE>\n";
73  time_t now = time(0);
74  std::string dstr(ctime(&now));
75  const NBNodeCont& nc = nb.getNodeCont();
76  const NBEdgeCont& ec = nb.getEdgeCont();
78  device << " <header revMajor=\"1\" revMinor=\"3\" name=\"\" version=\"1.00\" date=\"" << dstr.substr(0, dstr.length() - 1)
79  << "\" north=\"" << b.ymax() << "\" south=\"" << b.ymin() << "\" east=\"" << b.xmax() << "\" west=\"" << b.xmin()
80  << "\" maxRoad=\"" << ec.size() << "\" maxJunc=\"" << nc.size() << "\" maxPrg=\"0\"/>\n";
81  // write normal edges (road)
82  for (std::map<std::string, NBEdge*>::const_iterator i = ec.begin(); i != ec.end(); ++i) {
83  const NBEdge* e = (*i).second;
84  device << " <road name=\"" << StringUtils::escapeXML(e->getStreetName()) << "\" length=\"" << e->getLength() << "\" id=\"" << getID(e->getID(), edgeMap, edgeID) << "\" junction=\"-1\">\n";
85  device << " <link>\n";
86  device << " <predecessor elementType=\"junction\" elementId=\"" << getID(e->getFromNode()->getID(), nodeMap, nodeID) << "\"/>\n";
87  device << " <successor elementType=\"junction\" elementId=\"" << getID(e->getToNode()->getID(), nodeMap, nodeID) << "\"/>\n";
88  device << " </link>\n";
89  device << " <type s=\"0\" type=\"town\"/>\n";
90  const std::vector<NBEdge::Lane>& lanes = e->getLanes();
91  unsigned int li = (unsigned int)lanes.size() - 1;
92  PositionVector ls = e->getLaneShape(li);
93  SUMOReal width = lanes[li].width < 0 || !e->hasLaneSpecificWidth() ? SUMO_const_laneWidth : lanes[li].width;
94  ls.move2side(-width / 2.);
95  writePlanView(ls, device);
96  device << " <elevationProfile><elevation s=\"0\" a=\"0\" b=\"0\" c=\"0\" d=\"0\"/></elevationProfile>\n";
97  device << " <lateralProfile/>\n";
98  device << " <lanes>\n";
99  device << " <laneSection s=\"0\">\n";
100  writeEmptyCenterLane(device, "solid", 0.13);
101  device << " <right>\n";
102  for (int j = e->getNumLanes(); --j >= 0;) {
103  device << " <lane id=\"-" << e->getNumLanes() - j << "\" type=\"driving\" level=\"0\">\n";
104  device << " <link>\n";
105  device << " <predecessor id=\"-1\"/>\n"; // internal roads have this
106  device << " <successor id=\"-1\"/>\n"; // internal roads have this
107  device << " </link>\n";
108  SUMOReal width = lanes[j].width < 0 || !e->hasLaneSpecificWidth() ? SUMO_const_laneWidth : lanes[j].width;
109  device << " <width sOffset=\"0\" a=\"" << width << "\" b=\"0\" c=\"0\" d=\"0\"/>\n";
110  std::string markType = "broken";
111  if (j == 0) {
112  markType = "solid";
113  }
114  device << " <roadMark sOffset=\"0\" type=\"" << markType << "\" weight=\"standard\" color=\"standard\" width=\"0.13\"/>\n";
115  device << " </lane>\n";
116  }
117  device << " </right>\n";
118  device << " </laneSection>\n";
119  device << " </lanes>\n";
120  device << " <objects/>\n";
121  device << " <signals/>\n";
122  device << " </road>\n";
123  }
124  device << "\n";
125  // write junction-internal edges (road)
126  for (std::map<std::string, NBNode*>::const_iterator i = nc.begin(); i != nc.end(); ++i) {
127  NBNode* n = (*i).second;
128  const std::vector<NBEdge*>& incoming = (*i).second->getIncomingEdges();
129  for (std::vector<NBEdge*>::const_iterator j = incoming.begin(); j != incoming.end(); ++j) {
130  const std::vector<NBEdge::Connection>& elv = (*j)->getConnections();
131  for (std::vector<NBEdge::Connection>::const_iterator k = elv.begin(); k != elv.end(); ++k) {
132  if ((*k).toEdge == 0) {
133  continue;
134  }
135  const NBEdge::Connection& c = *k;
136  PositionVector shape = c.shape;
137  if (c.haveVia) {
139  }
140  const SUMOReal width = SUMO_const_laneWidth;
141  // @todo: this if-clause is a hack which assures that the code also works with connections of zero length, what may be possible
142  // probably, it would make sense to mark such connections and connect the incoming/outgoing streets directly in such cases.
143  if (shape.length() != 0) {
144  shape.move2side(-width / 2.);
145  } else {
146  WRITE_WARNING("Same position problem at internal edge '" + c.id + "'.");
147  }
148  device << " <road name=\"" << c.id << "\" length=\"" << shape.length() << "\" id=\"" << getID(c.id, edgeMap, edgeID) << "\" junction=\"" << getID(n->getID(), nodeMap, nodeID) << "\">\n";
149  device << " <link>\n";
150  device << " <predecessor elementType=\"road\" elementId=\"" << getID((*j)->getID(), edgeMap, edgeID) << "\"/>\n";
151  device << " <successor elementType=\"road\" elementId=\"" << getID((*k).toEdge->getID(), edgeMap, edgeID) << "\"/>\n";
152  device << " </link>\n";
153  device << " <type s=\"0\" type=\"town\"/>\n";
154  writePlanView(shape, device);
155  device << " <elevationProfile><elevation s=\"0\" a=\"0\" b=\"0\" c=\"0\" d=\"0\"/></elevationProfile>\n";
156  device << " <lateralProfile/>\n";
157  device << " <lanes>\n";
158  device << " <laneSection s=\"0\">\n";
159  writeEmptyCenterLane(device, "none", 0);
160  device << " <right>\n";
161  device << " <lane id=\"-1\" type=\"driving\" level=\"0\">\n";
162  device << " <link>\n";
163  device << " <predecessor id=\"-" << (*j)->getNumLanes() - c.fromLane << "\"/>\n";
164  device << " <successor id=\"-" << c.toEdge->getNumLanes() - c.toLane << "\"/>\n";
165  device << " </link>\n";
166  device << " <width sOffset=\"0\" a=\"" << width << "\" b=\"0\" c=\"0\" d=\"0\"/>\n";
167  device << " <roadMark sOffset=\"0\" type=\"none\" weight=\"standard\" color=\"standard\" width=\"0.13\"/>\n";
168  device << " </lane>\n";
169  device << " </right>\n";
170  device << " </laneSection>\n";
171  device << " </lanes>\n";
172  device << " <objects/>\n";
173  device << " <signals/>\n";
174  device << " </road>\n";
175  }
176  }
177  }
178 
179  // write junctions (junction)
180  for (std::map<std::string, NBNode*>::const_iterator i = nc.begin(); i != nc.end(); ++i) {
181  NBNode* n = (*i).second;
182  device << " <junction name=\"" << n->getID() << "\" id=\"" << getID(n->getID(), nodeMap, nodeID) << "\">\n";
183  unsigned int index = 0;
184  const std::vector<NBEdge*>& incoming = n->getIncomingEdges();
185  for (std::vector<NBEdge*>::const_iterator j = incoming.begin(); j != incoming.end(); ++j) {
186  const std::vector<NBEdge::Connection>& elv = (*j)->getConnections();
187  for (std::vector<NBEdge::Connection>::const_iterator k = elv.begin(); k != elv.end(); ++k) {
188  if ((*k).toEdge == 0) {
189  continue;
190  }
191  device << " <connection id=\"" << index << "\" incomingRoad=\"" << getID((*j)->getID(), edgeMap, edgeID)
192  << "\" connectingRoad=\"" << getID((*k).id, edgeMap, edgeID) << "\" contactPoint=\"start\"/>\n";
193  ++index;
194  }
195  }
196  device << " </junction>\n";
197  }
198 
199  device << "</OpenDRIVE>\n";
200  device.close();
201 }
202 
203 
204 void
206  device << " <planView>\n";
207  SUMOReal offset = 0;
208  for (unsigned int j = 0; j < shape.size() - 1; ++j) {
209  const Position& p = shape[j];
210  Line l = shape.lineAt(j);
211  SUMOReal hdg = atan2(l.p2().y() - l.p1().y(), l.p2().x() - l.p1().x());
212  device << " <geometry s=\"" << offset << "\" x=\"" << p.x() << "\" y=\"" << p.y() << "\" hdg=\"" << hdg << "\" length=\"" << l.length() << "\"><line/></geometry>\n";
213  offset += l.length();
214  }
215  device << " </planView>\n";
216 }
217 
218 
219 void
220 NWWriter_OpenDrive::writeEmptyCenterLane(OutputDevice& device, const std::string& mark, SUMOReal markWidth) {
221  device << " <center>\n";
222  device << " <lane id=\"0\" type=\"none\" level= \"0\">\n";
223  device << " <link/>\n";
224  device << " <roadMark sOffset=\"0\" type=\"" << mark << "\" weight=\"standard\" color=\"standard\" width=\"" << markWidth << "\"/>\n";
225  device << " <width sOffset=\"0\" a=\"0\" b=\"0\" c=\"0\" d=\"0\"/>\n";
226  device << " </lane>\n";
227  device << " </center>\n";
228 }
229 
230 
231 int
232 NWWriter_OpenDrive::getID(const std::string& origID, StringBijection<int>& map, int& lastID) {
233  if (map.hasString(origID)) {
234  return map.get(origID);
235  }
236  map.insert(origID, lastID++);
237  return lastID - 1;
238 }
239 
240 
241 /****************************************************************************/
242