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-2023 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>
39#include <utils/xml/XMLSubSys.h>
40#include "NILoader.h"
41#include "NIImporter_MATSim.h"
42
43
44
45// ===========================================================================
46// static variables
47// ===========================================================================
54};
55
56
72
74};
75
76
77// ===========================================================================
78// method definitions
79// ===========================================================================
80// ---------------------------------------------------------------------------
81// static methods
82// ---------------------------------------------------------------------------
83void
85 // check whether the option is set properly and all files exist
86 if (!oc.isUsableFileList("matsim-files")) {
87 return;
88 }
89 /* Parse file(s)
90 * Each file is parsed twice: first for nodes, second for edges. */
91 const std::vector<std::string> files = oc.getStringVector("matsim-files");
92 // load nodes, first
93 NodesHandler nodesHandler(nb.getNodeCont());
94 for (const std::string& file : files) {
95 nodesHandler.setFileName(file);
96 PROGRESS_BEGIN_MESSAGE("Parsing nodes from matsim-file '" + file + "'");
97 if (!XMLSubSys::runParser(nodesHandler, file, false, false, true)) {
98 return;
99 }
101 }
102 // load edges, then
103 EdgesHandler edgesHandler(nb.getNodeCont(), nb.getEdgeCont(), oc.getBool("matsim.keep-length"),
104 oc.getBool("matsim.lanes-from-capacity"), NBCapacity2Lanes(oc.getFloat("lanes-from-capacity.norm")));
105 for (const std::string& file : files) {
106 edgesHandler.setFileName(file);
107 PROGRESS_BEGIN_MESSAGE("Parsing edges from matsim-file '" + file + "'");
108 XMLSubSys::runParser(edgesHandler, file, false, false, true);
110 }
111}
112
113
114// ---------------------------------------------------------------------------
115// definitions of NIImporter_MATSim::NodesHandler-methods
116// ---------------------------------------------------------------------------
118 : GenericSAXHandler(matsimTags, MATSIM_TAG_NOTHING,
119 matsimAttrs, MATSIM_ATTR_NOTHING,
120 "matsim - file"), myNodeCont(toFill) {
121}
122
123
125
126
127void
129 if (element != MATSIM_TAG_NODE) {
130 return;
131 }
132 // get the id, report a warning if not given or empty...
133 bool ok = true;
134 std::string id = attrs.get<std::string>(MATSIM_ATTR_ID, nullptr, ok);
135 double x = attrs.get<double>(MATSIM_ATTR_X, id.c_str(), ok);
136 double y = attrs.get<double>(MATSIM_ATTR_Y, id.c_str(), ok);
137 if (!ok) {
138 return;
139 }
140 Position pos(x, y);
142 WRITE_ERRORF(TL("Unable to project coordinates for node '%'."), id);
143 }
144 NBNode* node = new NBNode(id, pos);
145 if (!myNodeCont.insert(node)) {
146 delete node;
147 WRITE_ERRORF(TL("Could not add node '%'. Probably declared twice."), id);
148 }
149}
150
151
152
153// ---------------------------------------------------------------------------
154// definitions of NIImporter_MATSim::EdgesHandler-methods
155// ---------------------------------------------------------------------------
157 bool keepEdgeLengths, bool lanesFromCapacity,
158 NBCapacity2Lanes capacity2Lanes)
160 matsimAttrs, MATSIM_ATTR_NOTHING, "matsim - file"),
161 myNodeCont(nc), myEdgeCont(toFill), myCapacityNorm(3600),
162 myKeepEdgeLengths(keepEdgeLengths), myLanesFromCapacity(lanesFromCapacity),
163 myCapacity2Lanes(capacity2Lanes) {
164}
165
166
169
170
171void
172NIImporter_MATSim::EdgesHandler::insertEdge(const std::string& id, NBNode* fromNode, NBNode* toNode, double freeSpeed, int numLanes, double capacity, double length) {
173 NBEdge* edge = new NBEdge(id, fromNode, toNode, "", freeSpeed, NBEdge::UNSPECIFIED_FRICTION, numLanes, -1, NBEdge::UNSPECIFIED_WIDTH, NBEdge::UNSPECIFIED_OFFSET, LaneSpreadFunction::RIGHT);
174 edge->setParameter("capacity", toString(capacity));
175 if (myKeepEdgeLengths) {
176 edge->setLoadedLength(length);
177 }
178 if (!myEdgeCont.insert(edge)) {
179 delete edge;
180 WRITE_ERRORF(TL("Could not add edge '%'. Probably declared twice."), id);
181 }
182}
183
184
185void
187 const SUMOSAXAttributes& attrs) {
188 if (element == MATSIM_TAG_NETWORK) {
190 bool ok = true;
191 int capDivider = attrs.get<int>(MATSIM_ATTR_CAPDIVIDER, "network", ok);
192 if (ok) {
193 myCapacityNorm = (double)(capDivider * 3600);
194 }
195 }
196 }
197 if (element == MATSIM_TAG_LINKS) {
198 bool ok = true;
199 std::string capperiod = attrs.get<std::string>(MATSIM_ATTR_CAPPERIOD, "links", ok);
200 StringTokenizer st(capperiod, ":");
201 if (st.size() != 3) {
202 WRITE_ERROR(TL("Bogus capacity period format; requires 'hh:mm:ss'."));
203 return;
204 }
205 try {
206 int hours = StringUtils::toInt(st.next());
207 int minutes = StringUtils::toInt(st.next());
208 int seconds = StringUtils::toInt(st.next());
209 myCapacityNorm = (double)(hours * 3600 + minutes * 60 + seconds);
210 } catch (NumberFormatException&) {
211 } catch (EmptyData&) {
212 }
213 return;
214 }
215
216 // parse "link" elements
217 if (element != MATSIM_TAG_LINK) {
218 return;
219 }
220 bool ok = true;
221 std::string id = attrs.get<std::string>(MATSIM_ATTR_ID, nullptr, ok);
222 std::string fromNodeID = attrs.get<std::string>(MATSIM_ATTR_FROM, id.c_str(), ok);
223 std::string toNodeID = attrs.get<std::string>(MATSIM_ATTR_TO, id.c_str(), ok);
224 double length = attrs.get<double>(MATSIM_ATTR_LENGTH, id.c_str(), ok); // override computed?
225 double freeSpeed = attrs.get<double>(MATSIM_ATTR_FREESPEED, id.c_str(), ok); //
226 double capacity = attrs.get<double>(MATSIM_ATTR_CAPACITY, id.c_str(), ok); // override permLanes?
227 double permLanes = attrs.get<double>(MATSIM_ATTR_PERMLANES, id.c_str(), ok);
228 //bool oneWay = attrs.getOpt<bool>(MATSIM_ATTR_ONEWAY, id.c_str(), ok, true); // mandatory?
229 std::string modes = attrs.getOpt<std::string>(MATSIM_ATTR_MODES, id.c_str(), ok, ""); // which values?
230 std::string origid = attrs.getOpt<std::string>(MATSIM_ATTR_ORIGID, id.c_str(), ok, "");
231 NBNode* fromNode = myNodeCont.retrieve(fromNodeID);
232 NBNode* toNode = myNodeCont.retrieve(toNodeID);
233 if (fromNode == nullptr) {
234 WRITE_ERRORF(TL("Could not find from-node for edge '%'."), id);
235 }
236 if (toNode == nullptr) {
237 WRITE_ERRORF(TL("Could not find to-node for edge '%'."), id);
238 }
239 if (fromNode == nullptr || toNode == nullptr) {
240 return;
241 }
242 if (myLanesFromCapacity) {
243 permLanes = myCapacity2Lanes.get(capacity);
244 }
245 if (fromNode == toNode) {
246 // adding node and edge with a different naming scheme to keep the original edge id for easier route repair
247 NBNode* intermediate = new NBNode(id + ".0", toNode->getPosition() + Position(POSITION_EPS, POSITION_EPS));
248 if (myNodeCont.insert(intermediate)) {
249 insertEdge(id + ".0", intermediate, toNode, freeSpeed, (int)(permLanes + 0.5), capacity, length);
250 toNode = intermediate;
251 } else {
252 delete intermediate;
253 WRITE_ERRORF(TL("Could not add intermediate node to split loop edge '%'."), id);
254 }
255 }
256 insertEdge(id, fromNode, toNode, freeSpeed, (int)(permLanes + 0.5), capacity, length);
257}
258
259
260/****************************************************************************/
#define WRITE_ERRORF(...)
Definition MsgHandler.h:280
#define WRITE_ERROR(msg)
Definition MsgHandler.h:279
#define TL(string)
Definition MsgHandler.h:287
#define PROGRESS_DONE_MESSAGE()
Definition MsgHandler.h:275
#define PROGRESS_BEGIN_MESSAGE(msg)
Definition MsgHandler.h:274
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
Definition ToString.h:46
A handler which converts occuring 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
static const double UNSPECIFIED_FRICTION
unspecified lane friction
Definition NBEdge.h:350
static const double UNSPECIFIED_WIDTH
unspecified lane width
Definition NBEdge.h:341
static const double UNSPECIFIED_OFFSET
unspecified lane offset
Definition NBEdge.h:344
void setLoadedLength(double val)
set loaded length
Definition NBEdge.cpp:4247
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:258
A class which extracts MATSIM-edges from a parsed MATSIM-file.
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)
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 StringBijection< int >::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 StringBijection< int >::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 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.