Eclipse SUMO - Simulation of Urban MObility
NIImporter_MATSim.cpp
Go to the documentation of this file.
1 /****************************************************************************/
2 // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
3 // Copyright (C) 2001-2024 German Aerospace Center (DLR) and others.
4 // This program and the accompanying materials are made available under the
5 // terms of the Eclipse Public License 2.0 which is available at
6 // https://www.eclipse.org/legal/epl-2.0/
7 // This Source Code may also be made available under the following Secondary
8 // Licenses when the conditions for such availability set forth in the Eclipse
9 // Public License 2.0 are satisfied: GNU General Public License, version 2
10 // or later which is available at
11 // https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
12 // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
13 /****************************************************************************/
20 // Importer for networks stored in MATSim format
21 /****************************************************************************/
22 #include <config.h>
23 #include <set>
24 #include <functional>
25 #include <sstream>
27 #include <utils/common/ToString.h>
29 #include <netbuild/NBEdge.h>
30 #include <netbuild/NBEdgeCont.h>
31 #include <netbuild/NBNode.h>
32 #include <netbuild/NBNodeCont.h>
33 #include <netbuild/NBNetBuilder.h>
40 #include <utils/xml/XMLSubSys.h>
41 #include "NILoader.h"
42 #include "NIImporter_MATSim.h"
43 
44 
45 
46 // ===========================================================================
47 // static variables
48 // ===========================================================================
55 };
56 
57 
73 
75 };
76 
77 
78 // ===========================================================================
79 // method definitions
80 // ===========================================================================
81 // ---------------------------------------------------------------------------
82 // static methods
83 // ---------------------------------------------------------------------------
84 void
86  // check whether the option is set properly and all files exist
87  if (!oc.isUsableFileList("matsim-files")) {
88  return;
89  }
90  /* Parse file(s)
91  * Each file is parsed twice: first for nodes, second for edges. */
92  const std::vector<std::string> files = oc.getStringVector("matsim-files");
93  // load nodes, first
94  NodesHandler nodesHandler(nb.getNodeCont());
95  for (const std::string& file : files) {
96  nodesHandler.setFileName(file);
97  PROGRESS_BEGIN_MESSAGE("Parsing nodes from matsim-file '" + file + "'");
98  if (!XMLSubSys::runParser(nodesHandler, file, false, false, true)) {
99  return;
100  }
102  }
103  // load edges, then
104  EdgesHandler edgesHandler(nb.getNodeCont(), nb.getEdgeCont(), oc.getBool("matsim.keep-length"),
105  oc.getBool("matsim.lanes-from-capacity"), NBCapacity2Lanes(oc.getFloat("lanes-from-capacity.norm")));
106  for (const std::string& file : files) {
107  edgesHandler.setFileName(file);
108  PROGRESS_BEGIN_MESSAGE("Parsing edges from matsim-file '" + file + "'");
109  XMLSubSys::runParser(edgesHandler, file, false, false, true);
111  }
112 }
113 
114 
115 // ---------------------------------------------------------------------------
116 // definitions of NIImporter_MATSim::NodesHandler-methods
117 // ---------------------------------------------------------------------------
119  : GenericSAXHandler(matsimTags, MATSIM_TAG_NOTHING,
120  matsimAttrs, MATSIM_ATTR_NOTHING,
121  "matsim - file"), myNodeCont(toFill) {
122 }
123 
124 
126 
127 
128 void
130  if (element != MATSIM_TAG_NODE) {
131  return;
132  }
133  // get the id, report a warning if not given or empty...
134  bool ok = true;
135  const std::string id = SUMOXMLDefinitions::makeValidID(attrs.get<std::string>(MATSIM_ATTR_ID, nullptr, ok));
136  const double x = attrs.get<double>(MATSIM_ATTR_X, id.c_str(), ok);
137  const double y = attrs.get<double>(MATSIM_ATTR_Y, id.c_str(), ok);
138  if (!ok) {
139  return;
140  }
141  Position pos(x, y);
143  WRITE_ERRORF(TL("Unable to project coordinates for node '%'."), id);
144  }
145  NBNode* node = new NBNode(id, pos);
146  if (!myNodeCont.insert(node)) {
147  delete node;
148  WRITE_ERRORF(TL("Could not add node '%'. Probably declared twice."), id);
149  }
150 }
151 
152 
153 
154 // ---------------------------------------------------------------------------
155 // definitions of NIImporter_MATSim::EdgesHandler-methods
156 // ---------------------------------------------------------------------------
158  bool keepEdgeLengths, bool lanesFromCapacity,
159  NBCapacity2Lanes capacity2Lanes)
161  matsimAttrs, MATSIM_ATTR_NOTHING, "matsim - file"),
162  myNodeCont(nc), myEdgeCont(toFill), myCapacityNorm(3600),
163  myKeepEdgeLengths(keepEdgeLengths), myLanesFromCapacity(lanesFromCapacity),
164  myCapacity2Lanes(capacity2Lanes) {
165 }
166 
167 
169 }
170 
171 
172 void
173 NIImporter_MATSim::EdgesHandler::insertEdge(const std::string& id, NBNode* fromNode, NBNode* toNode, double freeSpeed, int numLanes, double capacity, double length, SVCPermissions perm) {
174  NBEdge* edge = new NBEdge(id, fromNode, toNode, "", freeSpeed, NBEdge::UNSPECIFIED_FRICTION, numLanes, -1, NBEdge::UNSPECIFIED_WIDTH, NBEdge::UNSPECIFIED_OFFSET, LaneSpreadFunction::RIGHT);
175  edge->setParameter("capacity", toString(capacity));
176  edge->setPermissions(perm, -1);
177  if (myKeepEdgeLengths) {
178  edge->setLoadedLength(length);
179  }
180  if (!myEdgeCont.insert(edge)) {
181  delete edge;
182  WRITE_ERRORF(TL("Could not add edge '%'. Probably declared twice."), id);
183  }
184 }
185 
186 
189  // using the MATSim modes from org.matsim.api.core.v01.TransportMode
190  if (modes.size() == 0) {
191  return SVCAll;
192  }
194  for (StringTokenizer st(modes); st.hasNext();) {
195  std::string mode = st.next();
196  if (mode == "car") {
197  result |= SVC_PASSENGER;
198  } else if (mode == "bike") {
199  result |= SVC_BICYCLE;
200  } else if (mode == "motorcycle") {
201  result |= SVC_MOTORCYCLE | SVC_MOPED;
202  } else if (mode == "truck") {
203  result |= SVC_TRUCK | SVC_TRAILER;
204  } else if (mode == "pt") {
205  result |= SVC_BUS | SVC_TRAM;
206  } else if (mode == "drt" || mode == "taxi") {
207  result |= SVC_TAXI;
208  } else if (mode == "walk" || mode == "transit_walk") {
209  result |= SVC_PEDESTRIAN;
210  } else if (mode == "train") {
211  result |= SVC_RAIL_CLASSES;
212  } else if (mode == "ship") {
213  result |= SVC_SHIP;
214  }
215  }
216  return result;
217 }
218 
219 
220 void
222  const SUMOSAXAttributes& attrs) {
223  if (element == MATSIM_TAG_NETWORK) {
225  bool ok = true;
226  int capDivider = attrs.get<int>(MATSIM_ATTR_CAPDIVIDER, "network", ok);
227  if (ok) {
228  myCapacityNorm = (double)(capDivider * 3600);
229  }
230  }
231  }
232  if (element == MATSIM_TAG_LINKS) {
233  bool ok = true;
234  std::string capperiod = attrs.get<std::string>(MATSIM_ATTR_CAPPERIOD, "links", ok);
235  StringTokenizer st(capperiod, ":");
236  if (st.size() != 3) {
237  WRITE_ERROR(TL("Bogus capacity period format; requires 'hh:mm:ss'."));
238  return;
239  }
240  try {
241  int hours = StringUtils::toInt(st.next());
242  int minutes = StringUtils::toInt(st.next());
243  int seconds = StringUtils::toInt(st.next());
244  myCapacityNorm = (double)(hours * 3600 + minutes * 60 + seconds);
245  } catch (NumberFormatException&) {
246  } catch (EmptyData&) {
247  }
248  return;
249  }
250 
251  // parse "link" elements
252  if (element != MATSIM_TAG_LINK) {
253  return;
254  }
255  bool ok = true;
256  const std::string id = SUMOXMLDefinitions::makeValidID(attrs.get<std::string>(MATSIM_ATTR_ID, nullptr, ok));
257  const std::string fromNodeID = SUMOXMLDefinitions::makeValidID(attrs.get<std::string>(MATSIM_ATTR_FROM, id.c_str(), ok));
258  const std::string toNodeID = SUMOXMLDefinitions::makeValidID(attrs.get<std::string>(MATSIM_ATTR_TO, id.c_str(), ok));
259  const double length = attrs.get<double>(MATSIM_ATTR_LENGTH, id.c_str(), ok); // override computed?
260  const double freeSpeed = attrs.get<double>(MATSIM_ATTR_FREESPEED, id.c_str(), ok); //
261  const double capacity = attrs.get<double>(MATSIM_ATTR_CAPACITY, id.c_str(), ok); // override permLanes?
262  double permLanes = attrs.get<double>(MATSIM_ATTR_PERMLANES, id.c_str(), ok);
263  //bool oneWay = attrs.getOpt<bool>(MATSIM_ATTR_ONEWAY, id.c_str(), ok, true); // mandatory?
264  const std::string modes = attrs.getOpt<std::string>(MATSIM_ATTR_MODES, id.c_str(), ok, "");
265  const std::string origid = attrs.getOpt<std::string>(MATSIM_ATTR_ORIGID, id.c_str(), ok, "");
266  NBNode* fromNode = myNodeCont.retrieve(fromNodeID);
267  NBNode* toNode = myNodeCont.retrieve(toNodeID);
268  if (fromNode == nullptr) {
269  WRITE_ERRORF(TL("Could not find from-node for edge '%'."), id);
270  }
271  if (toNode == nullptr) {
272  WRITE_ERRORF(TL("Could not find to-node for edge '%'."), id);
273  }
274  if (fromNode == nullptr || toNode == nullptr) {
275  return;
276  }
277  if (myLanesFromCapacity) {
278  permLanes = myCapacity2Lanes.get(capacity);
279  }
280  if (permLanes < 0.5) {
281  WRITE_WARNINGF(TL("Ignoring edge % which has no lanes."), id);
282  return;
283  }
284  if (fromNode == toNode) {
285  // adding node and edge with a different naming scheme to keep the original edge id for easier route repair
286  NBNode* intermediate = new NBNode(id + ".0", toNode->getPosition() + Position(POSITION_EPS, POSITION_EPS));
287  if (myNodeCont.insert(intermediate)) {
288  insertEdge(id + ".0", intermediate, toNode, freeSpeed, (int)(permLanes + 0.5), capacity, length, computePermission(modes));
289  toNode = intermediate;
290  } else {
291  delete intermediate;
292  WRITE_ERRORF(TL("Could not add intermediate node to split loop edge '%'."), id);
293  }
294  }
295  insertEdge(id, fromNode, toNode, freeSpeed, (int)(permLanes + 0.5), capacity, length, computePermission(modes));
296 }
297 
298 
299 /****************************************************************************/
#define WRITE_WARNINGF(...)
Definition: MsgHandler.h:296
#define WRITE_ERRORF(...)
Definition: MsgHandler.h:305
#define WRITE_ERROR(msg)
Definition: MsgHandler.h:304
#define TL(string)
Definition: MsgHandler.h:315
#define PROGRESS_DONE_MESSAGE()
Definition: MsgHandler.h:300
#define PROGRESS_BEGIN_MESSAGE(msg)
Definition: MsgHandler.h:299
const SVCPermissions SVCAll
all VClasses are allowed
long long int SVCPermissions
bitset where each bit declares whether a certain SVC may use this edge/lane
@ SVC_SHIP
is an arbitrary ship
@ SVC_TRUCK
vehicle is a large transport vehicle
@ SVC_IGNORING
vehicles ignoring classes
@ SVC_RAIL_CLASSES
classes which drive on tracks
@ SVC_PASSENGER
vehicle is a passenger car (a "normal" car)
@ SVC_BICYCLE
vehicle is a bicycle
@ SVC_TRAILER
vehicle is a large transport vehicle
@ SVC_MOTORCYCLE
vehicle is a motorcycle
@ SVC_MOPED
vehicle is a moped
@ SVC_TRAM
vehicle is a light rail
@ SVC_TAXI
vehicle is a taxi
@ SVC_BUS
vehicle is a bus
@ SVC_PEDESTRIAN
pedestrian
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
Definition: ToString.h:46
A handler which converts occurring elements and attributes into enums.
void setFileName(const std::string &name)
Sets the current file name.
A helper class which computes the lane number from given capacity.
Storage for edges, including some functionality operating on multiple edges.
Definition: NBEdgeCont.h:59
The representation of a single edge during network building.
Definition: NBEdge.h:92
void setPermissions(SVCPermissions permissions, int lane=-1)
set allowed/disallowed classes for the given lane or for all lanes if -1 is given
Definition: NBEdge.cpp:4331
static const double UNSPECIFIED_FRICTION
unspecified lane friction
Definition: NBEdge.h:351
static const double UNSPECIFIED_WIDTH
unspecified lane width
Definition: NBEdge.h:342
static const double UNSPECIFIED_OFFSET
unspecified lane offset
Definition: NBEdge.h:345
void setLoadedLength(double val)
set loaded length
Definition: NBEdge.cpp:4383
Instance responsible for building networks.
Definition: NBNetBuilder.h:107
NBEdgeCont & getEdgeCont()
Definition: NBNetBuilder.h:139
static bool transformCoordinate(Position &from, bool includeInBoundary=true, GeoConvHelper *from_srs=nullptr)
transforms loaded coordinates handles projections, offsets (using GeoConvHelper) and import of height...
NBNodeCont & getNodeCont()
Returns a reference to the node container.
Definition: NBNetBuilder.h:144
Container for nodes during the netbuilding process.
Definition: NBNodeCont.h:57
Represents a single node (junction) during network building.
Definition: NBNode.h:66
const Position & getPosition() const
Definition: NBNode.h:260
A class which extracts MATSIM-edges from a parsed MATSIM-file.
SVCPermissions computePermission(std::string modes)
void myStartElement(int element, const SUMOSAXAttributes &attrs)
Called on the opening of a tag;.
EdgesHandler(NBNodeCont &nc, NBEdgeCont &toFill, bool keepEdgeLengths, bool lanesFromCapacity, NBCapacity2Lanes capacity2Lanes)
Constructor.
void insertEdge(const std::string &id, NBNode *fromNode, NBNode *toNode, double freeSpeed, int numLanes, double capacity, double length, SVCPermissions perm=SVCAll)
A class which extracts MATSIM-nodes from a parsed MATSIM-file.
NodesHandler(NBNodeCont &toFill)
Contructor.
void myStartElement(int element, const SUMOSAXAttributes &attrs)
Called on the opening of a tag;.
static SequentialStringBijection::Entry matsimAttrs[]
The names of MATSIM-XML attributes (for passing to GenericSAXHandler)
static void loadNetwork(const OptionsCont &oc, NBNetBuilder &nb)
Loads content of the optionally given MATSIM network files.
static SequentialStringBijection::Entry matsimTags[]
The names of MATSIM-XML elements (for passing to GenericSAXHandler)
A storage for options typed value containers)
Definition: OptionsCont.h:89
double getFloat(const std::string &name) const
Returns the double-value of the named option (only for Option_Float)
bool getBool(const std::string &name) const
Returns the boolean-value of the named option (only for Option_Bool)
const StringVector & getStringVector(const std::string &name) const
Returns the list of string-value of the named option (only for Option_StringVector)
bool isUsableFileList(const std::string &name) const
Checks whether the named option is usable as a file list (with at least a single file)
virtual void setParameter(const std::string &key, const std::string &value)
Sets a parameter.
A point in 2D or 3D with translation and scaling methods.
Definition: Position.h:37
Encapsulated SAX-Attributes.
T getOpt(int attr, const char *objectid, bool &ok, T defaultValue=T(), bool report=true) const
Tries to read given attribute assuming it is an int.
T get(int attr, const char *objectid, bool &ok, bool report=true) const
Tries to read given attribute assuming it is an int.
virtual bool hasAttribute(int id) const =0
Returns the information whether the named (by its enum-value) attribute is within the current list.
static std::string makeValidID(const std::string &value)
transform the given string into a valid id for a network element (or any other id)
bool hasNext()
returns the information whether further substrings exist
static int toInt(const std::string &sData)
converts a string into the integer value described by it by calling the char-type converter,...
static bool runParser(GenericSAXHandler &handler, const std::string &file, const bool isNet=false, const bool isRoute=false, const bool isExternal=false, const bool catchExceptions=true)
Runs the given handler on the given file; returns if everything's ok.
Definition: XMLSubSys.cpp:148