Eclipse SUMO - Simulation of Urban MObility
Loading...
Searching...
No Matches
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-2025 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>
29#include <netbuild/NBEdge.h>
30#include <netbuild/NBEdgeCont.h>
31#include <netbuild/NBNode.h>
32#include <netbuild/NBNodeCont.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// ---------------------------------------------------------------------------
84void
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// ---------------------------------------------------------------------------
123
124
126
127
128void
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
170
171
172void
173NIImporter_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
220void
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 }
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:287
#define WRITE_ERRORF(...)
Definition MsgHandler.h:296
#define WRITE_ERROR(msg)
Definition MsgHandler.h:295
#define TL(string)
Definition MsgHandler.h:304
#define PROGRESS_DONE_MESSAGE()
Definition MsgHandler.h:291
#define PROGRESS_BEGIN_MESSAGE(msg)
Definition MsgHandler.h:290
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
GenericSAXHandler(SequentialStringBijection::Entry *tags, int terminatorTag, SequentialStringBijection::Entry *attrs, int terminatorAttr, const std::string &file, const std::string &expectedRoot="")
Constructor.
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:4503
static const double UNSPECIFIED_FRICTION
unspecified lane friction
Definition NBEdge.h:355
static const double UNSPECIFIED_WIDTH
unspecified lane width
Definition NBEdge.h:346
static const double UNSPECIFIED_OFFSET
unspecified lane offset
Definition NBEdge.h:349
void setLoadedLength(double val)
set loaded length
Definition NBEdge.cpp:4555
Instance responsible for building networks.
NBNodeCont & getNodeCont()
Returns a reference to the node container.
NBEdgeCont & getEdgeCont()
static bool transformCoordinate(Position &from, bool includeInBoundary=true, GeoConvHelper *from_srs=nullptr)
transforms loaded coordinates handles projections, offsets (using GeoConvHelper) and import of height...
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.
double myCapacityNorm
The capacity norming.
SVCPermissions computePermission(std::string modes)
NBCapacity2Lanes myCapacity2Lanes
The converter from flow to lanes.
bool myKeepEdgeLengths
Whether the loaded lengths shal be used.
bool myLanesFromCapacity
Whether the lane number shall be computed from the capacity.
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.
NBNodeCont & myNodeCont
The previously parsed nodes.
void insertEdge(const std::string &id, NBNode *fromNode, NBNode *toNode, double freeSpeed, int numLanes, double capacity, double length, SVCPermissions perm=SVCAll)
NBEdgeCont & myEdgeCont
The edge container to fill.
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;.
NBNodeCont & myNodeCont
The nodes container to fill.
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.