Line data Source code
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 : /****************************************************************************/
14 : /// @file MSNet.cpp
15 : /// @author Christian Roessel
16 : /// @author Daniel Krajzewicz
17 : /// @author Jakob Erdmann
18 : /// @author Clemens Honomichl
19 : /// @author Eric Nicolay
20 : /// @author Mario Krumnow
21 : /// @author Michael Behrisch
22 : /// @author Christoph Sommer
23 : /// @date Tue, 06 Mar 2001
24 : ///
25 : // The simulated network and simulation performer
26 : /****************************************************************************/
27 : #include <config.h>
28 :
29 : #ifdef HAVE_VERSION_H
30 : #include <version.h>
31 : #endif
32 :
33 : #include <string>
34 : #include <iostream>
35 : #include <sstream>
36 : #include <typeinfo>
37 : #include <algorithm>
38 : #include <cassert>
39 : #include <vector>
40 : #include <ctime>
41 :
42 : #ifdef HAVE_FOX
43 : #include <utils/common/ScopedLocker.h>
44 : #endif
45 : #include <utils/common/MsgHandler.h>
46 : #include <utils/common/ToString.h>
47 : #include <utils/common/SysUtils.h>
48 : #include <utils/common/UtilExceptions.h>
49 : #include <utils/common/WrappingCommand.h>
50 : #include <utils/common/SystemFrame.h>
51 : #include <utils/geom/GeoConvHelper.h>
52 : #include <utils/iodevices/OutputDevice_File.h>
53 : #include <utils/iodevices/OutputDevice.h>
54 : #include <utils/options/OptionsCont.h>
55 : #include <utils/options/OptionsIO.h>
56 : #include <utils/shapes/ShapeContainer.h>
57 : #include <utils/router/DijkstraRouter.h>
58 : #include <utils/router/AStarRouter.h>
59 : #include <utils/router/IntermodalRouter.h>
60 : #include <utils/router/PedestrianRouter.h>
61 : #include <utils/vehicle/SUMORouteLoaderControl.h>
62 : #include <utils/vehicle/SUMOVehicleParserHelper.h>
63 : #include <utils/xml/XMLSubSys.h>
64 : #include <traci-server/TraCIServer.h>
65 : #include <libsumo/Helper.h>
66 : #include <libsumo/Simulation.h>
67 : #include <mesosim/MELoop.h>
68 : #include <mesosim/MESegment.h>
69 : #include <microsim/output/MSDetectorControl.h>
70 : #include <microsim/MSVehicleTransfer.h>
71 : #include <microsim/devices/MSRoutingEngine.h>
72 : #include <microsim/devices/MSDevice_Vehroutes.h>
73 : #include <microsim/devices/MSDevice_Tripinfo.h>
74 : #include <microsim/devices/MSDevice_BTsender.h>
75 : #include <microsim/devices/MSDevice_SSM.h>
76 : #include <microsim/devices/MSDevice_ElecHybrid.h>
77 : #include <microsim/devices/MSDevice_ToC.h>
78 : #include <microsim/devices/MSDevice_Taxi.h>
79 : #include <microsim/output/MSBatteryExport.h>
80 : #include <microsim/output/MSChargingStationExport.h>
81 : #include <microsim/output/MSElecHybridExport.h>
82 : #include <microsim/output/MSEmissionExport.h>
83 : #include <microsim/output/MSFCDExport.h>
84 : #include <microsim/output/MSFullExport.h>
85 : #include <microsim/output/MSQueueExport.h>
86 : #include <microsim/output/MSVTKExport.h>
87 : #include <microsim/output/MSXMLRawOut.h>
88 : #include <microsim/output/MSAmitranTrajectories.h>
89 : #include <microsim/output/MSStopOut.h>
90 : #include <microsim/transportables/MSPModel.h>
91 : #include <microsim/transportables/MSPerson.h>
92 : #include <microsim/traffic_lights/MSTrafficLightLogic.h>
93 : #include <microsim/transportables/MSTransportableControl.h>
94 : #include <microsim/traffic_lights/MSRailSignal.h>
95 : #include <microsim/traffic_lights/MSRailSignalConstraint.h>
96 : #include <microsim/traffic_lights/MSRailSignalControl.h>
97 : #include <microsim/traffic_lights/MSTLLogicControl.h>
98 : #include <microsim/traffic_lights/MSDriveWay.h>
99 : #include <microsim/trigger/MSCalibrator.h>
100 : #include <microsim/trigger/MSChargingStation.h>
101 : #include <microsim/trigger/MSLaneSpeedTrigger.h>
102 : #include <microsim/trigger/MSOverheadWire.h>
103 : #include <microsim/trigger/MSTriggeredRerouter.h>
104 : #include <utils/router/FareModul.h>
105 : #include <netload/NLBuilder.h>
106 :
107 : #include "MSEdgeControl.h"
108 : #include "MSJunctionControl.h"
109 : #include "MSInsertionControl.h"
110 : #include "MSDynamicShapeUpdater.h"
111 : #include "MSEventControl.h"
112 : #include "MSEdge.h"
113 : #include "MSJunction.h"
114 : #include "MSJunctionLogic.h"
115 : #include "MSLane.h"
116 : #include "MSVehicleControl.h"
117 : #include "MSVehicleTransfer.h"
118 : #include "MSRoute.h"
119 : #include "MSGlobals.h"
120 : #include "MSEdgeWeightsStorage.h"
121 : #include "MSStateHandler.h"
122 : #include "MSFrame.h"
123 : #include "MSParkingArea.h"
124 : #include "MSStoppingPlace.h"
125 : #include "MSNet.h"
126 :
127 :
128 : // ===========================================================================
129 : // debug constants
130 : // ===========================================================================
131 : //#define DEBUG_SIMSTEP
132 :
133 :
134 : // ===========================================================================
135 : // static member definitions
136 : // ===========================================================================
137 : MSNet* MSNet::myInstance = nullptr;
138 :
139 : const std::string MSNet::STAGE_EVENTS("events");
140 : const std::string MSNet::STAGE_MOVEMENTS("move");
141 : const std::string MSNet::STAGE_LANECHANGE("laneChange");
142 : const std::string MSNet::STAGE_INSERTIONS("insertion");
143 : const std::string MSNet::STAGE_REMOTECONTROL("remoteControl");
144 :
145 : const NamedObjectCont<MSStoppingPlace*> MSNet::myEmptyStoppingPlaceCont;
146 :
147 : // ===========================================================================
148 : // static member method definitions
149 : // ===========================================================================
150 : double
151 178 : MSNet::getEffort(const MSEdge* const e, const SUMOVehicle* const v, double t) {
152 : double value;
153 178 : const MSVehicle* const veh = dynamic_cast<const MSVehicle* const>(v);
154 178 : if (veh != nullptr && veh->getWeightsStorage().retrieveExistingEffort(e, t, value)) {
155 2 : return value;
156 : }
157 176 : if (getInstance()->getWeightsStorage().retrieveExistingEffort(e, t, value)) {
158 2 : return value;
159 : }
160 : return 0;
161 : }
162 :
163 :
164 : double
165 5164417 : MSNet::getTravelTime(const MSEdge* const e, const SUMOVehicle* const v, double t) {
166 : double value;
167 5164417 : const MSVehicle* const veh = dynamic_cast<const MSVehicle* const>(v);
168 5163428 : if (veh != nullptr && veh->getWeightsStorage().retrieveExistingTravelTime(e, t, value)) {
169 317 : return value;
170 : }
171 5164100 : if (getInstance()->getWeightsStorage().retrieveExistingTravelTime(e, t, value)) {
172 155 : return value;
173 : }
174 5163945 : if (veh != nullptr && veh->getRoutingMode() == libsumo::ROUTING_MODE_AGGREGATED_CUSTOM) {
175 1755 : return MSRoutingEngine::getEffortExtra(e, v, t);
176 : }
177 5162190 : return e->getMinimumTravelTime(v);
178 : }
179 :
180 :
181 : // ---------------------------------------------------------------------------
182 : // MSNet - methods
183 : // ---------------------------------------------------------------------------
184 : MSNet*
185 4451369188 : MSNet::getInstance(void) {
186 4451369188 : if (myInstance != nullptr) {
187 4451369143 : return myInstance;
188 : }
189 90 : throw ProcessError(TL("A network was not yet constructed."));
190 : }
191 :
192 : void
193 42753 : MSNet::initStatic() {
194 42753 : if (!MSGlobals::gUseMesoSim) {
195 37375 : MSVehicle::Influencer::init();
196 : }
197 42753 : MSDriveWay::init();
198 42753 : }
199 :
200 : void
201 39793 : MSNet::cleanupStatic() {
202 39793 : if (!MSGlobals::gUseMesoSim) {
203 34511 : MSVehicle::Influencer::cleanup();
204 : }
205 39793 : }
206 :
207 :
208 42753 : MSNet::MSNet(MSVehicleControl* vc, MSEventControl* beginOfTimestepEvents,
209 : MSEventControl* endOfTimestepEvents,
210 : MSEventControl* insertionEvents,
211 42753 : ShapeContainer* shapeCont):
212 42753 : myAmInterrupted(false),
213 42753 : myVehiclesMoved(0),
214 42753 : myPersonsMoved(0),
215 42753 : myHavePermissions(false),
216 42753 : myHasInternalLinks(false),
217 42753 : myJunctionHigherSpeeds(false),
218 42753 : myHasElevation(false),
219 42753 : myHasPedestrianNetwork(false),
220 42753 : myHasBidiEdges(false),
221 42753 : myEdgeDataEndTime(-1),
222 42753 : myDynamicShapeUpdater(nullptr) {
223 42753 : if (myInstance != nullptr) {
224 0 : throw ProcessError(TL("A network was already constructed."));
225 : }
226 42753 : OptionsCont& oc = OptionsCont::getOptions();
227 42753 : myStep = string2time(oc.getString("begin"));
228 42753 : myMaxTeleports = oc.getInt("max-num-teleports");
229 42753 : myLogExecutionTime = !oc.getBool("no-duration-log");
230 42753 : myLogStepNumber = !oc.getBool("no-step-log");
231 42753 : myLogStepPeriod = oc.getInt("step-log.period");
232 171012 : myInserter = new MSInsertionControl(*vc, string2time(oc.getString("max-depart-delay")), oc.getBool("eager-insert"), oc.getInt("max-num-vehicles"),
233 171012 : string2time(oc.getString("random-depart-offset")));
234 42753 : myVehicleControl = vc;
235 42753 : myDetectorControl = new MSDetectorControl();
236 42753 : myEdges = nullptr;
237 42753 : myJunctions = nullptr;
238 42753 : myRouteLoaders = nullptr;
239 42753 : myLogics = nullptr;
240 42753 : myPersonControl = nullptr;
241 42753 : myContainerControl = nullptr;
242 42753 : myEdgeWeights = nullptr;
243 42753 : myShapeContainer = shapeCont == nullptr ? new ShapeContainer() : shapeCont;
244 :
245 42753 : myBeginOfTimestepEvents = beginOfTimestepEvents;
246 42753 : myEndOfTimestepEvents = endOfTimestepEvents;
247 42753 : myInsertionEvents = insertionEvents;
248 42753 : myLanesRTree.first = false;
249 :
250 42753 : if (MSGlobals::gUseMesoSim) {
251 10756 : MSGlobals::gMesoNet = new MELoop(string2time(oc.getString("meso-recheck")));
252 : }
253 42753 : myInstance = this;
254 42753 : initStatic();
255 42753 : }
256 :
257 :
258 : void
259 42314 : MSNet::closeBuilding(const OptionsCont& oc, MSEdgeControl* edges, MSJunctionControl* junctions,
260 : SUMORouteLoaderControl* routeLoaders,
261 : MSTLLogicControl* tlc,
262 : std::vector<SUMOTime> stateDumpTimes,
263 : std::vector<std::string> stateDumpFiles,
264 : bool hasInternalLinks,
265 : bool junctionHigherSpeeds,
266 : const MMVersion& version) {
267 42314 : myEdges = edges;
268 42314 : myJunctions = junctions;
269 42314 : myRouteLoaders = routeLoaders;
270 42314 : myLogics = tlc;
271 : // save the time the network state shall be saved at
272 42314 : myStateDumpTimes = stateDumpTimes;
273 42314 : myStateDumpFiles = stateDumpFiles;
274 42314 : myStateDumpPeriod = string2time(oc.getString("save-state.period"));
275 42314 : myStateDumpPrefix = oc.getString("save-state.prefix");
276 42314 : myStateDumpSuffix = oc.getString("save-state.suffix");
277 :
278 : // initialise performance computation
279 42314 : mySimBeginMillis = SysUtils::getCurrentMillis();
280 42314 : myTraCIMillis = 0;
281 42314 : myHasInternalLinks = hasInternalLinks;
282 42314 : myJunctionHigherSpeeds = junctionHigherSpeeds;
283 42314 : myHasElevation = checkElevation();
284 42314 : myHasPedestrianNetwork = checkWalkingarea();
285 42314 : myHasBidiEdges = checkBidiEdges();
286 : myVersion = version;
287 42314 : if ((!MSGlobals::gUsingInternalLanes || !myHasInternalLinks)
288 16153 : && MSGlobals::gWeightsSeparateTurns > 0) {
289 20 : throw ProcessError(TL("Option weights.separate-turns is only supported when simulating with internal lanes"));
290 : }
291 42304 : }
292 :
293 :
294 72134 : MSNet::~MSNet() {
295 39793 : cleanupStatic();
296 : // delete controls
297 39793 : delete myJunctions;
298 39793 : delete myDetectorControl;
299 : // delete mean data
300 39793 : delete myEdges;
301 39793 : delete myInserter;
302 39793 : myInserter = nullptr;
303 39793 : delete myLogics;
304 39793 : delete myRouteLoaders;
305 39793 : if (myPersonControl != nullptr) {
306 6891 : delete myPersonControl;
307 6891 : myPersonControl = nullptr; // just to have that clear for later cleanups
308 : }
309 39793 : if (myContainerControl != nullptr) {
310 739 : delete myContainerControl;
311 739 : myContainerControl = nullptr; // just to have that clear for later cleanups
312 : }
313 39793 : delete myVehicleControl; // must happen after deleting transportables
314 : // delete events late so that vehicles can get rid of references first
315 39793 : delete myBeginOfTimestepEvents;
316 39793 : myBeginOfTimestepEvents = nullptr;
317 39793 : delete myEndOfTimestepEvents;
318 39793 : myEndOfTimestepEvents = nullptr;
319 39793 : delete myInsertionEvents;
320 39793 : myInsertionEvents = nullptr;
321 39793 : delete myShapeContainer;
322 39793 : delete myEdgeWeights;
323 41638 : for (auto& router : myRouterTT) {
324 1845 : delete router.second;
325 : }
326 : myRouterTT.clear();
327 39804 : for (auto& router : myRouterEffort) {
328 11 : delete router.second;
329 : }
330 : myRouterEffort.clear();
331 42413 : for (auto& router : myPedestrianRouter) {
332 2620 : delete router.second;
333 : }
334 : myPedestrianRouter.clear();
335 43206 : for (auto& router : myIntermodalRouter) {
336 3413 : delete router.second;
337 : }
338 : myIntermodalRouter.clear();
339 : myLanesRTree.second.RemoveAll();
340 39793 : clearAll();
341 39793 : if (MSGlobals::gUseMesoSim) {
342 5282 : delete MSGlobals::gMesoNet;
343 : }
344 39793 : myInstance = nullptr;
345 151720 : }
346 :
347 :
348 : void
349 217 : MSNet::addRestriction(const std::string& id, const SUMOVehicleClass svc, const double speed) {
350 217 : myRestrictions[id][svc] = speed;
351 217 : }
352 :
353 :
354 : const std::map<SUMOVehicleClass, double>*
355 2156244 : MSNet::getRestrictions(const std::string& id) const {
356 : std::map<std::string, std::map<SUMOVehicleClass, double> >::const_iterator i = myRestrictions.find(id);
357 2156244 : if (i == myRestrictions.end()) {
358 : return nullptr;
359 : }
360 1094 : return &i->second;
361 : }
362 :
363 : void
364 22 : MSNet::addMesoType(const std::string& typeID, const MESegment::MesoEdgeType& edgeType) {
365 22 : myMesoEdgeTypes[typeID] = edgeType;
366 22 : }
367 :
368 : const MESegment::MesoEdgeType&
369 595587 : MSNet::getMesoType(const std::string& typeID) {
370 : if (myMesoEdgeTypes.count(typeID) == 0) {
371 : // init defaults
372 5746 : const OptionsCont& oc = OptionsCont::getOptions();
373 : MESegment::MesoEdgeType edgeType;
374 5746 : edgeType.tauff = string2time(oc.getString("meso-tauff"));
375 5746 : edgeType.taufj = string2time(oc.getString("meso-taufj"));
376 5746 : edgeType.taujf = string2time(oc.getString("meso-taujf"));
377 5746 : edgeType.taujj = string2time(oc.getString("meso-taujj"));
378 5746 : edgeType.jamThreshold = oc.getFloat("meso-jam-threshold");
379 5746 : edgeType.junctionControl = oc.getBool("meso-junction-control");
380 5746 : edgeType.tlsPenalty = oc.getFloat("meso-tls-penalty");
381 5746 : edgeType.tlsFlowPenalty = oc.getFloat("meso-tls-flow-penalty");
382 5746 : edgeType.minorPenalty = string2time(oc.getString("meso-minor-penalty"));
383 5746 : edgeType.overtaking = oc.getBool("meso-overtaking");
384 5746 : myMesoEdgeTypes[typeID] = edgeType;
385 : }
386 595587 : return myMesoEdgeTypes[typeID];
387 : }
388 :
389 :
390 : bool
391 6558563 : MSNet::hasFlow(const std::string& id) const {
392 : // inserter is deleted at the end of the simulation
393 6558563 : return myInserter != nullptr && myInserter->hasFlow(id);
394 : }
395 :
396 :
397 : MSNet::SimulationState
398 30893 : MSNet::simulate(SUMOTime start, SUMOTime stop) {
399 : // report the begin when wished
400 61786 : WRITE_MESSAGEF(TL("Simulation version % started with time: %."), VERSION_STRING, time2string(start));
401 : // the simulation loop
402 : SimulationState state = SIMSTATE_RUNNING;
403 : // state loading may have changed the start time so we need to reinit it
404 30893 : myStep = start;
405 : int numSteps = 0;
406 : bool doStepLog = false;
407 76461314 : while (state == SIMSTATE_RUNNING) {
408 76430737 : doStepLog = myLogStepNumber && (numSteps % myLogStepPeriod == 0);
409 : if (doStepLog) {
410 113 : preSimStepOutput();
411 : }
412 76430737 : simulationStep();
413 76430421 : if (doStepLog) {
414 113 : postSimStepOutput();
415 : }
416 76430421 : state = adaptToState(simulationState(stop));
417 : #ifdef DEBUG_SIMSTEP
418 : std::cout << SIMTIME << " MSNet::simulate(" << start << ", " << stop << ")"
419 : << "\n simulation state: " << getStateMessage(state)
420 : << std::endl;
421 : #endif
422 76430421 : numSteps++;
423 : }
424 30577 : if (myLogStepNumber && !doStepLog) {
425 : // ensure some output on the last step
426 16 : preSimStepOutput();
427 16 : postSimStepOutput();
428 : }
429 : // exit simulation loop
430 30577 : if (myLogStepNumber) {
431 : // start new line for final verbose output
432 20 : std::cout << "\n";
433 : }
434 30577 : closeSimulation(start, getStateMessage(state));
435 30577 : return state;
436 : }
437 :
438 :
439 : void
440 82355952 : MSNet::loadRoutes() {
441 82355952 : myRouteLoaders->loadNext(myStep);
442 82352911 : }
443 :
444 :
445 : const std::string
446 11357 : MSNet::generateStatistics(const SUMOTime start, const long now) {
447 11357 : std::ostringstream msg;
448 11357 : if (myLogExecutionTime) {
449 11066 : const long duration = now - mySimBeginMillis;
450 : // print performance notice
451 22132 : msg << "Performance:\n" << " Duration: " << elapsedMs2string(duration) << "\n";
452 11066 : if (duration != 0) {
453 10979 : if (TraCIServer::getInstance() != nullptr) {
454 4125 : msg << " TraCI-Duration: " << elapsedMs2string(myTraCIMillis) << "\n";
455 : }
456 10979 : msg << " Real time factor: " << (STEPS2TIME(myStep - start) * 1000. / (double)duration) << "\n";
457 : msg.setf(std::ios::fixed, std::ios::floatfield); // use decimal format
458 : msg.setf(std::ios::showpoint); // print decimal point
459 10979 : msg << " UPS: " << ((double)myVehiclesMoved / ((double)duration / 1000)) << "\n";
460 10979 : if (myPersonsMoved > 0) {
461 2080 : msg << " UPS-Persons: " << ((double)myPersonsMoved / ((double)duration / 1000)) << "\n";
462 : }
463 : }
464 : // print vehicle statistics
465 11066 : const std::string discardNotice = ((myVehicleControl->getLoadedVehicleNo() != myVehicleControl->getDepartedVehicleNo()) ?
466 14834 : " (Loaded: " + toString(myVehicleControl->getLoadedVehicleNo()) + ")" : "");
467 : msg << "Vehicles:\n"
468 11066 : << " Inserted: " << myVehicleControl->getDepartedVehicleNo() << discardNotice << "\n"
469 22132 : << " Running: " << myVehicleControl->getRunningVehicleNo() << "\n"
470 22132 : << " Waiting: " << myInserter->getWaitingVehicleNo() << "\n";
471 :
472 11066 : if (myVehicleControl->getTeleportCount() > 0 || myVehicleControl->getCollisionCount() > 0) {
473 : // print optional teleport statistics
474 : std::vector<std::string> reasons;
475 609 : if (myVehicleControl->getCollisionCount() > 0) {
476 632 : reasons.push_back("Collisions: " + toString(myVehicleControl->getCollisionCount()));
477 : }
478 609 : if (myVehicleControl->getTeleportsJam() > 0) {
479 300 : reasons.push_back("Jam: " + toString(myVehicleControl->getTeleportsJam()));
480 : }
481 609 : if (myVehicleControl->getTeleportsYield() > 0) {
482 186 : reasons.push_back("Yield: " + toString(myVehicleControl->getTeleportsYield()));
483 : }
484 609 : if (myVehicleControl->getTeleportsWrongLane() > 0) {
485 258 : reasons.push_back("Wrong Lane: " + toString(myVehicleControl->getTeleportsWrongLane()));
486 : }
487 1827 : msg << " Teleports: " << myVehicleControl->getTeleportCount() << " (" << joinToString(reasons, ", ") << ")\n";
488 609 : }
489 11066 : if (myVehicleControl->getEmergencyStops() > 0) {
490 53 : msg << " Emergency Stops: " << myVehicleControl->getEmergencyStops() << "\n";
491 : }
492 11066 : if (myVehicleControl->getEmergencyBrakingCount() > 0) {
493 279 : msg << " Emergency Braking: " << myVehicleControl->getEmergencyBrakingCount() << "\n";
494 : }
495 11066 : if (myPersonControl != nullptr && myPersonControl->getLoadedNumber() > 0) {
496 : msg << "Persons:\n"
497 2102 : << " Inserted: " << myPersonControl->getLoadedNumber() << "\n"
498 4204 : << " Running: " << myPersonControl->getRunningNumber() << "\n";
499 2102 : if (myPersonControl->getJammedNumber() > 0) {
500 57 : msg << " Jammed: " << myPersonControl->getJammedNumber() << "\n";
501 : }
502 2102 : if (myPersonControl->getTeleportCount() > 0) {
503 : std::vector<std::string> reasons;
504 7 : if (myPersonControl->getTeleportsAbortWait() > 0) {
505 0 : reasons.push_back("Abort Wait: " + toString(myPersonControl->getTeleportsAbortWait()));
506 : }
507 7 : if (myPersonControl->getTeleportsWrongDest() > 0) {
508 14 : reasons.push_back("Wrong Dest: " + toString(myPersonControl->getTeleportsWrongDest()));
509 : }
510 21 : msg << " Teleports: " << myPersonControl->getTeleportCount() << " (" << joinToString(reasons, ", ") << ")\n";
511 7 : }
512 : }
513 11066 : if (myContainerControl != nullptr && myContainerControl->getLoadedNumber() > 0) {
514 : msg << "Containers:\n"
515 76 : << " Inserted: " << myContainerControl->getLoadedNumber() << "\n"
516 152 : << " Running: " << myContainerControl->getRunningNumber() << "\n";
517 76 : if (myContainerControl->getJammedNumber() > 0) {
518 0 : msg << " Jammed: " << myContainerControl->getJammedNumber() << "\n";
519 : }
520 76 : if (myContainerControl->getTeleportCount() > 0) {
521 : std::vector<std::string> reasons;
522 0 : if (myContainerControl->getTeleportsAbortWait() > 0) {
523 0 : reasons.push_back("Abort Wait: " + toString(myContainerControl->getTeleportsAbortWait()));
524 : }
525 0 : if (myContainerControl->getTeleportsWrongDest() > 0) {
526 0 : reasons.push_back("Wrong Dest: " + toString(myContainerControl->getTeleportsWrongDest()));
527 : }
528 0 : msg << " Teleports: " << myContainerControl->getTeleportCount() << " (" << joinToString(reasons, ", ") << ")\n";
529 0 : }
530 : }
531 : }
532 22714 : if (OptionsCont::getOptions().getBool("duration-log.statistics")) {
533 5278 : msg << MSDevice_Tripinfo::printStatistics();
534 : }
535 : std::string result = msg.str();
536 : result.erase(result.end() - 1);
537 11357 : return result;
538 11357 : }
539 :
540 :
541 : void
542 10356 : MSNet::writeCollisions() const {
543 20712 : OutputDevice& od = OutputDevice::getDeviceByOption("collision-output");
544 10539 : for (const auto& item : myCollisions) {
545 366 : for (const auto& c : item.second) {
546 366 : od.openTag("collision");
547 366 : od.writeAttr("time", time2string(getCurrentTimeStep()));
548 183 : od.writeAttr("type", c.type);
549 183 : od.writeAttr("lane", c.lane->getID());
550 183 : od.writeAttr("pos", c.pos);
551 183 : od.writeAttr("collider", item.first);
552 183 : od.writeAttr("victim", c.victim);
553 183 : od.writeAttr("colliderType", c.colliderType);
554 183 : od.writeAttr("victimType", c.victimType);
555 183 : od.writeAttr("colliderSpeed", c.colliderSpeed);
556 183 : od.writeAttr("victimSpeed", c.victimSpeed);
557 366 : od.closeTag();
558 : }
559 : }
560 10356 : }
561 :
562 :
563 : void
564 311 : MSNet::writeStatistics(const SUMOTime start, const long now) const {
565 311 : const long duration = now - mySimBeginMillis;
566 311 : OutputDevice& od = OutputDevice::getDeviceByOption("statistic-output");
567 311 : od.openTag("performance");
568 622 : od.writeAttr("clockBegin", time2string(mySimBeginMillis));
569 622 : od.writeAttr("clockEnd", time2string(now));
570 622 : od.writeAttr("clockDuration", time2string(duration));
571 622 : od.writeAttr("traciDuration", time2string(myTraCIMillis));
572 311 : od.writeAttr("realTimeFactor", duration != 0 ? (double)(myStep - start) / (double)duration : -1);
573 311 : od.writeAttr("vehicleUpdatesPerSecond", duration != 0 ? (double)myVehiclesMoved / ((double)duration / 1000) : -1);
574 311 : od.writeAttr("personUpdatesPerSecond", duration != 0 ? (double)myPersonsMoved / ((double)duration / 1000) : -1);
575 622 : od.writeAttr("begin", time2string(start));
576 622 : od.writeAttr("end", time2string(myStep));
577 622 : od.writeAttr("duration", time2string(myStep - start));
578 311 : od.closeTag();
579 311 : od.openTag("vehicles");
580 311 : od.writeAttr("loaded", myVehicleControl->getLoadedVehicleNo());
581 311 : od.writeAttr("inserted", myVehicleControl->getDepartedVehicleNo());
582 311 : od.writeAttr("running", myVehicleControl->getRunningVehicleNo());
583 311 : od.writeAttr("waiting", myInserter->getWaitingVehicleNo());
584 311 : od.closeTag();
585 311 : od.openTag("teleports");
586 311 : od.writeAttr("total", myVehicleControl->getTeleportCount());
587 311 : od.writeAttr("jam", myVehicleControl->getTeleportsJam());
588 311 : od.writeAttr("yield", myVehicleControl->getTeleportsYield());
589 311 : od.writeAttr("wrongLane", myVehicleControl->getTeleportsWrongLane());
590 311 : od.closeTag();
591 311 : od.openTag("safety");
592 311 : od.writeAttr("collisions", myVehicleControl->getCollisionCount());
593 311 : od.writeAttr("emergencyStops", myVehicleControl->getEmergencyStops());
594 311 : od.writeAttr("emergencyBraking", myVehicleControl->getEmergencyBrakingCount());
595 311 : od.closeTag();
596 311 : od.openTag("persons");
597 315 : od.writeAttr("loaded", myPersonControl != nullptr ? myPersonControl->getLoadedNumber() : 0);
598 315 : od.writeAttr("running", myPersonControl != nullptr ? myPersonControl->getRunningNumber() : 0);
599 315 : od.writeAttr("jammed", myPersonControl != nullptr ? myPersonControl->getJammedNumber() : 0);
600 311 : od.closeTag();
601 311 : od.openTag("personTeleports");
602 315 : od.writeAttr("total", myPersonControl != nullptr ? myPersonControl->getTeleportCount() : 0);
603 315 : od.writeAttr("abortWait", myPersonControl != nullptr ? myPersonControl->getTeleportsAbortWait() : 0);
604 315 : od.writeAttr("wrongDest", myPersonControl != nullptr ? myPersonControl->getTeleportsWrongDest() : 0);
605 311 : od.closeTag();
606 469 : if (OptionsCont::getOptions().isSet("tripinfo-output") || OptionsCont::getOptions().getBool("duration-log.statistics")) {
607 262 : MSDevice_Tripinfo::writeStatistics(od);
608 : }
609 :
610 311 : }
611 :
612 :
613 : void
614 82314030 : MSNet::writeSummaryOutput() {
615 : // summary output
616 82314030 : const OptionsCont& oc = OptionsCont::getOptions();
617 82314030 : const bool hasOutput = oc.isSet("summary-output");
618 82314030 : const bool hasPersonOutput = oc.isSet("person-summary-output");
619 82314030 : if (hasOutput || hasPersonOutput) {
620 528578 : const SUMOTime period = string2time(oc.getString("summary-output.period"));
621 528578 : const SUMOTime begin = string2time(oc.getString("begin"));
622 528578 : if (period > 0 && (myStep - begin) % period != 0) {
623 : return;
624 : }
625 : }
626 522638 : if (hasOutput) {
627 517886 : OutputDevice& od = OutputDevice::getDeviceByOption("summary-output");
628 517886 : int departedVehiclesNumber = myVehicleControl->getDepartedVehicleNo();
629 517886 : const double meanWaitingTime = departedVehiclesNumber != 0 ? myVehicleControl->getTotalDepartureDelay() / (double) departedVehiclesNumber : -1.;
630 : int endedVehicleNumber = myVehicleControl->getEndedVehicleNo();
631 517886 : const double meanTravelTime = endedVehicleNumber != 0 ? myVehicleControl->getTotalTravelTime() / (double) endedVehicleNumber : -1.;
632 517886 : od.openTag("step");
633 1035772 : od.writeAttr("time", time2string(myStep));
634 517886 : od.writeAttr("loaded", myVehicleControl->getLoadedVehicleNo());
635 517886 : od.writeAttr("inserted", myVehicleControl->getDepartedVehicleNo());
636 517886 : od.writeAttr("running", myVehicleControl->getRunningVehicleNo());
637 517886 : od.writeAttr("waiting", myInserter->getWaitingVehicleNo());
638 517886 : od.writeAttr("ended", myVehicleControl->getEndedVehicleNo());
639 517886 : od.writeAttr("arrived", myVehicleControl->getArrivedVehicleNo());
640 517886 : od.writeAttr("collisions", myVehicleControl->getCollisionCount());
641 517886 : od.writeAttr("teleports", myVehicleControl->getTeleportCount());
642 517886 : od.writeAttr("halting", myVehicleControl->getHaltingVehicleNo());
643 517886 : od.writeAttr("stopped", myVehicleControl->getStoppedVehiclesCount());
644 517886 : od.writeAttr("meanWaitingTime", meanWaitingTime);
645 517886 : od.writeAttr("meanTravelTime", meanTravelTime);
646 517886 : std::pair<double, double> meanSpeed = myVehicleControl->getVehicleMeanSpeeds();
647 517886 : od.writeAttr("meanSpeed", meanSpeed.first);
648 517886 : od.writeAttr("meanSpeedRelative", meanSpeed.second);
649 517886 : if (myLogExecutionTime) {
650 466884 : od.writeAttr("duration", mySimStepDuration);
651 : }
652 1035772 : od.closeTag();
653 : }
654 82308090 : if (hasPersonOutput) {
655 4752 : OutputDevice& od = OutputDevice::getDeviceByOption("person-summary-output");
656 4752 : MSTransportableControl& pc = getPersonControl();
657 4752 : od.openTag("step");
658 9504 : od.writeAttr("time", time2string(myStep));
659 4752 : od.writeAttr("loaded", pc.getLoadedNumber());
660 4752 : od.writeAttr("inserted", pc.getDepartedNumber());
661 9504 : od.writeAttr("walking", pc.getMovingNumber());
662 4752 : od.writeAttr("waitingForRide", pc.getWaitingForVehicleNumber());
663 9504 : od.writeAttr("riding", pc.getRidingNumber());
664 9504 : od.writeAttr("stopping", pc.getWaitingUntilNumber());
665 9504 : od.writeAttr("jammed", pc.getJammedNumber());
666 9504 : od.writeAttr("ended", pc.getEndedNumber());
667 9504 : od.writeAttr("arrived", pc.getArrivedNumber());
668 4752 : od.writeAttr("teleports", pc.getTeleportCount());
669 4752 : if (myLogExecutionTime) {
670 0 : od.writeAttr("duration", mySimStepDuration);
671 : }
672 9504 : od.closeTag();
673 : }
674 : }
675 :
676 :
677 : void
678 38342 : MSNet::closeSimulation(SUMOTime start, const std::string& reason) {
679 : // report the end when wished
680 76684 : WRITE_MESSAGE(TLF("Simulation ended at time: %.", time2string(getCurrentTimeStep())));
681 38342 : if (reason != "") {
682 75846 : WRITE_MESSAGE(TL("Reason: ") + reason);
683 : }
684 38342 : myDetectorControl->close(myStep);
685 39552 : if (MSStopOut::active() && OptionsCont::getOptions().getBool("stop-output.write-unfinished")) {
686 112 : MSStopOut::getInstance()->generateOutputForUnfinished();
687 : }
688 38342 : MSDevice_Vehroutes::writePendingOutput(OptionsCont::getOptions().getBool("vehroute-output.write-unfinished"));
689 76684 : if (OptionsCont::getOptions().getBool("tripinfo-output.write-unfinished")) {
690 829 : MSDevice_Tripinfo::generateOutputForUnfinished();
691 : }
692 38426 : if (OptionsCont::getOptions().isSet("chargingstations-output") && !OptionsCont::getOptions().getBool("chargingstations-output.aggregated")) {
693 72 : writeChargingStationOutput();
694 : }
695 76684 : if (OptionsCont::getOptions().isSet("overheadwiresegments-output")) {
696 5 : writeOverheadWireSegmentOutput();
697 : }
698 76684 : if (OptionsCont::getOptions().isSet("substations-output")) {
699 5 : writeSubstationOutput();
700 : }
701 38342 : writeRailSignalBlocks();
702 38342 : const long now = SysUtils::getCurrentMillis();
703 65618 : if (myLogExecutionTime || OptionsCont::getOptions().getBool("duration-log.statistics")) {
704 22714 : WRITE_MESSAGE(generateStatistics(start, now));
705 : }
706 76684 : if (OptionsCont::getOptions().isSet("statistic-output")) {
707 311 : writeStatistics(start, now);
708 : }
709 38342 : }
710 :
711 :
712 : void
713 82316912 : MSNet::simulationStep(const bool onlyMove) {
714 82316912 : if (myStepCompletionMissing) {
715 4 : postMoveStep();
716 4 : myStepCompletionMissing = false;
717 2459 : return;
718 : }
719 : #ifdef DEBUG_SIMSTEP
720 : std::cout << SIMTIME << ": MSNet::simulationStep() called"
721 : << ", myStep = " << myStep
722 : << std::endl;
723 : #endif
724 : TraCIServer* t = TraCIServer::getInstance();
725 : int lastTraCICmd = 0;
726 82316908 : if (t != nullptr) {
727 404326 : if (myLogExecutionTime) {
728 236152 : myTraCIStepDuration = SysUtils::getCurrentMillis();
729 : }
730 404326 : lastTraCICmd = t->processCommands(myStep);
731 : #ifdef DEBUG_SIMSTEP
732 : bool loadRequested = !TraCI::getLoadArgs().empty();
733 : assert(t->getTargetTime() >= myStep || loadRequested || TraCIServer::wasClosed());
734 : #endif
735 404301 : if (myLogExecutionTime) {
736 236136 : myTraCIStepDuration = SysUtils::getCurrentMillis() - myTraCIStepDuration;
737 : }
738 404301 : if (TraCIServer::wasClosed() || !t->getLoadArgs().empty()) {
739 : return;
740 : }
741 : }
742 : #ifdef DEBUG_SIMSTEP
743 : std::cout << SIMTIME << ": TraCI target time: " << t->getTargetTime() << std::endl;
744 : #endif
745 : // execute beginOfTimestepEvents
746 82314432 : if (myLogExecutionTime) {
747 42394683 : mySimStepDuration = SysUtils::getCurrentMillis();
748 : }
749 : // simulation state output
750 82314432 : std::vector<SUMOTime>::iterator timeIt = std::find(myStateDumpTimes.begin(), myStateDumpTimes.end(), myStep);
751 82314432 : if (timeIt != myStateDumpTimes.end()) {
752 270 : const int dist = (int)distance(myStateDumpTimes.begin(), timeIt);
753 270 : MSStateHandler::saveState(myStateDumpFiles[dist], myStep);
754 : }
755 82314432 : if (myStateDumpPeriod > 0 && myStep % myStateDumpPeriod == 0) {
756 84 : std::string timeStamp = time2string(myStep);
757 : std::replace(timeStamp.begin(), timeStamp.end(), ':', '-');
758 84 : const std::string filename = myStateDumpPrefix + "_" + timeStamp + myStateDumpSuffix;
759 84 : MSStateHandler::saveState(filename, myStep);
760 84 : myPeriodicStateFiles.push_back(filename);
761 84 : int keep = OptionsCont::getOptions().getInt("save-state.period.keep");
762 84 : if (keep > 0 && (int)myPeriodicStateFiles.size() > keep) {
763 0 : std::remove(myPeriodicStateFiles.front().c_str());
764 : myPeriodicStateFiles.erase(myPeriodicStateFiles.begin());
765 : }
766 : }
767 82314432 : myBeginOfTimestepEvents->execute(myStep);
768 82314427 : if (MSRailSignalControl::hasInstance()) {
769 268232 : MSRailSignalControl::getInstance().updateSignals(myStep);
770 : }
771 : #ifdef HAVE_FOX
772 82314427 : MSRoutingEngine::waitForAll();
773 : #endif
774 82314427 : if (MSGlobals::gCheck4Accidents && !MSGlobals::gUseMesoSim) {
775 78377716 : myEdges->detectCollisions(myStep, STAGE_EVENTS);
776 : }
777 : // check whether the tls programs need to be switched
778 82314427 : myLogics->check2Switch(myStep);
779 :
780 82314427 : if (MSGlobals::gUseMesoSim) {
781 3936711 : MSGlobals::gMesoNet->simulate(myStep);
782 : } else {
783 : // assure all lanes with vehicles are 'active'
784 78377716 : myEdges->patchActiveLanes();
785 :
786 : // compute safe velocities for all vehicles for the next few lanes
787 : // also register ApproachingVehicleInformation for all links
788 78377716 : myEdges->planMovements(myStep);
789 :
790 : // register junction approaches based on planned velocities as basis for right-of-way decision
791 78377716 : myEdges->setJunctionApproaches(myStep);
792 :
793 : // decide right-of-way and execute movements
794 78377716 : myEdges->executeMovements(myStep);
795 78377711 : if (MSGlobals::gCheck4Accidents) {
796 78377711 : myEdges->detectCollisions(myStep, STAGE_MOVEMENTS);
797 : }
798 :
799 : // vehicles may change lanes
800 78377711 : myEdges->changeLanes(myStep);
801 :
802 78377711 : if (MSGlobals::gCheck4Accidents) {
803 78377711 : myEdges->detectCollisions(myStep, STAGE_LANECHANGE);
804 : }
805 : }
806 : // flush arrived meso vehicles and micro vehicles that were removed due to collision
807 82314422 : myVehicleControl->removePending();
808 82314422 : loadRoutes();
809 :
810 : // persons
811 82314406 : if (myPersonControl != nullptr && myPersonControl->hasTransportables()) {
812 4750320 : myPersonControl->checkWaiting(this, myStep);
813 : }
814 : // containers
815 82314363 : if (myContainerControl != nullptr && myContainerControl->hasTransportables()) {
816 1061723 : myContainerControl->checkWaiting(this, myStep);
817 : }
818 82314363 : if (MSRailSignalControl::hasInstance()) {
819 268232 : MSRailSignalControl::getInstance().resetWaitRelations();
820 : // preserve waitRelation from insertion for the next step
821 : }
822 : // insert vehicles
823 82314363 : myInserter->determineCandidates(myStep);
824 82314318 : myInsertionEvents->execute(myStep);
825 : #ifdef HAVE_FOX
826 82314220 : MSRoutingEngine::waitForAll();
827 : #endif
828 82314196 : myInserter->emitVehicles(myStep);
829 82314054 : if (MSGlobals::gCheck4Accidents && !MSGlobals::gUseMesoSim) {
830 : //myEdges->patchActiveLanes(); // @note required to detect collisions on lanes that were empty before insertion. wasteful?
831 78377444 : myEdges->detectCollisions(myStep, STAGE_INSERTIONS);
832 : }
833 82314054 : MSVehicleTransfer::getInstance()->checkInsertions(myStep);
834 :
835 : // execute endOfTimestepEvents
836 82314054 : myEndOfTimestepEvents->execute(myStep);
837 :
838 82314045 : if (myLogExecutionTime) {
839 42394521 : myTraCIStepDuration -= SysUtils::getCurrentMillis();
840 : }
841 82314045 : if (onlyMove) {
842 4 : myStepCompletionMissing = true;
843 4 : return;
844 : }
845 82314041 : if (t != nullptr && lastTraCICmd == libsumo::CMD_EXECUTEMOVE) {
846 6 : t->processCommands(myStep, true);
847 : }
848 82314041 : postMoveStep();
849 : }
850 :
851 :
852 : void
853 82314045 : MSNet::postMoveStep() {
854 82314045 : const int numControlled = libsumo::Helper::postProcessRemoteControl();
855 82314045 : if (numControlled > 0 && MSGlobals::gCheck4Accidents) {
856 10071 : myEdges->detectCollisions(myStep, STAGE_REMOTECONTROL);
857 : }
858 82314045 : if (myLogExecutionTime) {
859 42394521 : myTraCIStepDuration += SysUtils::getCurrentMillis();
860 42394521 : myTraCIMillis += myTraCIStepDuration;
861 : }
862 82314045 : if (MSGlobals::gCheck4Accidents && !MSGlobals::gUseMesoSim) {
863 : // collisions from the previous step were kept to avoid duplicate
864 : // warnings. we must remove them now to ensure correct output.
865 78377439 : removeOutdatedCollisions();
866 : }
867 : // update and write (if needed) detector values
868 82314045 : mySimStepDuration = SysUtils::getCurrentMillis() - mySimStepDuration;
869 82314045 : writeOutput();
870 :
871 82314029 : if (myLogExecutionTime) {
872 42394521 : myVehiclesMoved += myVehicleControl->getRunningVehicleNo();
873 42394521 : if (myPersonControl != nullptr) {
874 2532473 : myPersonsMoved += myPersonControl->getRunningNumber();
875 : }
876 : }
877 82314029 : myStep += DELTA_T;
878 82314029 : }
879 :
880 :
881 : MSNet::SimulationState
882 82240521 : MSNet::simulationState(SUMOTime stopTime) const {
883 82240521 : if (TraCIServer::wasClosed()) {
884 : return SIMSTATE_CONNECTION_CLOSED;
885 : }
886 82237990 : if (TraCIServer::getInstance() != nullptr && !TraCIServer::getInstance()->getLoadArgs().empty()) {
887 : return SIMSTATE_LOADING;
888 : }
889 82237977 : if ((stopTime < 0 || myStep > stopTime) && TraCIServer::getInstance() == nullptr && (stopTime > 0 || myStep > myEdgeDataEndTime)) {
890 44337301 : if ((myVehicleControl->getActiveVehicleCount() == 0)
891 3874150 : && (myInserter->getPendingFlowCount() == 0)
892 1143310 : && (myPersonControl == nullptr || !myPersonControl->hasNonWaiting())
893 148084 : && (myContainerControl == nullptr || !myContainerControl->hasNonWaiting())
894 44378537 : && !MSDevice_Taxi::hasServableReservations()) {
895 : return SIMSTATE_NO_FURTHER_VEHICLES;
896 : }
897 : }
898 82201583 : if (stopTime >= 0 && myStep >= stopTime) {
899 : return SIMSTATE_END_STEP_REACHED;
900 : }
901 82177452 : if (myMaxTeleports >= 0 && myVehicleControl->getTeleportCount() > myMaxTeleports) {
902 : return SIMSTATE_TOO_MANY_TELEPORTS;
903 : }
904 82177444 : if (myAmInterrupted) {
905 10 : return SIMSTATE_INTERRUPTED;
906 : }
907 : return SIMSTATE_RUNNING;
908 : }
909 :
910 :
911 : MSNet::SimulationState
912 82233320 : MSNet::adaptToState(MSNet::SimulationState state, const bool isLibsumo) const {
913 82233320 : if (state == SIMSTATE_LOADING) {
914 13 : OptionsIO::setArgs(TraCIServer::getInstance()->getLoadArgs());
915 : TraCIServer::getInstance()->getLoadArgs().clear();
916 82233307 : } else if (state != SIMSTATE_RUNNING && ((TraCIServer::getInstance() != nullptr && !TraCIServer::wasClosed()) || isLibsumo)) {
917 : // overrides SIMSTATE_END_STEP_REACHED, e.g. (TraCI / Libsumo ignore SUMO's --end option)
918 19277 : return SIMSTATE_RUNNING;
919 82214030 : } else if (state == SIMSTATE_NO_FURTHER_VEHICLES) {
920 19907 : if (myPersonControl != nullptr) {
921 3552 : myPersonControl->abortAnyWaitingForVehicle();
922 : }
923 19907 : if (myContainerControl != nullptr) {
924 367 : myContainerControl->abortAnyWaitingForVehicle();
925 : }
926 19907 : myVehicleControl->abortWaiting();
927 : }
928 : return state;
929 : }
930 :
931 :
932 : std::string
933 37778 : MSNet::getStateMessage(MSNet::SimulationState state) {
934 37778 : switch (state) {
935 : case MSNet::SIMSTATE_RUNNING:
936 419 : return "";
937 : case MSNet::SIMSTATE_END_STEP_REACHED:
938 14658 : return TL("The final simulation step has been reached.");
939 : case MSNet::SIMSTATE_NO_FURTHER_VEHICLES:
940 20234 : return TL("All vehicles have left the simulation.");
941 : case MSNet::SIMSTATE_CONNECTION_CLOSED:
942 2438 : return TL("TraCI requested termination.");
943 : case MSNet::SIMSTATE_ERROR_IN_SIM:
944 0 : return TL("An error occurred (see log).");
945 : case MSNet::SIMSTATE_INTERRUPTED:
946 10 : return TL("Interrupted.");
947 : case MSNet::SIMSTATE_TOO_MANY_TELEPORTS:
948 6 : return TL("Too many teleports.");
949 : case MSNet::SIMSTATE_LOADING:
950 13 : return TL("TraCI issued load command.");
951 : default:
952 0 : return TL("Unknown reason.");
953 : }
954 : }
955 :
956 :
957 : void
958 40044 : MSNet::clearAll() {
959 : // clear container
960 40044 : MSEdge::clear();
961 40044 : MSLane::clear();
962 40044 : MSRoute::clear();
963 40044 : delete MSVehicleTransfer::getInstance();
964 40044 : MSDevice::cleanupAll();
965 40044 : MSCalibrator::cleanup();
966 80565 : while (!MSLaneSpeedTrigger::getInstances().empty()) {
967 477 : delete MSLaneSpeedTrigger::getInstances().begin()->second;
968 : }
969 43430 : while (!MSTriggeredRerouter::getInstances().empty()) {
970 3386 : delete MSTriggeredRerouter::getInstances().begin()->second;
971 : }
972 40044 : MSDevice_BTsender::cleanup();
973 40044 : MSDevice_SSM::cleanup();
974 40044 : MSDevice_ToC::cleanup();
975 40044 : MSStopOut::cleanup();
976 40044 : MSRailSignalConstraint::cleanup();
977 40044 : MSRailSignalControl::cleanup();
978 40044 : MSDriveWay::cleanup();
979 : TraCIServer* t = TraCIServer::getInstance();
980 40044 : if (t != nullptr) {
981 2478 : t->cleanup();
982 : }
983 40044 : libsumo::Helper::cleanup();
984 40044 : OutputDevice::closeAll(true);
985 40044 : }
986 :
987 :
988 : void
989 186 : MSNet::clearState(const SUMOTime step, bool quickReload) {
990 186 : MSGlobals::gClearState = true;
991 186 : if (MSGlobals::gUseMesoSim) {
992 2 : MSGlobals::gMesoNet->clearState();
993 259 : for (MSEdge* const edge : MSEdge::getAllEdges()) {
994 534 : for (MESegment* s = MSGlobals::gMesoNet->getSegmentForEdge(*edge); s != nullptr; s = s->getNextSegment()) {
995 277 : s->clearState();
996 : }
997 : }
998 : } else {
999 8368 : for (MSEdge* const edge : MSEdge::getAllEdges()) {
1000 18264 : for (MSLane* const lane : edge->getLanes()) {
1001 10080 : lane->getVehiclesSecure();
1002 10080 : lane->clearState();
1003 10080 : lane->releaseVehicles();
1004 : }
1005 8184 : edge->clearState();
1006 : }
1007 : }
1008 186 : myInserter->clearState();
1009 : // detectors may still reference persons/vehicles
1010 186 : myDetectorControl->updateDetectors(myStep);
1011 186 : myDetectorControl->writeOutput(myStep, true);
1012 186 : myDetectorControl->clearState(step);
1013 :
1014 186 : if (myPersonControl != nullptr) {
1015 25 : myPersonControl->clearState();
1016 : }
1017 186 : if (myContainerControl != nullptr) {
1018 0 : myContainerControl->clearState();
1019 : }
1020 : // delete vtypes after transportables have removed their types
1021 186 : myVehicleControl->clearState(true);
1022 186 : MSVehicleTransfer::getInstance()->clearState();
1023 186 : myLogics->clearState(step, quickReload);
1024 : // delete all routes after vehicles and detector output is done
1025 186 : MSRoute::dict_clearState();
1026 236 : for (auto& item : myStoppingPlaces) {
1027 100 : for (auto& item2 : item.second) {
1028 50 : item2.second->clearState();
1029 : }
1030 : }
1031 186 : myShapeContainer->clearState();
1032 186 : myBeginOfTimestepEvents->clearState(myStep, step);
1033 186 : myEndOfTimestepEvents->clearState(myStep, step);
1034 186 : myInsertionEvents->clearState(myStep, step);
1035 186 : MSRailSignalControl::clearState();
1036 186 : MSDriveWay::clearState();
1037 186 : myStep = step;
1038 186 : MSGlobals::gClearState = false;
1039 186 : }
1040 :
1041 :
1042 : void
1043 82314045 : MSNet::writeOutput() {
1044 : // update detector values
1045 82314045 : myDetectorControl->updateDetectors(myStep);
1046 82314036 : const OptionsCont& oc = OptionsCont::getOptions();
1047 :
1048 : // check state dumps
1049 164628072 : if (oc.isSet("netstate-dump")) {
1050 303234 : MSXMLRawOut::write(OutputDevice::getDeviceByOption("netstate-dump"), *myEdges, myStep,
1051 : oc.getInt("netstate-dump.precision"));
1052 : }
1053 :
1054 : // check fcd dumps
1055 164628072 : if (OptionsCont::getOptions().isSet("fcd-output")) {
1056 1539678 : MSFCDExport::write(OutputDevice::getDeviceByOption("fcd-output"), myStep, myHasElevation);
1057 : }
1058 :
1059 : // check emission dumps
1060 164628072 : if (OptionsCont::getOptions().isSet("emission-output")) {
1061 185048 : MSEmissionExport::write(OutputDevice::getDeviceByOption("emission-output"), myStep,
1062 : oc.getInt("emission-output.precision"));
1063 : }
1064 :
1065 : // battery dumps
1066 164628072 : if (OptionsCont::getOptions().isSet("battery-output")) {
1067 250270 : MSBatteryExport::write(OutputDevice::getDeviceByOption("battery-output"), myStep,
1068 : oc.getInt("battery-output.precision"));
1069 : }
1070 :
1071 : // charging station aggregated dumps
1072 82369552 : if (OptionsCont::getOptions().isSet("chargingstations-output") && OptionsCont::getOptions().getBool("chargingstations-output.aggregated")) {
1073 4648 : MSChargingStationExport::write(OutputDevice::getDeviceByOption("chargingstations-output"), myStep);
1074 : }
1075 :
1076 : // elecHybrid dumps
1077 164628072 : if (OptionsCont::getOptions().isSet("elechybrid-output")) {
1078 450 : std::string output = OptionsCont::getOptions().getString("elechybrid-output");
1079 :
1080 900 : if (oc.getBool("elechybrid-output.aggregated")) {
1081 : // build a xml file with aggregated device.elechybrid output
1082 600 : MSElecHybridExport::writeAggregated(OutputDevice::getDeviceByOption("elechybrid-output"), myStep,
1083 : oc.getInt("elechybrid-output.precision"));
1084 : } else {
1085 : // build a separate xml file for each vehicle equipped with device.elechybrid
1086 : // RICE_TODO: Does this have to be placed here in MSNet.cpp ?
1087 150 : MSVehicleControl& vc = MSNet::getInstance()->getVehicleControl();
1088 204 : for (MSVehicleControl::constVehIt it = vc.loadedVehBegin(); it != vc.loadedVehEnd(); ++it) {
1089 54 : const SUMOVehicle* veh = it->second;
1090 54 : if (!veh->isOnRoad()) {
1091 0 : continue;
1092 : }
1093 54 : if (static_cast<MSDevice_ElecHybrid*>(veh->getDevice(typeid(MSDevice_ElecHybrid))) != nullptr) {
1094 : std::string vehID = veh->getID();
1095 54 : std::string filename2 = output + "_" + vehID + ".xml";
1096 54 : OutputDevice& dev = OutputDevice::getDevice(filename2);
1097 : std::map<SumoXMLAttr, std::string> attrs;
1098 54 : attrs[SUMO_ATTR_VEHICLE] = vehID;
1099 54 : attrs[SUMO_ATTR_MAXIMUMBATTERYCAPACITY] = toString(dynamic_cast<MSDevice_ElecHybrid*>(veh->getDevice(typeid(MSDevice_ElecHybrid)))->getMaximumBatteryCapacity());
1100 54 : attrs[SUMO_ATTR_RECUPERATIONENABLE] = toString(MSGlobals::gOverheadWireRecuperation);
1101 108 : dev.writeXMLHeader("elecHybrid-export", "", attrs);
1102 108 : MSElecHybridExport::write(OutputDevice::getDevice(filename2), veh, myStep, oc.getInt("elechybrid-output.precision"));
1103 : }
1104 : }
1105 : }
1106 : }
1107 :
1108 :
1109 : // check full dumps
1110 164628072 : if (OptionsCont::getOptions().isSet("full-output")) {
1111 960 : MSGlobals::gHaveEmissions = true;
1112 1920 : MSFullExport::write(OutputDevice::getDeviceByOption("full-output"), myStep);
1113 : }
1114 :
1115 : // check queue dumps
1116 164628072 : if (OptionsCont::getOptions().isSet("queue-output")) {
1117 324414 : MSQueueExport::write(OutputDevice::getDeviceByOption("queue-output"), myStep);
1118 : }
1119 :
1120 : // check amitran dumps
1121 164628072 : if (OptionsCont::getOptions().isSet("amitran-output")) {
1122 2340 : MSAmitranTrajectories::write(OutputDevice::getDeviceByOption("amitran-output"), myStep);
1123 : }
1124 :
1125 : // check vtk dumps
1126 164628072 : if (OptionsCont::getOptions().isSet("vtk-output")) {
1127 :
1128 6 : if (MSNet::getInstance()->getVehicleControl().getRunningVehicleNo() > 0) {
1129 6 : std::string timestep = time2string(myStep);
1130 6 : timestep = timestep.substr(0, timestep.length() - 3);
1131 12 : std::string output = OptionsCont::getOptions().getString("vtk-output");
1132 12 : std::string filename = output + "_" + timestep + ".vtp";
1133 :
1134 6 : OutputDevice_File dev(filename, false);
1135 :
1136 : //build a huge mass of xml files
1137 0 : MSVTKExport::write(dev, myStep);
1138 :
1139 0 : }
1140 :
1141 : }
1142 :
1143 82314030 : writeSummaryOutput();
1144 :
1145 : // write detector values
1146 82314030 : myDetectorControl->writeOutput(myStep + DELTA_T, false);
1147 :
1148 : // write link states
1149 164628058 : if (OptionsCont::getOptions().isSet("link-output")) {
1150 3704 : OutputDevice& od = OutputDevice::getDeviceByOption("link-output");
1151 3704 : od.openTag("timestep");
1152 3704 : od.writeAttr(SUMO_ATTR_ID, STEPS2TIME(myStep));
1153 70088 : for (const MSEdge* const edge : myEdges->getEdges()) {
1154 143648 : for (const MSLane* const lane : edge->getLanes()) {
1155 158588 : for (const MSLink* const link : lane->getLinkCont()) {
1156 162648 : link->writeApproaching(od, lane->getID());
1157 : }
1158 : }
1159 : }
1160 7408 : od.closeTag();
1161 : }
1162 :
1163 : // write SSM output
1164 84552287 : for (MSDevice_SSM* dev : MSDevice_SSM::getInstances()) {
1165 2238258 : dev->updateAndWriteOutput();
1166 : }
1167 :
1168 : // write ToC output
1169 82329748 : for (MSDevice_ToC* dev : MSDevice_ToC::getInstances()) {
1170 15719 : if (dev->generatesOutput()) {
1171 15513 : dev->writeOutput();
1172 : }
1173 : }
1174 :
1175 164628058 : if (OptionsCont::getOptions().isSet("collision-output")) {
1176 10356 : writeCollisions();
1177 : }
1178 82314029 : }
1179 :
1180 :
1181 : bool
1182 0 : MSNet::logSimulationDuration() const {
1183 0 : return myLogExecutionTime;
1184 : }
1185 :
1186 :
1187 : MSTransportableControl&
1188 10338902 : MSNet::getPersonControl() {
1189 10338902 : if (myPersonControl == nullptr) {
1190 5530 : myPersonControl = new MSTransportableControl(true);
1191 : }
1192 10338881 : return *myPersonControl;
1193 : }
1194 :
1195 :
1196 : MSTransportableControl&
1197 616232 : MSNet::getContainerControl() {
1198 616232 : if (myContainerControl == nullptr) {
1199 577 : myContainerControl = new MSTransportableControl(false);
1200 : }
1201 616232 : return *myContainerControl;
1202 : }
1203 :
1204 : MSDynamicShapeUpdater*
1205 24 : MSNet::makeDynamicShapeUpdater() {
1206 24 : myDynamicShapeUpdater = std::unique_ptr<MSDynamicShapeUpdater> (new MSDynamicShapeUpdater(*myShapeContainer));
1207 24 : return myDynamicShapeUpdater.get();
1208 : }
1209 :
1210 : MSEdgeWeightsStorage&
1211 5164549 : MSNet::getWeightsStorage() {
1212 5164549 : if (myEdgeWeights == nullptr) {
1213 1503 : myEdgeWeights = new MSEdgeWeightsStorage();
1214 : }
1215 5164549 : return *myEdgeWeights;
1216 : }
1217 :
1218 :
1219 : void
1220 129 : MSNet::preSimStepOutput() const {
1221 129 : std::cout << "Step #" << time2string(myStep);
1222 129 : }
1223 :
1224 :
1225 : void
1226 129 : MSNet::postSimStepOutput() const {
1227 129 : if (myLogExecutionTime) {
1228 127 : std::ostringstream oss;
1229 : oss.setf(std::ios::fixed, std::ios::floatfield); // use decimal format
1230 : oss.setf(std::ios::showpoint); // print decimal point
1231 127 : oss << std::setprecision(gPrecision);
1232 127 : if (mySimStepDuration != 0) {
1233 74 : const double durationSec = (double)mySimStepDuration / 1000.;
1234 74 : oss << " (" << mySimStepDuration << "ms ~= "
1235 74 : << (TS / durationSec) << "*RT, ~"
1236 74 : << ((double) myVehicleControl->getRunningVehicleNo() / durationSec);
1237 : } else {
1238 53 : oss << " (0ms ?*RT. ?";
1239 : }
1240 127 : oss << "UPS, ";
1241 127 : if (TraCIServer::getInstance() != nullptr) {
1242 79 : oss << "TraCI: " << myTraCIStepDuration << "ms, ";
1243 : }
1244 127 : oss << "vehicles TOT " << myVehicleControl->getDepartedVehicleNo()
1245 254 : << " ACT " << myVehicleControl->getRunningVehicleNo()
1246 127 : << " BUF " << myInserter->getWaitingVehicleNo()
1247 127 : << ") ";
1248 254 : std::string prev = "Step #" + time2string(myStep - DELTA_T);
1249 254 : std::cout << oss.str().substr(0, 90 - prev.length());
1250 127 : }
1251 129 : std::cout << '\r';
1252 129 : }
1253 :
1254 :
1255 : void
1256 47039 : MSNet::addVehicleStateListener(VehicleStateListener* listener) {
1257 47039 : if (find(myVehicleStateListeners.begin(), myVehicleStateListeners.end(), listener) == myVehicleStateListeners.end()) {
1258 47039 : myVehicleStateListeners.push_back(listener);
1259 : }
1260 47039 : }
1261 :
1262 :
1263 : void
1264 34511 : MSNet::removeVehicleStateListener(VehicleStateListener* listener) {
1265 34511 : std::vector<VehicleStateListener*>::iterator i = std::find(myVehicleStateListeners.begin(), myVehicleStateListeners.end(), listener);
1266 34511 : if (i != myVehicleStateListeners.end()) {
1267 34511 : myVehicleStateListeners.erase(i);
1268 : }
1269 34511 : }
1270 :
1271 :
1272 : void
1273 13200515 : MSNet::informVehicleStateListener(const SUMOVehicle* const vehicle, VehicleState to, const std::string& info) {
1274 : #ifdef HAVE_FOX
1275 13200515 : ScopedLocker<> lock(myVehicleStateListenerMutex, MSGlobals::gNumThreads > 1);
1276 : #endif
1277 24626129 : for (VehicleStateListener* const listener : myVehicleStateListeners) {
1278 11425614 : listener->vehicleStateChanged(vehicle, to, info);
1279 : }
1280 13200515 : }
1281 :
1282 :
1283 : void
1284 3531 : MSNet::addTransportableStateListener(TransportableStateListener* listener) {
1285 3531 : if (find(myTransportableStateListeners.begin(), myTransportableStateListeners.end(), listener) == myTransportableStateListeners.end()) {
1286 3531 : myTransportableStateListeners.push_back(listener);
1287 : }
1288 3531 : }
1289 :
1290 :
1291 : void
1292 0 : MSNet::removeTransportableStateListener(TransportableStateListener* listener) {
1293 0 : std::vector<TransportableStateListener*>::iterator i = std::find(myTransportableStateListeners.begin(), myTransportableStateListeners.end(), listener);
1294 0 : if (i != myTransportableStateListeners.end()) {
1295 0 : myTransportableStateListeners.erase(i);
1296 : }
1297 0 : }
1298 :
1299 :
1300 : void
1301 823937 : MSNet::informTransportableStateListener(const MSTransportable* const transportable, TransportableState to, const std::string& info) {
1302 : #ifdef HAVE_FOX
1303 823937 : ScopedLocker<> lock(myTransportableStateListenerMutex, MSGlobals::gNumThreads > 1);
1304 : #endif
1305 826367 : for (TransportableStateListener* const listener : myTransportableStateListeners) {
1306 2430 : listener->transportableStateChanged(transportable, to, info);
1307 : }
1308 823937 : }
1309 :
1310 :
1311 : bool
1312 10605 : MSNet::registerCollision(const SUMOTrafficObject* collider, const SUMOTrafficObject* victim, const std::string& collisionType, const MSLane* lane, double pos) {
1313 : auto it = myCollisions.find(collider->getID());
1314 10605 : if (it != myCollisions.end()) {
1315 5314 : for (Collision& old : it->second) {
1316 5185 : if (old.victim == victim->getID()) {
1317 : // collision from previous step continues
1318 4345 : old.colliderSpeed = collider->getSpeed();
1319 4345 : old.victimSpeed = victim->getSpeed();
1320 4345 : old.type = collisionType;
1321 4345 : old.lane = lane;
1322 4345 : old.pos = pos;
1323 4345 : old.time = myStep;
1324 : return false;
1325 : }
1326 : }
1327 : }
1328 : Collision c;
1329 : c.victim = victim->getID();
1330 6260 : c.colliderType = collider->getVehicleType().getID();
1331 6260 : c.victimType = victim->getVehicleType().getID();
1332 6260 : c.colliderSpeed = collider->getSpeed();
1333 6260 : c.victimSpeed = victim->getSpeed();
1334 : c.type = collisionType;
1335 6260 : c.lane = lane;
1336 6260 : c.pos = pos;
1337 6260 : c.time = myStep;
1338 6260 : myCollisions[collider->getID()].push_back(c);
1339 : return true;
1340 6260 : }
1341 :
1342 :
1343 : void
1344 78377439 : MSNet::removeOutdatedCollisions() {
1345 78391369 : for (auto it = myCollisions.begin(); it != myCollisions.end();) {
1346 28106 : for (auto it2 = it->second.begin(); it2 != it->second.end();) {
1347 14176 : if (it2->time != myStep) {
1348 6249 : it2 = it->second.erase(it2);
1349 : } else {
1350 : it2++;
1351 : }
1352 : }
1353 13930 : if (it->second.size() == 0) {
1354 : it = myCollisions.erase(it);
1355 : } else {
1356 : it++;
1357 : }
1358 : }
1359 78377439 : }
1360 :
1361 :
1362 : bool
1363 63589 : MSNet::addStoppingPlace(const SumoXMLTag category, MSStoppingPlace* stop) {
1364 73784 : return myStoppingPlaces[category == SUMO_TAG_TRAIN_STOP ? SUMO_TAG_BUS_STOP : category].add(stop->getID(), stop);
1365 : }
1366 :
1367 :
1368 : bool
1369 8 : MSNet::addTractionSubstation(MSTractionSubstation* substation) {
1370 8 : if (find(myTractionSubstations.begin(), myTractionSubstations.end(), substation) == myTractionSubstations.end()) {
1371 8 : myTractionSubstations.push_back(substation);
1372 8 : return true;
1373 : }
1374 : return false;
1375 : }
1376 :
1377 :
1378 : MSStoppingPlace*
1379 903341 : MSNet::getStoppingPlace(const std::string& id, const SumoXMLTag category) const {
1380 : if (myStoppingPlaces.count(category) > 0) {
1381 : return myStoppingPlaces.find(category)->second.get(id);
1382 : }
1383 : return nullptr;
1384 : }
1385 :
1386 :
1387 : MSStoppingPlace*
1388 24 : MSNet::getStoppingPlace(const std::string& id) const {
1389 40 : for (SumoXMLTag category : std::vector<SumoXMLTag>({SUMO_TAG_BUS_STOP, SUMO_TAG_PARKING_AREA, SUMO_TAG_CONTAINER_STOP, SUMO_TAG_CHARGING_STATION, SUMO_TAG_OVERHEAD_WIRE_SEGMENT})) {
1390 40 : MSStoppingPlace* result = getStoppingPlace(id, category);
1391 40 : if (result != nullptr) {
1392 : return result;
1393 : }
1394 24 : }
1395 0 : return nullptr;
1396 : }
1397 :
1398 :
1399 : std::string
1400 373320 : MSNet::getStoppingPlaceID(const MSLane* lane, const double pos, const SumoXMLTag category) const {
1401 : if (myStoppingPlaces.count(category) > 0) {
1402 510258 : for (const auto& it : myStoppingPlaces.find(category)->second) {
1403 441791 : MSStoppingPlace* stop = it.second;
1404 441791 : if (&stop->getLane() == lane && stop->getBeginLanePosition() - POSITION_EPS <= pos && stop->getEndLanePosition() + POSITION_EPS >= pos) {
1405 : return stop->getID();
1406 : }
1407 : }
1408 : }
1409 338182 : return "";
1410 : }
1411 :
1412 :
1413 : const NamedObjectCont<MSStoppingPlace*>&
1414 5059 : MSNet::getStoppingPlaces(SumoXMLTag category) const {
1415 : auto it = myStoppingPlaces.find(category);
1416 5059 : if (it != myStoppingPlaces.end()) {
1417 4774 : return it->second;
1418 : } else {
1419 : return myEmptyStoppingPlaceCont;
1420 : }
1421 : }
1422 :
1423 :
1424 : void
1425 72 : MSNet::writeChargingStationOutput() const {
1426 : if (myStoppingPlaces.count(SUMO_TAG_CHARGING_STATION) > 0) {
1427 136 : OutputDevice& output = OutputDevice::getDeviceByOption("chargingstations-output");
1428 400 : for (const auto& it : myStoppingPlaces.find(SUMO_TAG_CHARGING_STATION)->second) {
1429 332 : static_cast<MSChargingStation*>(it.second)->writeChargingStationOutput(output);
1430 : }
1431 : }
1432 72 : }
1433 :
1434 :
1435 : void
1436 38342 : MSNet::writeRailSignalBlocks() const {
1437 76684 : if (OptionsCont::getOptions().isSet("railsignal-block-output")) {
1438 983 : OutputDevice& output = OutputDevice::getDeviceByOption("railsignal-block-output");
1439 3528 : for (auto tls : myLogics->getAllLogics()) {
1440 2545 : MSRailSignal* rs = dynamic_cast<MSRailSignal*>(tls);
1441 2545 : if (rs != nullptr) {
1442 2524 : rs->writeBlocks(output, false);
1443 : }
1444 983 : }
1445 983 : MSDriveWay::writeDepatureBlocks(output, false);
1446 : }
1447 76684 : if (OptionsCont::getOptions().isSet("railsignal-vehicle-output")) {
1448 75 : OutputDevice& output = OutputDevice::getDeviceByOption("railsignal-vehicle-output");
1449 326 : for (auto tls : myLogics->getAllLogics()) {
1450 251 : MSRailSignal* rs = dynamic_cast<MSRailSignal*>(tls);
1451 251 : if (rs != nullptr) {
1452 251 : rs->writeBlocks(output, true);
1453 : }
1454 75 : }
1455 75 : MSDriveWay::writeDepatureBlocks(output, true);
1456 : }
1457 38342 : }
1458 :
1459 :
1460 : void
1461 5 : MSNet::writeOverheadWireSegmentOutput() const {
1462 : if (myStoppingPlaces.count(SUMO_TAG_OVERHEAD_WIRE_SEGMENT) > 0) {
1463 10 : OutputDevice& output = OutputDevice::getDeviceByOption("overheadwiresegments-output");
1464 53 : for (const auto& it : myStoppingPlaces.find(SUMO_TAG_OVERHEAD_WIRE_SEGMENT)->second) {
1465 48 : static_cast<MSOverheadWire*>(it.second)->writeOverheadWireSegmentOutput(output);
1466 : }
1467 : }
1468 5 : }
1469 :
1470 :
1471 : void
1472 5 : MSNet::writeSubstationOutput() const {
1473 5 : if (myTractionSubstations.size() > 0) {
1474 5 : OutputDevice& output = OutputDevice::getDeviceByOption("substations-output");
1475 10 : output.setPrecision(OptionsCont::getOptions().getInt("substations-output.precision"));
1476 13 : for (auto& it : myTractionSubstations) {
1477 8 : it->writeTractionSubstationOutput(output);
1478 : }
1479 : }
1480 5 : }
1481 :
1482 :
1483 : MSTractionSubstation*
1484 19 : MSNet::findTractionSubstation(const std::string& substationId) {
1485 22 : for (std::vector<MSTractionSubstation*>::iterator it = myTractionSubstations.begin(); it != myTractionSubstations.end(); ++it) {
1486 22 : if ((*it)->getID() == substationId) {
1487 : return *it;
1488 : }
1489 : }
1490 : return nullptr;
1491 : }
1492 :
1493 :
1494 : bool
1495 0 : MSNet::existTractionSubstation(const std::string& substationId) {
1496 0 : for (std::vector<MSTractionSubstation*>::iterator it = myTractionSubstations.begin(); it != myTractionSubstations.end(); ++it) {
1497 0 : if ((*it)->getID() == substationId) {
1498 : return true;
1499 : }
1500 : }
1501 : return false;
1502 : }
1503 :
1504 :
1505 : MSVehicleRouter&
1506 55932 : MSNet::getRouterTT(const int rngIndex, const MSEdgeVector& prohibited) const {
1507 : if (myRouterTT.count(rngIndex) == 0) {
1508 1846 : const std::string routingAlgorithm = OptionsCont::getOptions().getString("routing-algorithm");
1509 1846 : if (routingAlgorithm == "dijkstra") {
1510 1620 : myRouterTT[rngIndex] = new DijkstraRouter<MSEdge, SUMOVehicle>(MSEdge::getAllEdges(), true, &MSNet::getTravelTime, nullptr, false, nullptr, true);
1511 : } else {
1512 226 : if (routingAlgorithm != "astar") {
1513 0 : WRITE_WARNINGF(TL("TraCI and Triggers cannot use routing algorithm '%'. using 'astar' instead."), routingAlgorithm);
1514 : }
1515 226 : myRouterTT[rngIndex] = new AStarRouter<MSEdge, SUMOVehicle>(MSEdge::getAllEdges(), true, &MSNet::getTravelTime, nullptr, true);
1516 : }
1517 : }
1518 55932 : myRouterTT[rngIndex]->prohibit(prohibited);
1519 55932 : return *myRouterTT[rngIndex];
1520 : }
1521 :
1522 :
1523 : MSVehicleRouter&
1524 11 : MSNet::getRouterEffort(const int rngIndex, const MSEdgeVector& prohibited) const {
1525 : if (myRouterEffort.count(rngIndex) == 0) {
1526 11 : myRouterEffort[rngIndex] = new DijkstraRouter<MSEdge, SUMOVehicle>(MSEdge::getAllEdges(), true, &MSNet::getEffort, &MSNet::getTravelTime, false, nullptr, true);
1527 : }
1528 11 : myRouterEffort[rngIndex]->prohibit(prohibited);
1529 11 : return *myRouterEffort[rngIndex];
1530 : }
1531 :
1532 :
1533 : MSPedestrianRouter&
1534 818506 : MSNet::getPedestrianRouter(const int rngIndex, const MSEdgeVector& prohibited) const {
1535 : if (myPedestrianRouter.count(rngIndex) == 0) {
1536 2620 : myPedestrianRouter[rngIndex] = new MSPedestrianRouter();
1537 : }
1538 818506 : myPedestrianRouter[rngIndex]->prohibit(prohibited);
1539 818506 : return *myPedestrianRouter[rngIndex];
1540 : }
1541 :
1542 :
1543 : MSTransportableRouter&
1544 183122 : MSNet::getIntermodalRouter(const int rngIndex, const int routingMode, const MSEdgeVector& prohibited) const {
1545 183122 : const OptionsCont& oc = OptionsCont::getOptions();
1546 183122 : const int key = rngIndex * oc.getInt("thread-rngs") + routingMode;
1547 : if (myIntermodalRouter.count(key) == 0) {
1548 3414 : const int carWalk = SUMOVehicleParserHelper::parseCarWalkTransfer(oc, MSDevice_Taxi::getTaxi() != nullptr);
1549 3414 : const std::string routingAlgorithm = OptionsCont::getOptions().getString("routing-algorithm");
1550 3414 : const double taxiWait = STEPS2TIME(string2time(OptionsCont::getOptions().getString("persontrip.taxi.waiting-time")));
1551 3414 : if (routingMode == libsumo::ROUTING_MODE_COMBINED) {
1552 0 : myIntermodalRouter[key] = new MSTransportableRouter(MSNet::adaptIntermodalRouter, carWalk, taxiWait, routingAlgorithm, routingMode, new FareModul());
1553 : } else {
1554 3414 : myIntermodalRouter[key] = new MSTransportableRouter(MSNet::adaptIntermodalRouter, carWalk, taxiWait, routingAlgorithm, routingMode);
1555 : }
1556 : }
1557 183122 : myIntermodalRouter[key]->prohibit(prohibited);
1558 183122 : return *myIntermodalRouter[key];
1559 : }
1560 :
1561 :
1562 : void
1563 4220 : MSNet::adaptIntermodalRouter(MSTransportableRouter& router) {
1564 8440 : double taxiWait = STEPS2TIME(string2time(OptionsCont::getOptions().getString("persontrip.taxi.waiting-time")));
1565 : // add access to all parking areas
1566 : EffortCalculator* const external = router.getExternalEffort();
1567 12607 : for (const auto& stopType : myInstance->myStoppingPlaces) {
1568 : // add access to all stopping places
1569 8387 : const SumoXMLTag element = stopType.first;
1570 30914 : for (const auto& i : stopType.second) {
1571 22527 : const MSEdge* const edge = &i.second->getLane().getEdge();
1572 22527 : router.getNetwork()->addAccess(i.first, edge, i.second->getBeginLanePosition(), i.second->getEndLanePosition(),
1573 : 0., element, false, taxiWait);
1574 22527 : if (element == SUMO_TAG_BUS_STOP) {
1575 : // add access to all public transport stops
1576 10899 : for (const auto& a : i.second->getAllAccessPos()) {
1577 1007 : router.getNetwork()->addAccess(i.first, &a.lane->getEdge(), a.startPos, a.endPos, a.length, element, true, taxiWait);
1578 : }
1579 9892 : if (external != nullptr) {
1580 0 : external->addStop(router.getNetwork()->getStopEdge(i.first)->getNumericalID(), *i.second);
1581 : }
1582 : }
1583 : }
1584 : }
1585 4220 : myInstance->getInsertionControl().adaptIntermodalRouter(router);
1586 4220 : myInstance->getVehicleControl().adaptIntermodalRouter(router);
1587 : // add access to transfer from walking to taxi-use
1588 4220 : if ((router.getCarWalkTransfer() & ModeChangeOptions::TAXI_PICKUP_ANYWHERE) != 0) {
1589 24224 : for (MSEdge* edge : myInstance->getEdgeControl().getEdges()) {
1590 24136 : if ((edge->getPermissions() & SVC_PEDESTRIAN) != 0 && (edge->getPermissions() & SVC_TAXI) != 0) {
1591 11456 : router.getNetwork()->addCarAccess(edge, SVC_TAXI, taxiWait);
1592 : }
1593 : }
1594 : }
1595 4220 : }
1596 :
1597 :
1598 : bool
1599 42314 : MSNet::checkElevation() {
1600 42314 : const MSEdgeVector& edges = myEdges->getEdges();
1601 1768220 : for (MSEdgeVector::const_iterator e = edges.begin(); e != edges.end(); ++e) {
1602 3870420 : for (std::vector<MSLane*>::const_iterator i = (*e)->getLanes().begin(); i != (*e)->getLanes().end(); ++i) {
1603 2144514 : if ((*i)->getShape().hasElevation()) {
1604 : return true;
1605 : }
1606 : }
1607 : }
1608 : return false;
1609 : }
1610 :
1611 :
1612 : bool
1613 42314 : MSNet::checkWalkingarea() {
1614 1369626 : for (const MSEdge* e : myEdges->getEdges()) {
1615 1335258 : if (e->getFunction() == SumoXMLEdgeFunc::WALKINGAREA) {
1616 : return true;
1617 : }
1618 : }
1619 : return false;
1620 : }
1621 :
1622 :
1623 : bool
1624 42314 : MSNet::checkBidiEdges() {
1625 1715806 : for (const MSEdge* e : myEdges->getEdges()) {
1626 1674352 : if (e->getBidiEdge() != nullptr) {
1627 : return true;
1628 : }
1629 : }
1630 : return false;
1631 : }
1632 :
1633 : bool
1634 291 : MSNet::warnOnce(const std::string& typeAndID) {
1635 291 : if (myWarnedOnce.find(typeAndID) == myWarnedOnce.end()) {
1636 278 : myWarnedOnce[typeAndID] = true;
1637 278 : return true;
1638 : }
1639 : return false;
1640 : }
1641 :
1642 : void
1643 0 : MSNet::quickReload() {
1644 0 : const OptionsCont& oc = OptionsCont::getOptions();
1645 0 : clearState(string2time(oc.getString("begin")), true);
1646 0 : NLBuilder::initRandomness();
1647 : // load traffic from additional files
1648 0 : for (std::string file : oc.getStringVector("additional-files")) {
1649 : // ignore failure on parsing calibrator flow
1650 0 : MSRouteHandler rh(file, true);
1651 0 : const long before = PROGRESS_BEGIN_TIME_MESSAGE("Loading traffic from '" + file + "'");
1652 0 : if (!XMLSubSys::runParser(rh, file, false)) {
1653 0 : throw ProcessError(TLF("Loading of % failed.", file));
1654 : }
1655 0 : PROGRESS_TIME_MESSAGE(before);
1656 0 : }
1657 0 : delete myRouteLoaders;
1658 0 : myRouteLoaders = NLBuilder::buildRouteLoaderControl(OptionsCont::getOptions());
1659 0 : updateGUI();
1660 0 : }
1661 :
1662 :
1663 : SUMOTime
1664 196 : MSNet::loadState(const std::string& fileName, const bool catchExceptions) {
1665 : // load time only
1666 196 : const SUMOTime newTime = MSStateHandler::MSStateTimeHandler::getTime(fileName);
1667 : // clean up state
1668 186 : clearState(newTime);
1669 : // load state
1670 186 : MSStateHandler h(fileName, 0);
1671 186 : XMLSubSys::runParser(h, fileName, false, false, false, catchExceptions);
1672 186 : if (MsgHandler::getErrorInstance()->wasInformed()) {
1673 0 : throw ProcessError(TLF("Loading state from '%' failed.", fileName));
1674 : }
1675 : // reset route loaders
1676 186 : delete myRouteLoaders;
1677 186 : myRouteLoaders = NLBuilder::buildRouteLoaderControl(OptionsCont::getOptions());
1678 : // prevent loading errors on rewound route file
1679 186 : MSGlobals::gStateLoaded = true;
1680 :
1681 186 : updateGUI();
1682 186 : return newTime;
1683 186 : }
1684 :
1685 :
1686 : /****************************************************************************/
|