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