SUMO - Simulation of Urban MObility
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
NWWriter_DlrNavteq.cpp
Go to the documentation of this file.
1 /****************************************************************************/
8 // Exporter writing networks using DlrNavteq (Elmar) format
9 /****************************************************************************/
10 // SUMO, Simulation of Urban MObility; see http://sumo.dlr.de/
11 // Copyright (C) 2012-2016 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 #include <algorithm>
32 #include <ctime>
33 #include <cmath>
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>
40 #include <utils/common/ToString.h>
46 #include "NWFrame.h"
47 #include "NWWriter_DlrNavteq.h"
48 
49 #ifdef CHECK_MEMORY_LEAKS
50 #include <foreign/nvwa/debug_new.h>
51 #endif // CHECK_MEMORY_LEAKS
52 
53 
54 // ---------------------------------------------------------------------------
55 // static members
56 // ---------------------------------------------------------------------------
57 const std::string NWWriter_DlrNavteq::UNDEFINED("-1");
58 
59 // ---------------------------------------------------------------------------
60 // static methods
61 // ---------------------------------------------------------------------------
62 void
64  // check whether a matsim-file shall be generated
65  if (!oc.isSet("dlr-navteq-output")) {
66  return;
67  }
71 }
72 
73 
75  time_t rawtime;
76  time(&rawtime);
77  char buffer [80];
78  strftime(buffer, 80, "on %c", localtime(&rawtime));
79  device << "# Generated " << buffer << " by " << oc.getFullName() << "\n";
80  device << "# Format matches Extraction version: V6.0 \n";
81  std::stringstream tmp;
82  oc.writeConfiguration(tmp, true, false, false);
83  tmp.seekg(std::ios_base::beg);
84  std::string line;
85  while (!tmp.eof()) {
86  std::getline(tmp, line);
87  device << "# " << line << "\n";
88  }
89  device << "#\n";
90 }
91 
92 void
94  // For "real" nodes we simply use the node id.
95  // For internal nodes (geometry vectors describing edge geometry in the parlance of this format)
96  // we use the id of the edge and do not bother with
97  // compression (each direction gets its own internal node).
98  // XXX add option for generating numerical ids in case the input network has string ids and the target process needs integers
99  OutputDevice& device = OutputDevice::getDevice(oc.getString("dlr-navteq-output") + "_nodes_unsplitted.txt");
100  writeHeader(device, oc);
101  const GeoConvHelper& gch = GeoConvHelper::getFinal();
102  const bool haveGeo = gch.usingGeoProjection();
103  const SUMOReal geoScale = pow(10.0f, haveGeo ? 5 : 2); // see NIImporter_DlrNavteq::GEO_SCALE
104  device.setPrecision(0);
105  if (!haveGeo) {
106  WRITE_WARNING("DlrNavteq node data will be written in (floating point) cartesian coordinates");
107  }
108  // write format specifier
109  device << "# NODE_ID\tIS_BETWEEN_NODE\tamount_of_geocoordinates\tx1\ty1\t[x2 y2 ... xn yn]\n";
110  // write normal nodes
111  for (std::map<std::string, NBNode*>::const_iterator i = nc.begin(); i != nc.end(); ++i) {
112  NBNode* n = (*i).second;
113  Position pos = n->getPosition();
114  gch.cartesian2geo(pos);
115  pos.mul(geoScale);
116  device << n->getID() << "\t0\t1\t" << pos.x() << "\t" << pos.y() << "\n";
117  }
118  // write "internal" nodes
119  std::vector<std::string> avoid;
120  const bool numericalIDs = oc.getBool("numerical-ids");
121  if (numericalIDs) {
122  avoid = nc.getAllNames();
123  std::vector<std::string> avoid2 = ec.getAllNames();
124  avoid.insert(avoid.end(), avoid2.begin(), avoid2.end());
125  }
126  IDSupplier idSupplier("", avoid);
127  for (std::map<std::string, NBEdge*>::const_iterator i = ec.begin(); i != ec.end(); ++i) {
128  NBEdge* e = (*i).second;
129  const PositionVector& geom = e->getGeometry();
130  if (geom.size() > 2) {
131  std::string internalNodeID = e->getID();
132  if (internalNodeID == UNDEFINED ||
133  (nc.retrieve(internalNodeID) != 0)) {
134  // need to invent a new name to avoid clashing with the id of a 'real' node or a reserved name
135  if (numericalIDs) {
136  internalNodeID = idSupplier.getNext();
137  } else {
138  internalNodeID += "_geometry";
139  }
140  }
141  device << internalNodeID << "\t1\t" << geom.size() - 2;
142  for (int ii = 1; ii < (int)geom.size() - 1; ++ii) {
143  Position pos = geom[(int)ii];
144  gch.cartesian2geo(pos);
145  pos.mul(geoScale);
146  device << "\t" << pos.x() << "\t" << pos.y();
147  }
148  device << "\n";
149  }
150  }
151  device.close();
152 }
153 
154 
155 void
157  std::map<const std::string, std::string> nameIDs;
158  OutputDevice& device = OutputDevice::getDevice(oc.getString("dlr-navteq-output") + "_links_unsplitted.txt");
159  writeHeader(device, oc);
160  // write format specifier
161  device << "# LINK_ID\tNODE_ID_FROM\tNODE_ID_TO\tBETWEEN_NODE_ID\tLENGTH\tVEHICLE_TYPE\tFORM_OF_WAY\tBRUNNEL_TYPE\tFUNCTIONAL_ROAD_CLASS\tSPEED_CATEGORY\tNUMBER_OF_LANES\tSPEED_LIMIT\tSPEED_RESTRICTION\tNAME_ID1_REGIONAL\tNAME_ID2_LOCAL\tHOUSENUMBERS_RIGHT\tHOUSENUMBERS_LEFT\tZIP_CODE\tAREA_ID\tSUBAREA_ID\tTHROUGH_TRAFFIC\tSPECIAL_RESTRICTIONS\tEXTENDED_NUMBER_OF_LANES\tISRAMP\tCONNECTION\n";
162  // write edges
163  for (std::map<std::string, NBEdge*>::const_iterator i = ec.begin(); i != ec.end(); ++i) {
164  NBEdge* e = (*i).second;
165  const int kph = speedInKph(e->getSpeed());
166  const std::string& betweenNodeID = (e->getGeometry().size() > 2) ? e->getID() : UNDEFINED;
167  std::string nameID = UNDEFINED;
168  if (oc.getBool("output.street-names")) {
169  const std::string& name = i->second->getStreetName();
170  if (name != "" && nameIDs.count(name) == 0) {
171  nameID = toString(nameIDs.size());
172  nameIDs[name] = nameID;
173  }
174  }
175  device << e->getID() << "\t"
176  << e->getFromNode()->getID() << "\t"
177  << e->getToNode()->getID() << "\t"
178  << betweenNodeID << "\t"
179  << getGraphLength(e) << "\t"
180  << getAllowedTypes(e->getPermissions()) << "\t"
181  << "3\t" // Speed Category 1-8 XXX refine this
182  << UNDEFINED << "\t" // no special brunnel type (we don't know yet)
183  << getRoadClass(e) << "\t"
184  << getSpeedCategory(kph) << "\t"
185  << getNavteqLaneCode(e->getNumLanes()) << "\t"
186  << getSpeedCategoryUpperBound(kph) << "\t"
187  << kph << "\t"
188  << nameID << "\t" // NAME_ID1_REGIONAL XXX
189  << UNDEFINED << "\t" // NAME_ID2_LOCAL XXX
190  << UNDEFINED << "\t" // housenumbers_right
191  << UNDEFINED << "\t" // housenumbers_left
192  << UNDEFINED << "\t" // ZIP_CODE
193  << UNDEFINED << "\t" // AREA_ID
194  << UNDEFINED << "\t" // SUBAREA_ID
195  << "1\t" // through_traffic (allowed)
196  << UNDEFINED << "\t" // special_restrictions
197  << UNDEFINED << "\t" // extended_number_of_lanes
198  << UNDEFINED << "\t" // isRamp
199  << "0\t" // connection (between nodes always in order)
200  << "\n";
201  }
202  if (oc.getBool("output.street-names")) {
203  OutputDevice& namesDevice = OutputDevice::getDevice(oc.getString("dlr-navteq-output") + "_names.txt");
204  writeHeader(namesDevice, oc);
205  // write format specifier
206  namesDevice << "# NAME_ID\tName\n" << nameIDs.size() << "\n";
207  for (std::map<const std::string, std::string>::const_iterator i = nameIDs.begin(); i != nameIDs.end(); ++i) {
208  namesDevice << i->second << "\t" << i->first << "\n";
209  }
210  }
211 }
212 
213 
214 std::string
216  if (permissions == SVCAll) {
217  return "100000000000";
218  }
219  std::ostringstream oss;
220  oss << "0";
221  oss << ((permissions & SVC_PASSENGER) > 0 ? 1 : 0);
222  oss << ((permissions & SVC_PASSENGER) > 0 ? 1 : 0); // residential
223  oss << ((permissions & SVC_HOV) > 0 ? 1 : 0);
224  oss << ((permissions & SVC_EMERGENCY) > 0 ? 1 : 0);
225  oss << ((permissions & SVC_TAXI) > 0 ? 1 : 0);
226  oss << ((permissions & (SVC_BUS | SVC_COACH)) > 0 ? 1 : 0);
227  oss << ((permissions & SVC_DELIVERY) > 0 ? 1 : 0);
228  oss << ((permissions & (SVC_TRUCK | SVC_TRAILER)) > 0 ? 1 : 0);
229  oss << ((permissions & SVC_MOTORCYCLE) > 0 ? 1 : 0);
230  oss << ((permissions & SVC_BICYCLE) > 0 ? 1 : 0);
231  oss << ((permissions & SVC_PEDESTRIAN) > 0 ? 1 : 0);
232  return oss.str();
233 }
234 
235 
236 int
238  // quoting the navteq manual:
239  // As a general rule, Functional Road Class assignments have no direct
240  // correlation with other road attributes like speed, controlled access, route type, etc.
241  // if the network is based on OSM, we can use the highway types for determining FRC
242  std::string type = edge->getTypeID();
243  if (StringUtils::startsWith(type, "highway.")) {
244  type = type.substr(8);
245  }
246  if (StringUtils::startsWith(type, "motorway")) {
247  return 0;
248  } else if (StringUtils::startsWith(type, "trunk")) {
249  return 1;
250  } else if (StringUtils::startsWith(type, "primary")) {
251  return 2;
252  } else if (StringUtils::startsWith(type, "secondary")) {
253  return 2;
254  } else if (StringUtils::startsWith(type, "tertiary")) {
255  return 3;
256  } else if (type == "unclassified" || type == "residential") {
257  return 3;
258  } else if (type == "living_street" || type == "road" || type == "service" || type == "track" || type == "cycleway" || type == "path" || type == "footway") {
259  return 4;
260  }
261  // as a fallback we do a simple speed / lane-count mapping anyway
262  // the resulting functional road class layers probably won't be connected as required
263  const int kph = speedInKph(edge->getSpeed());
264  if ((kph) > 100) {
265  return 0;
266  }
267  if ((kph) > 70) {
268  return 1;
269  }
270  if ((kph) > 50) {
271  return (edge->getNumLanes() > 1 ? 2 : 3);
272  }
273  if ((kph) > 30) {
274  return 3;
275  }
276  return 4;
277 }
278 
279 
280 int
282  if ((kph) > 130) {
283  return 1;
284  }
285  if ((kph) > 100) {
286  return 2;
287  }
288  if ((kph) > 90) {
289  return 3;
290  }
291  if ((kph) > 70) {
292  return 4;
293  }
294  if ((kph) > 50) {
295  return 5;
296  }
297  if ((kph) > 30) {
298  return 6;
299  }
300  if ((kph) > 10) {
301  return 7;
302  }
303  return 8;
304 }
305 
306 
307 int
309  if ((kph) > 130) {
310  return 131;
311  }
312  if ((kph) > 100) {
313  return 130;
314  }
315  if ((kph) > 90) {
316  return 100;
317  }
318  if ((kph) > 70) {
319  return 90;
320  }
321  if ((kph) > 50) {
322  return 70;
323  }
324  if ((kph) > 30) {
325  return 50;
326  }
327  if ((kph) > 10) {
328  return 30;
329  }
330  return 10;
331 }
332 
333 
334 int
336  const int code = (numLanes == 1 ? 1 :
337  (numLanes < 4 ? 2 : 3));
338  return numLanes * 10 + code;
339 }
340 
341 
342 SUMOReal
344  PositionVector geom = edge->getGeometry();
347  return geom.length();
348 }
349 
350 
351 void
353  OutputDevice& device = OutputDevice::getDevice(oc.getString("dlr-navteq-output") + "_traffic_signals.txt");
354  writeHeader(device, oc);
355  const GeoConvHelper& gch = GeoConvHelper::getFinal();
356  const bool haveGeo = gch.usingGeoProjection();
357  const SUMOReal geoScale = pow(10.0f, haveGeo ? 5 : 2); // see NIImporter_DlrNavteq::GEO_SCALE
358  device.setPrecision(0);
359  // write format specifier
360  device << "#Traffic signal related to LINK_ID and NODE_ID with location relative to driving direction.\n#column format like pointcollection.\n#DESCRIPTION->LOCATION: 1-rechts von LINK; 2-links von LINK; 3-oberhalb LINK -1-keineAngabe\n#RELATREC_ID\tPOICOL_TYPE\tDESCRIPTION\tLONGITUDE\tLATITUDE\tLINK_ID\n";
361  // write record for every edge incoming to a tls controlled node
362  for (std::map<std::string, NBNode*>::const_iterator i = nc.begin(); i != nc.end(); ++i) {
363  NBNode* n = (*i).second;
364  if (n->isTLControlled()) {
365  Position pos = n->getPosition();
366  gch.cartesian2geo(pos);
367  pos.mul(geoScale);
368  const EdgeVector& incoming = n->getIncomingEdges();
369  for (EdgeVector::const_iterator it = incoming.begin(); it != incoming.end(); ++it) {
370  NBEdge* e = *it;
371  device << e->getID() << "\t"
372  << "12\t" // POICOL_TYPE
373  << "LSA;NODEIDS#" << n->getID() << "#;LOCATION#-1#;\t"
374  << pos.x() << "\t"
375  << pos.y() << "\t"
376  << e->getID() << "\n";
377  }
378  }
379  }
380 }
381 
382 
383 /****************************************************************************/
384 
const EdgeVector & getIncomingEdges() const
Returns this node's incoming edges.
Definition: NBNode.h:240
void close()
Closes the device and removes it from the dictionary.
const std::string & getTypeID() const
get ID of type
Definition: NBEdge.h:934
void cartesian2geo(Position &cartesian) const
Converts the given cartesian (shifted) position to its geo (lat/long) representation.
std::vector< std::string > getAllNames() const
Returns all ids of known edges.
Definition: NBEdgeCont.cpp:520
static int speedInKph(SUMOReal metersPerSecond)
get edge speed rounded to kmh
static void writeHeader(OutputDevice &device, const OptionsCont &oc)
write header comments (input paramters, date, etc...)
bool isTLControlled() const
Returns whether this node is controlled by any tls.
Definition: NBNode.h:304
static int getRoadClass(NBEdge *edge)
get the navteq road class
int SVCPermissions
bool getBool(const std::string &name) const
Returns the boolean-value of the named option (only for Option_Bool)
static int getSpeedCategory(int kph)
get the navteq speed class based on the speed in km/h
The representation of a single edge during network building.
Definition: NBEdge.h:71
void setPrecision(int precision=OUTPUT_ACCURACY)
Sets the precison or resets it to default.
const std::string & getFullName() const
Definition: OptionsCont.h:656
const SVCPermissions SVCAll
SUMOReal x() const
Returns the x-position.
Definition: Position.h:63
static int getSpeedCategoryUpperBound(int kph)
get the SPEED_LIMIT as defined by elmar (upper bound of speed category)
#define WRITE_WARNING(msg)
Definition: MsgHandler.h:200
static const std::string UNDEFINED
magic value for undefined stuff
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:66
static int getNavteqLaneCode(const int numLanes)
get the lane number encoding
void push_front_noDoublePos(const Position &p)
insert in front a non double position
static void writeNodesUnsplitted(const OptionsCont &oc, NBNodeCont &nc, NBEdgeCont &ec)
Writes the nodes_unsplitted file.
const Position & getPosition() const
Returns the position of this node.
Definition: NBNode.h:228
static bool startsWith(const std::string &str, const std::string prefix)
Checks whether a given string starts with the prefix.
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 getNext()
Returns the next id.
Definition: IDSupplier.cpp:63
bool usingGeoProjection() const
Returns whether a transformation from geo to metric coordinates will be performed.
static methods for processing the coordinates conversion for the current net
Definition: GeoConvHelper.h:60
A point in 2D or 3D with translation and scaling methods.
Definition: Position.h:46
NBEdgeCont & getEdgeCont()
Returns the edge container.
Definition: NBNetBuilder.h:153
A list of positions.
int getNumLanes() const
Returns the number of lanes.
Definition: NBEdge.h:395
Storage for edges, including some functionality operating on multiple edges.
Definition: NBEdgeCont.h:66
static void writeLinksUnsplitted(const OptionsCont &oc, NBEdgeCont &ec)
Writes the links_unsplitted file.
std::vector< std::string > getAllNames() const
get all node names
std::map< std::string, NBNode * >::const_iterator end() const
Returns the pointer to the end of the stored nodes.
Definition: NBNodeCont.h:134
std::string toString(const T &t, std::streamsize accuracy=OUTPUT_ACCURACY)
Definition: ToString.h:55
static void writeNetwork(const OptionsCont &oc, NBNetBuilder &nb)
Writes the network into XML-files (nodes, edges, connections, traffic lights)
std::map< std::string, NBEdge * >::const_iterator begin() const
Returns the pointer to the begin of the stored edges.
Definition: NBEdgeCont.h:190
SVCPermissions getPermissions(int lane=-1) const
get the union of allowed classes over all lanes or for a specific lane
Definition: NBEdge.cpp:2726
static std::string getAllowedTypes(SVCPermissions permissions)
build the ascii-bit-vector for column vehicle_type
SUMOReal length() const
Returns the length.
NBNode * getToNode() const
Returns the destination node of the edge.
Definition: NBEdge.h:416
NBNodeCont & getNodeCont()
Returns the node container.
Definition: NBNetBuilder.h:161
Instance responsible for building networks.
Definition: NBNetBuilder.h:112
static OutputDevice & getDevice(const std::string &name)
Returns the described OutputDevice.
std::vector< NBEdge * > EdgeVector
Definition: NBCont.h:41
const PositionVector & getGeometry() const
Returns the geometry of the edge.
Definition: NBEdge.h:577
SUMOReal y() const
Returns the y-position.
Definition: Position.h:68
A storage for options typed value containers)
Definition: OptionsCont.h:99
void mul(SUMOReal val)
Multiplies both positions with the given value.
Definition: Position.h:99
static const GeoConvHelper & getFinal()
the coordinate transformation for writing the location element and for tracking the original coordina...
static SUMOReal getGraphLength(NBEdge *edge)
get the length of the edge when measured up to the junction center
Represents a single node (junction) during network building.
Definition: NBNode.h:74
static void writeTrafficSignals(const OptionsCont &oc, NBNodeCont &nc)
Writes the traffic_signals file.
Static storage of an output device and its base (abstract) implementation.
Definition: OutputDevice.h:71
#define SUMOReal
Definition: config.h:214
void writeConfiguration(std::ostream &os, bool filled, bool complete, bool addComments) const
Writes the configuration.
void push_back_noDoublePos(const Position &p)
insert in back a non double position
NBNode * retrieve(const std::string &id) const
Returns the node with the given name.
Definition: NBNodeCont.cpp:110
SUMOReal getSpeed() const
Returns the speed allowed on this edge.
Definition: NBEdge.h:489
Container for nodes during the netbuilding process.
Definition: NBNodeCont.h:63
std::map< std::string, NBNode * >::const_iterator begin() const
Returns the pointer to the begin of the stored nodes.
Definition: NBNodeCont.h:126
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:409