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 /****************************************************************************/
8 // Exporter writing networks using the openDRIVE format
9 /****************************************************************************/
10 // SUMO, Simulation of Urban MObility; see http://sumo-sim.org/
11 // Copyright (C) 2011-2014 DLR (http://www.dlr.de/) and contributors
12 /****************************************************************************/
13 //
14 // This file is part of SUMO.
15 // SUMO is free software: you can redistribute it and/or modify
16 // it under the terms of the GNU General Public License as published by
17 // the Free Software Foundation, either version 3 of the License, or
18 // (at your option) any later version.
19 //
20 /****************************************************************************/
21 
22 
23 // ===========================================================================
24 // included modules
25 // ===========================================================================
26 #ifdef _MSC_VER
27 #include <windows_config.h>
28 #else
29 #include <config.h>
30 #endif
31 
32 #include <ctime>
33 #include "NWWriter_OpenDrive.h"
35 #include <netbuild/NBEdge.h>
36 #include <netbuild/NBEdgeCont.h>
37 #include <netbuild/NBNode.h>
38 #include <netbuild/NBNodeCont.h>
39 #include <netbuild/NBNetBuilder.h>
43 #include <utils/common/StdDefs.h>
46 
47 #ifdef CHECK_MEMORY_LEAKS
48 #include <foreign/nvwa/debug_new.h>
49 #endif // CHECK_MEMORY_LEAKS
50 
51 
52 
53 // ===========================================================================
54 // method definitions
55 // ===========================================================================
56 // ---------------------------------------------------------------------------
57 // static methods
58 // ---------------------------------------------------------------------------
59 void
61  // check whether an opendrive-file shall be generated
62  if (!oc.isSet("opendrive-output")) {
63  return;
64  }
65  // some internal mapping containers
66  int edgeID = 0;
67  int nodeID = 0;
68  StringBijection<int> edgeMap;
69  StringBijection<int> nodeMap;
70  //
71  OutputDevice& device = OutputDevice::getDevice(oc.getString("opendrive-output"));
72  device << "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n";
73  device << "<OpenDRIVE>\n";
74  time_t now = time(0);
75  std::string dstr(ctime(&now));
76  const NBNodeCont& nc = nb.getNodeCont();
77  const NBEdgeCont& ec = nb.getEdgeCont();
79  device << " <header revMajor=\"1\" revMinor=\"3\" name=\"\" version=\"1.00\" date=\"" << dstr.substr(0, dstr.length() - 1)
80  << "\" north=\"" << b.ymax() << "\" south=\"" << b.ymin() << "\" east=\"" << b.xmax() << "\" west=\"" << b.xmin()
81  << "\" maxRoad=\"" << ec.size() << "\" maxJunc=\"" << nc.size() << "\" maxPrg=\"0\"/>\n";
82  // write normal edges (road)
83  for (std::map<std::string, NBEdge*>::const_iterator i = ec.begin(); i != ec.end(); ++i) {
84  const NBEdge* e = (*i).second;
85  device << " <road name=\"" << StringUtils::escapeXML(e->getStreetName()) << "\" length=\"" << e->getLength() << "\" id=\"" << getID(e->getID(), edgeMap, edgeID) << "\" junction=\"-1\">\n";
86  device << " <link>\n";
87  device << " <predecessor elementType=\"junction\" elementId=\"" << getID(e->getFromNode()->getID(), nodeMap, nodeID) << "\"/>\n";
88  device << " <successor elementType=\"junction\" elementId=\"" << getID(e->getToNode()->getID(), nodeMap, nodeID) << "\"/>\n";
89  device << " </link>\n";
90  device << " <type s=\"0\" type=\"town\"/>\n";
91  const std::vector<NBEdge::Lane>& lanes = e->getLanes();
92  unsigned int li = (unsigned int)lanes.size() - 1;
93  PositionVector ls = e->getLaneShape(li);
94  try {
95  ls.move2side(-e->getLaneWidth(li) / 2.);
96  } catch (InvalidArgument&) {
97  // we do not write anything, as this should have been reported, already
98  }
99  writePlanView(ls, device);
100  device << " <elevationProfile><elevation s=\"0\" a=\"0\" b=\"0\" c=\"0\" d=\"0\"/></elevationProfile>\n";
101  device << " <lateralProfile/>\n";
102  device << " <lanes>\n";
103  device << " <laneSection s=\"0\">\n";
104  writeEmptyCenterLane(device, "solid", 0.13);
105  device << " <right>\n";
106  for (int j = e->getNumLanes(); --j >= 0;) {
107  device << " <lane id=\"-" << e->getNumLanes() - j << "\" type=\"driving\" level=\"0\">\n";
108  device << " <link>\n";
109  device << " <predecessor id=\"-1\"/>\n"; // internal roads have this
110  device << " <successor id=\"-1\"/>\n"; // internal roads have this
111  device << " </link>\n";
112  device << " <width sOffset=\"0\" a=\"" << e->getLaneWidth(j) << "\" b=\"0\" c=\"0\" d=\"0\"/>\n";
113  std::string markType = "broken";
114  if (j == 0) {
115  markType = "solid";
116  }
117  device << " <roadMark sOffset=\"0\" type=\"" << markType << "\" weight=\"standard\" color=\"standard\" width=\"0.13\"/>\n";
118  device << " <speed sOffset=\"0\" max=\"" << lanes[j].speed << "\"/>\n";
119  device << " </lane>\n";
120  }
121  device << " </right>\n";
122  device << " </laneSection>\n";
123  device << " </lanes>\n";
124  device << " <objects/>\n";
125  device << " <signals/>\n";
126  device << " </road>\n";
127  }
128  device << "\n";
129  // write junction-internal edges (road)
130  for (std::map<std::string, NBNode*>::const_iterator i = nc.begin(); i != nc.end(); ++i) {
131  NBNode* n = (*i).second;
132  const std::vector<NBEdge*>& incoming = (*i).second->getIncomingEdges();
133  for (std::vector<NBEdge*>::const_iterator j = incoming.begin(); j != incoming.end(); ++j) {
134  const std::vector<NBEdge::Connection>& elv = (*j)->getConnections();
135  for (std::vector<NBEdge::Connection>::const_iterator k = elv.begin(); k != elv.end(); ++k) {
136  if ((*k).toEdge == 0) {
137  continue;
138  }
139  const NBEdge::Connection& c = *k;
140  PositionVector shape = c.shape;
141  if (c.haveVia) {
142  shape.append(c.viaShape);
143  }
144  const SUMOReal width = SUMO_const_laneWidth;
145  // @todo: this if-clause is a hack which assures that the code also works with connections of zero length, what may be possible
146  // probably, it would make sense to mark such connections and connect the incoming/outgoing streets directly in such cases.
147  try {
148  shape.move2side(-width / 2.);
149  } catch (InvalidArgument&) {
150  // we do not write anything, maybe we should
151  }
152  device << " <road name=\"" << c.getInternalLaneID() << "\" length=\"" << shape.length() << "\" id=\"" << getID(c.getInternalLaneID(), edgeMap, edgeID) << "\" junction=\"" << getID(n->getID(), nodeMap, nodeID) << "\">\n";
153  device << " <link>\n";
154  device << " <predecessor elementType=\"road\" elementId=\"" << getID((*j)->getID(), edgeMap, edgeID) << "\"/>\n";
155  device << " <successor elementType=\"road\" elementId=\"" << getID((*k).toEdge->getID(), edgeMap, edgeID) << "\"/>\n";
156  device << " </link>\n";
157  device << " <type s=\"0\" type=\"town\"/>\n";
158  writePlanView(shape, device);
159  device << " <elevationProfile><elevation s=\"0\" a=\"0\" b=\"0\" c=\"0\" d=\"0\"/></elevationProfile>\n";
160  device << " <lateralProfile/>\n";
161  device << " <lanes>\n";
162  device << " <laneSection s=\"0\">\n";
163  writeEmptyCenterLane(device, "none", 0);
164  device << " <right>\n";
165  device << " <lane id=\"-1\" type=\"driving\" level=\"0\">\n";
166  device << " <link>\n";
167  device << " <predecessor id=\"-" << (*j)->getNumLanes() - c.fromLane << "\"/>\n";
168  device << " <successor id=\"-" << c.toEdge->getNumLanes() - c.toLane << "\"/>\n";
169  device << " </link>\n";
170  device << " <width sOffset=\"0\" a=\"" << width << "\" b=\"0\" c=\"0\" d=\"0\"/>\n";
171  device << " <roadMark sOffset=\"0\" type=\"none\" weight=\"standard\" color=\"standard\" width=\"0.13\"/>\n";
172  device << " </lane>\n";
173  device << " </right>\n";
174  device << " </laneSection>\n";
175  device << " </lanes>\n";
176  device << " <objects/>\n";
177  device << " <signals/>\n";
178  device << " </road>\n";
179  }
180  }
181  }
182 
183  // write junctions (junction)
184  for (std::map<std::string, NBNode*>::const_iterator i = nc.begin(); i != nc.end(); ++i) {
185  NBNode* n = (*i).second;
186  device << " <junction name=\"" << n->getID() << "\" id=\"" << getID(n->getID(), nodeMap, nodeID) << "\">\n";
187  unsigned int index = 0;
188  const std::vector<NBEdge*>& incoming = n->getIncomingEdges();
189  for (std::vector<NBEdge*>::const_iterator j = incoming.begin(); j != incoming.end(); ++j) {
190  const std::vector<NBEdge::Connection>& elv = (*j)->getConnections();
191  for (std::vector<NBEdge::Connection>::const_iterator k = elv.begin(); k != elv.end(); ++k) {
192  if ((*k).toEdge == 0) {
193  continue;
194  }
195  device << " <connection id=\"" << index << "\" incomingRoad=\"" << getID((*j)->getID(), edgeMap, edgeID)
196  << "\" connectingRoad=\"" << getID((*k).getInternalLaneID(), edgeMap, edgeID) << "\" contactPoint=\"start\"/>\n";
197  ++index;
198  }
199  }
200  device << " </junction>\n";
201  }
202 
203  device << "</OpenDRIVE>\n";
204  device.close();
205 }
206 
207 
208 void
210  device << " <planView>\n";
211  SUMOReal offset = 0;
212  for (unsigned int j = 0; j < shape.size() - 1; ++j) {
213  const Position& p = shape[j];
214  Line l = shape.lineAt(j);
215  SUMOReal hdg = atan2(l.p2().y() - l.p1().y(), l.p2().x() - l.p1().x());
216  device << " <geometry s=\"" << offset << "\" x=\"" << p.x() << "\" y=\"" << p.y() << "\" hdg=\"" << hdg << "\" length=\"" << l.length() << "\"><line/></geometry>\n";
217  offset += l.length();
218  }
219  device << " </planView>\n";
220 }
221 
222 
223 void
224 NWWriter_OpenDrive::writeEmptyCenterLane(OutputDevice& device, const std::string& mark, SUMOReal markWidth) {
225  device << " <center>\n";
226  device << " <lane id=\"0\" type=\"none\" level= \"0\">\n";
227  device << " <link/>\n";
228  device << " <roadMark sOffset=\"0\" type=\"" << mark << "\" weight=\"standard\" color=\"standard\" width=\"" << markWidth << "\"/>\n";
229  device << " <width sOffset=\"0\" a=\"0\" b=\"0\" c=\"0\" d=\"0\"/>\n";
230  device << " </lane>\n";
231  device << " </center>\n";
232 }
233 
234 
235 int
236 NWWriter_OpenDrive::getID(const std::string& origID, StringBijection<int>& map, int& lastID) {
237  if (map.hasString(origID)) {
238  return map.get(origID);
239  }
240  map.insert(origID, lastID++);
241  return lastID - 1;
242 }
243 
244 
245 /****************************************************************************/
246 
static void writePlanView(const PositionVector &shape, OutputDevice &device)
const PositionVector & getLaneShape(unsigned int i) const
Returns the shape of the nth lane.
Definition: NBEdge.cpp:489
const Position & p2() const
Definition: Line.cpp:86
const EdgeVector & getIncomingEdges() const
Returns this node's incoming edges.
Definition: NBNode.h:244
A structure which describes a connection between edges or lanes.
Definition: NBEdge.h:148
int toLane
The lane the connections yields in.
Definition: NBEdge.h:166
const SUMOReal SUMO_const_laneWidth
Definition: StdDefs.h:46
NBEdge * toEdge
The edge the connections yields in.
Definition: NBEdge.h:164
bool hasString(const std::string &str) const
SUMOReal ymin() const
Returns minimum y-coordinate.
Definition: Boundary.cpp:124
const std::vector< NBEdge::Lane > & getLanes() const
Returns the lane definitions.
Definition: NBEdge.h:503
The representation of a single edge during network building.
Definition: NBEdge.h:71
static std::string escapeXML(const std::string &orig)
Replaces the standard escapes by their XML entities.
SUMOReal xmin() const
Returns minimum x-coordinate.
Definition: Boundary.cpp:112
SUMOReal getLaneWidth() const
Returns the default width of lanes of this edge.
Definition: NBEdge.h:446
SUMOReal x() const
Returns the x-position.
Definition: Position.h:63
SUMOReal xmax() const
Returns maximum x-coordinate.
Definition: Boundary.cpp:118
A class that stores a 2D geometrical boundary.
Definition: Boundary.h:48
PositionVector shape
Definition: NBEdge.h:178
std::string getString(const std::string &name) const
Returns the string-value of the named option (only for Option_String)
const std::string & getID() const
Returns the id.
Definition: Named.h:60
void insert(const std::string str, const T key, bool checkDuplicates=true)
unsigned int size() const
Returns the number of known nodes.
Definition: NBNodeCont.h:275
Line lineAt(int pos) const
const Position & p1() const
Definition: Line.cpp:80
static void writeNetwork(const OptionsCont &oc, NBNetBuilder &nb)
Writes the network into a openDRIVE-file.
std::map< std::string, NBEdge * >::const_iterator end() const
Returns the pointer to the end of the stored edges.
Definition: NBEdgeCont.h:198
std::string getInternalLaneID() const
Definition: NBEdge.cpp:74
int fromLane
The lane the connections starts at.
Definition: NBEdge.h:162
A point in 2D or 3D with translation and scaling methods.
Definition: Position.h:46
NBEdgeCont & getEdgeCont()
Returns the edge container.
Definition: NBNetBuilder.h:154
A list of positions.
unsigned int getNumLanes() const
Returns the number of lanes.
Definition: NBEdge.h:344
Definition: Line.h:51
static void writeEmptyCenterLane(OutputDevice &device, const std::string &mark, SUMOReal markWidth)
Storage for edges, including some functionality operating on multiple edges.
Definition: NBEdgeCont.h:66
std::map< std::string, NBNode * >::const_iterator end() const
Returns the pointer to the end of the stored nodes.
Definition: NBNodeCont.h:142
const Boundary & getConvBoundary() const
Returns the converted boundary.
std::map< std::string, NBEdge * >::const_iterator begin() const
Returns the pointer to the begin of the stored edges.
Definition: NBEdgeCont.h:190
SUMOReal length() const
Returns the length.
NBNode * getToNode() const
Returns the destination node of the edge.
Definition: NBEdge.h:368
SUMOReal length() const
Definition: Line.cpp:183
PositionVector viaShape
Definition: NBEdge.h:184
NBNodeCont & getNodeCont()
Returns the node container.
Definition: NBNetBuilder.h:162
Instance responsible for building networks.
Definition: NBNetBuilder.h:113
static OutputDevice & getDevice(const std::string &name)
Returns the described OutputDevice.
SUMOReal y() const
Returns the y-position.
Definition: Position.h:68
A storage for options typed value containers)
Definition: OptionsCont.h:108
static const GeoConvHelper & getFinal()
the coordinate transformation for writing the location element and for tracking the original coordina...
Represents a single node (junction) during network building.
Definition: NBNode.h:75
T get(const std::string &str) const
void move2side(SUMOReal amount)
Static storage of an output device and its base (abstract) implementation.
Definition: OutputDevice.h:71
#define SUMOReal
Definition: config.h:215
SUMOReal ymax() const
Returns maximum y-coordinate.
Definition: Boundary.cpp:130
Container for nodes during the netbuilding process.
Definition: NBNodeCont.h:64
static int getID(const std::string &origID, StringBijection< int > &map, int &lastID)
const std::string & getStreetName() const
Returns the street name of this edge.
Definition: NBEdge.h:458
void append(const PositionVector &v)
std::map< std::string, NBNode * >::const_iterator begin() const
Returns the pointer to the begin of the stored nodes.
Definition: NBNodeCont.h:134
unsigned int size() const
Returns the number of edges.
Definition: NBEdgeCont.h:274
SUMOReal getLength() const
Returns the computed length of the edge.
Definition: NBEdge.h:403
bool isSet(const std::string &name, bool failOnNonExistant=true) const
Returns the information whether the named option is set.
NBNode * getFromNode() const
Returns the origin node of the edge.
Definition: NBEdge.h:360