Line data Source code
1 : /****************************************************************************/
2 : // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
3 : // Copyright (C) 2001-2026 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/SUMORouteLoader.h>
63 : #include <utils/vehicle/SUMOVehicleParserHelper.h>
64 : #include <utils/xml/XMLSubSys.h>
65 : #include <traci-server/TraCIServer.h>
66 : #include <libsumo/Helper.h>
67 : #include <libsumo/Simulation.h>
68 : #include <mesosim/MELoop.h>
69 : #include <mesosim/MESegment.h>
70 : #include <microsim/output/MSDetectorControl.h>
71 : #include <microsim/MSVehicleTransfer.h>
72 : #include <microsim/devices/MSRoutingEngine.h>
73 : #include <microsim/devices/MSDevice_Vehroutes.h>
74 : #include <microsim/devices/MSDevice_Tripinfo.h>
75 : #include <microsim/devices/MSDevice_BTsender.h>
76 : #include <microsim/devices/MSDevice_SSM.h>
77 : #include <microsim/devices/MSDevice_ElecHybrid.h>
78 : #include <microsim/devices/MSDevice_ToC.h>
79 : #include <microsim/devices/MSDevice_Taxi.h>
80 : #include <microsim/output/MSBatteryExport.h>
81 : #include <microsim/output/MSChargingStationExport.h>
82 : #include <microsim/output/MSElecHybridExport.h>
83 : #include <microsim/output/MSEmissionExport.h>
84 : #include <microsim/output/MSFCDExport.h>
85 : #include <microsim/output/MSFullExport.h>
86 : #include <microsim/output/MSQueueExport.h>
87 : #include <microsim/output/MSVTKExport.h>
88 : #include <microsim/output/MSXMLRawOut.h>
89 : #include <microsim/output/MSAmitranTrajectories.h>
90 : #include <microsim/output/MSStopOut.h>
91 : #include <microsim/transportables/MSPModel.h>
92 : #include <microsim/transportables/MSPerson.h>
93 : #include <microsim/traffic_lights/MSTrafficLightLogic.h>
94 : #include <microsim/transportables/MSTransportableControl.h>
95 : #include <microsim/traffic_lights/MSRailSignal.h>
96 : #include <microsim/traffic_lights/MSRailSignalConstraint.h>
97 : #include <microsim/traffic_lights/MSRailSignalControl.h>
98 : #include <microsim/traffic_lights/MSTLLogicControl.h>
99 : #include <microsim/traffic_lights/MSDriveWay.h>
100 : #include <microsim/trigger/MSCalibrator.h>
101 : #include <microsim/trigger/MSChargingStation.h>
102 : #include <microsim/trigger/MSLaneSpeedTrigger.h>
103 : #include <microsim/trigger/MSOverheadWire.h>
104 : #include <microsim/trigger/MSTriggeredRerouter.h>
105 : #include <utils/router/FareModul.h>
106 : #include <netload/NLBuilder.h>
107 :
108 : #include "MSEdgeControl.h"
109 : #include "MSJunctionControl.h"
110 : #include "MSInsertionControl.h"
111 : #include "MSDynamicShapeUpdater.h"
112 : #include "MSEventControl.h"
113 : #include "MSEdge.h"
114 : #include "MSJunction.h"
115 : #include "MSJunctionLogic.h"
116 : #include "MSLane.h"
117 : #include "MSVehicleControl.h"
118 : #include "MSVehicleTransfer.h"
119 : #include "MSRoute.h"
120 : #include "MSGlobals.h"
121 : #include "MSEdgeWeightsStorage.h"
122 : #include "MSStateHandler.h"
123 : #include "MSFrame.h"
124 : #include "MSParkingArea.h"
125 : #include "MSStoppingPlace.h"
126 : #include "MSNet.h"
127 :
128 :
129 : // ===========================================================================
130 : // debug constants
131 : // ===========================================================================
132 : //#define DEBUG_SIMSTEP
133 :
134 :
135 : // ===========================================================================
136 : // static member definitions
137 : // ===========================================================================
138 : MSNet* MSNet::myInstance = nullptr;
139 :
140 : const std::string MSNet::STAGE_EVENTS("events");
141 : const std::string MSNet::STAGE_MOVEMENTS("move");
142 : const std::string MSNet::STAGE_LANECHANGE("laneChange");
143 : const std::string MSNet::STAGE_INSERTIONS("insertion");
144 : const std::string MSNet::STAGE_REMOTECONTROL("remoteControl");
145 :
146 : const NamedObjectCont<MSStoppingPlace*> MSNet::myEmptyStoppingPlaceCont;
147 : const std::vector<MSStoppingPlace*> MSNet::myEmptyStoppingPlaceVector;
148 :
149 : // ===========================================================================
150 : // static member method definitions
151 : // ===========================================================================
152 : double
153 336 : MSNet::getEffort(const MSEdge* const e, const SUMOVehicle* const v, double t) {
154 : double value;
155 336 : const MSVehicle* const veh = dynamic_cast<const MSVehicle* const>(v);
156 336 : if (veh != nullptr && veh->getWeightsStorage().retrieveExistingEffort(e, t, value)) {
157 2 : return value;
158 : }
159 334 : if (getInstance()->getWeightsStorage().retrieveExistingEffort(e, t, value)) {
160 2 : return value;
161 : }
162 : return 0;
163 : }
164 :
165 :
166 : double
167 6932825 : MSNet::getTravelTime(const MSEdge* const e, const SUMOVehicle* const v, double t) {
168 : double value;
169 6932825 : const MSVehicle* const veh = dynamic_cast<const MSVehicle* const>(v);
170 6931902 : if (veh != nullptr && veh->getWeightsStorage().retrieveExistingTravelTime(e, t, value)) {
171 522 : return value;
172 : }
173 6932303 : if (getInstance()->getWeightsStorage().retrieveExistingTravelTime(e, t, value)) {
174 177 : return value;
175 : }
176 6932126 : if (veh != nullptr) {
177 6755665 : if ((veh->getRoutingMode() & libsumo::ROUTING_MODE_AGGREGATED_CUSTOM) != 0) {
178 3411 : return MSRoutingEngine::getEffortExtra(e, v, t);
179 6752254 : } else if ((veh->getRoutingMode() & libsumo::ROUTING_MODE_AGGREGATED) != 0) {
180 507 : if (MSRoutingEngine::hasBikeSpeeds() && v->getVClass() == SVC_BICYCLE) {
181 0 : return MSRoutingEngine::getEffortBike(e, v, t);
182 : } else {
183 507 : return MSRoutingEngine::getEffort(e, v, t);
184 : }
185 6751747 : } else if (MSRoutingEngine::haveExtras()) {
186 6751747 : double tt = e->getMinimumTravelTime(v);
187 6751747 : MSRoutingEngine::applyExtras(e, v, SIMSTEP, tt);
188 6751747 : return tt;
189 : }
190 : }
191 176461 : return e->getMinimumTravelTime(v);
192 : }
193 :
194 :
195 : // ---------------------------------------------------------------------------
196 : // MSNet - methods
197 : // ---------------------------------------------------------------------------
198 : MSNet*
199 5456449815 : MSNet::getInstance(void) {
200 5456449815 : if (myInstance != nullptr) {
201 5456449770 : return myInstance;
202 : }
203 90 : throw ProcessError(TL("A network was not yet constructed."));
204 : }
205 :
206 : void
207 41790 : MSNet::initStatic() {
208 41790 : gRoutingPreferences = false;
209 41790 : MSDriveWay::init();
210 41790 : }
211 :
212 : void
213 41176 : MSNet::cleanupStatic() {
214 41176 : if (!MSGlobals::gUseMesoSim) {
215 34819 : MSVehicle::Influencer::cleanup();
216 : }
217 41176 : }
218 :
219 :
220 41790 : MSNet::MSNet(MSVehicleControl* vc, MSEventControl* beginOfTimestepEvents,
221 : MSEventControl* endOfTimestepEvents,
222 : MSEventControl* insertionEvents,
223 41790 : ShapeContainer* shapeCont):
224 41790 : myAmInterrupted(false),
225 41790 : myVehiclesMoved(0),
226 41790 : myPersonsMoved(0),
227 41790 : myHavePermissions(false),
228 41790 : myHasInternalLinks(false),
229 41790 : myJunctionHigherSpeeds(false),
230 41790 : myHasElevation(false),
231 41790 : myHasPedestrianNetwork(false),
232 41790 : myHasBidiEdges(false),
233 41790 : myEdgeDataEndTime(-1),
234 41790 : myDynamicShapeUpdater(nullptr) {
235 41790 : if (myInstance != nullptr) {
236 0 : throw ProcessError(TL("A network was already constructed."));
237 : }
238 41790 : OptionsCont& oc = OptionsCont::getOptions();
239 41790 : myStep = string2time(oc.getString("begin"));
240 41790 : myMaxTeleports = oc.getInt("max-num-teleports");
241 41790 : myLogExecutionTime = !oc.getBool("no-duration-log");
242 41790 : myLogStepNumber = !oc.getBool("no-step-log");
243 41790 : myLogStepPeriod = oc.getInt("step-log.period");
244 167160 : myInserter = new MSInsertionControl(*vc, string2time(oc.getString("max-depart-delay")), oc.getBool("eager-insert"), oc.getInt("max-num-vehicles"),
245 167160 : string2time(oc.getString("random-depart-offset")));
246 41790 : myVehicleControl = vc;
247 41790 : myDetectorControl = new MSDetectorControl();
248 41790 : myEdges = nullptr;
249 41790 : myJunctions = nullptr;
250 41790 : myRouteLoaders = nullptr;
251 41790 : myLogics = nullptr;
252 41790 : myPersonControl = nullptr;
253 41790 : myContainerControl = nullptr;
254 41790 : myEdgeWeights = nullptr;
255 41790 : myShapeContainer = shapeCont == nullptr ? new ShapeContainer() : shapeCont;
256 :
257 41790 : myBeginOfTimestepEvents = beginOfTimestepEvents;
258 41790 : myEndOfTimestepEvents = endOfTimestepEvents;
259 41790 : myInsertionEvents = insertionEvents;
260 41790 : myLanesRTree.first = false;
261 :
262 41790 : if (MSGlobals::gUseMesoSim) {
263 12902 : MSGlobals::gMesoNet = new MELoop(string2time(oc.getString("meso-recheck")));
264 : }
265 41790 : myInstance = this;
266 41790 : initStatic();
267 41790 : }
268 :
269 :
270 : void
271 41311 : MSNet::closeBuilding(const OptionsCont& oc, MSEdgeControl* edges, MSJunctionControl* junctions,
272 : SUMORouteLoaderControl* routeLoaders,
273 : MSTLLogicControl* tlc,
274 : std::vector<SUMOTime> stateDumpTimes,
275 : std::vector<std::string> stateDumpFiles,
276 : bool hasInternalLinks,
277 : bool junctionHigherSpeeds,
278 : const MMVersion& version) {
279 41311 : myEdges = edges;
280 41311 : myJunctions = junctions;
281 41311 : myRouteLoaders = routeLoaders;
282 41311 : myLogics = tlc;
283 : // save the time the network state shall be saved at
284 41311 : myStateDumpTimes = stateDumpTimes;
285 41311 : myStateDumpFiles = stateDumpFiles;
286 41311 : myStateDumpPeriod = string2time(oc.getString("save-state.period"));
287 41311 : myStateDumpPrefix = oc.getString("save-state.prefix");
288 41311 : myStateDumpSuffix = oc.getString("save-state.suffix");
289 :
290 : // initialise performance computation
291 41311 : mySimBeginMillis = SysUtils::getCurrentMillis();
292 41311 : myTraCIMillis = 0;
293 41311 : myHasInternalLinks = hasInternalLinks;
294 41311 : myJunctionHigherSpeeds = junctionHigherSpeeds;
295 41311 : myHasElevation = checkElevation();
296 41311 : myHasPedestrianNetwork = checkWalkingarea();
297 41311 : myHasBidiEdges = checkBidiEdges();
298 : myVersion = version;
299 41311 : if ((!MSGlobals::gUsingInternalLanes || !myHasInternalLinks)
300 14534 : && MSGlobals::gWeightsSeparateTurns > 0) {
301 0 : throw ProcessError(TL("Option weights.separate-turns is only supported when simulating with internal lanes"));
302 : }
303 41311 : }
304 :
305 :
306 73828 : MSNet::~MSNet() {
307 41176 : cleanupStatic();
308 : // delete controls
309 41176 : delete myJunctions;
310 41176 : delete myDetectorControl;
311 : // delete mean data
312 41176 : delete myEdges;
313 41176 : delete myInserter;
314 41176 : myInserter = nullptr;
315 41176 : delete myLogics;
316 41176 : delete myRouteLoaders;
317 41176 : if (myPersonControl != nullptr) {
318 8140 : delete myPersonControl;
319 8140 : myPersonControl = nullptr; // just to have that clear for later cleanups
320 : }
321 41176 : if (myContainerControl != nullptr) {
322 1950 : delete myContainerControl;
323 1950 : myContainerControl = nullptr; // just to have that clear for later cleanups
324 : }
325 41176 : delete myVehicleControl; // must happen after deleting transportables
326 : // delete events late so that vehicles can get rid of references first
327 41176 : delete myBeginOfTimestepEvents;
328 41176 : myBeginOfTimestepEvents = nullptr;
329 41176 : delete myEndOfTimestepEvents;
330 41176 : myEndOfTimestepEvents = nullptr;
331 41176 : delete myInsertionEvents;
332 41176 : myInsertionEvents = nullptr;
333 41176 : delete myShapeContainer;
334 41176 : delete myEdgeWeights;
335 42591 : for (auto& router : myRouterTT) {
336 1415 : delete router.second;
337 : }
338 : myRouterTT.clear();
339 41187 : for (auto& router : myRouterEffort) {
340 11 : delete router.second;
341 : }
342 : myRouterEffort.clear();
343 43986 : for (auto& router : myPedestrianRouter) {
344 2810 : delete router.second;
345 : }
346 : myPedestrianRouter.clear();
347 41176 : resetIntermodalRouter();
348 : myLanesRTree.second.RemoveAll();
349 41193 : for (MSTractionSubstation* sub : myTractionSubstations) {
350 17 : delete sub;
351 : }
352 : myTractionSubstations.clear();
353 41176 : clearAll();
354 41176 : if (MSGlobals::gUseMesoSim) {
355 6357 : delete MSGlobals::gMesoNet;
356 : }
357 41176 : myInstance = nullptr;
358 156180 : }
359 :
360 :
361 : void
362 221 : MSNet::addRestriction(const std::string& id, const SUMOVehicleClass svc, const double speed) {
363 221 : myRestrictions[id][svc] = speed;
364 221 : }
365 :
366 :
367 : const std::map<SUMOVehicleClass, double>*
368 2106681 : MSNet::getRestrictions(const std::string& id) const {
369 : std::map<std::string, std::map<SUMOVehicleClass, double> >::const_iterator i = myRestrictions.find(id);
370 2106681 : if (i == myRestrictions.end()) {
371 : return nullptr;
372 : }
373 1130 : return &i->second;
374 : }
375 :
376 :
377 : double
378 4045 : MSNet::getPreference(const std::string& routingType, const SUMOVTypeParameter& pars) const {
379 4045 : if (gRoutingPreferences) {
380 4045 : auto it = myVTypePreferences.find(pars.id);
381 4045 : if (it != myVTypePreferences.end()) {
382 : auto it2 = it->second.find(routingType);
383 224 : if (it2 != it->second.end()) {
384 56 : return it2->second;
385 : }
386 : }
387 : auto it3 = myVClassPreferences.find(pars.vehicleClass);
388 3989 : if (it3 != myVClassPreferences.end()) {
389 : auto it4 = it3->second.find(routingType);
390 336 : if (it4 != it3->second.end()) {
391 84 : return it4->second;
392 : }
393 : }
394 : // fallback to generel preferences
395 3905 : it = myVTypePreferences.find("");
396 3905 : if (it != myVTypePreferences.end()) {
397 : auto it2 = it->second.find(routingType);
398 2729 : if (it2 != it->second.end()) {
399 553 : return it2->second;
400 : }
401 : }
402 : }
403 : return 1;
404 : }
405 :
406 :
407 : void
408 28 : MSNet::addPreference(const std::string& routingType, SUMOVehicleClass svc, double prio) {
409 28 : myVClassPreferences[svc][routingType] = prio;
410 28 : gRoutingPreferences = true;
411 28 : }
412 :
413 :
414 : void
415 84 : MSNet::addPreference(const std::string& routingType, std::string vType, double prio) {
416 84 : myVTypePreferences[vType][routingType] = prio;
417 84 : gRoutingPreferences = true;
418 84 : }
419 :
420 : void
421 24 : MSNet::addMesoType(const std::string& typeID, const MESegment::MesoEdgeType& edgeType) {
422 24 : myMesoEdgeTypes[typeID] = edgeType;
423 24 : }
424 :
425 : const MESegment::MesoEdgeType&
426 838095 : MSNet::getMesoType(const std::string& typeID) {
427 : if (myMesoEdgeTypes.count(typeID) == 0) {
428 : // init defaults
429 6913 : const OptionsCont& oc = OptionsCont::getOptions();
430 : MESegment::MesoEdgeType edgeType;
431 6913 : edgeType.tauff = string2time(oc.getString("meso-tauff"));
432 6913 : edgeType.taufj = string2time(oc.getString("meso-taufj"));
433 6913 : edgeType.taujf = string2time(oc.getString("meso-taujf"));
434 6913 : edgeType.taujj = string2time(oc.getString("meso-taujj"));
435 6913 : edgeType.jamThreshold = oc.getFloat("meso-jam-threshold");
436 6913 : edgeType.junctionControl = oc.getBool("meso-junction-control");
437 6913 : edgeType.tlsPenalty = oc.getFloat("meso-tls-penalty");
438 6913 : edgeType.tlsFlowPenalty = oc.getFloat("meso-tls-flow-penalty");
439 6913 : edgeType.minorPenalty = string2time(oc.getString("meso-minor-penalty"));
440 6913 : edgeType.overtaking = oc.getBool("meso-overtaking");
441 6913 : edgeType.edgeLength = oc.getFloat("meso-edgelength");
442 6913 : myMesoEdgeTypes[typeID] = edgeType;
443 : }
444 838095 : return myMesoEdgeTypes[typeID];
445 : }
446 :
447 :
448 : bool
449 7152718 : MSNet::hasFlow(const std::string& id) const {
450 : // inserter is deleted at the end of the simulation
451 7152718 : return myInserter != nullptr && myInserter->hasFlow(id);
452 : }
453 :
454 :
455 : MSNet::SimulationState
456 31242 : MSNet::simulate(SUMOTime start, SUMOTime stop) {
457 : // report the begin when wished
458 62484 : WRITE_MESSAGEF(TL("Simulation version % started with time: %."), VERSION_STRING, time2string(start));
459 : // the simulation loop
460 : SimulationState state = SIMSTATE_RUNNING;
461 : // state loading may have changed the start time so we need to reinit it
462 31242 : myStep = start;
463 : int numSteps = 0;
464 : bool doStepLog = false;
465 46326926 : while (state == SIMSTATE_RUNNING) {
466 46296090 : doStepLog = myLogStepNumber && (numSteps % myLogStepPeriod == 0);
467 : if (doStepLog) {
468 110 : preSimStepOutput();
469 : }
470 46296090 : simulationStep();
471 46295684 : if (doStepLog) {
472 110 : postSimStepOutput();
473 : }
474 46295684 : state = adaptToState(simulationState(stop));
475 : #ifdef DEBUG_SIMSTEP
476 : std::cout << SIMTIME << " MSNet::simulate(" << start << ", " << stop << ")"
477 : << "\n simulation state: " << getStateMessage(state)
478 : << std::endl;
479 : #endif
480 46295684 : numSteps++;
481 : }
482 30836 : if (myLogStepNumber && !doStepLog) {
483 : // ensure some output on the last step
484 17 : preSimStepOutput();
485 17 : postSimStepOutput();
486 : }
487 : // exit simulation loop
488 30836 : if (myLogStepNumber) {
489 : // start new line for final verbose output
490 20 : std::cout << "\n";
491 : }
492 30836 : closeSimulation(start, getStateMessage(state));
493 30836 : return state;
494 : }
495 :
496 :
497 : void
498 56177021 : MSNet::loadRoutes() {
499 56177021 : myRouteLoaders->loadNext(myStep);
500 56176441 : }
501 :
502 :
503 : const std::string
504 12861 : MSNet::generateStatistics(const SUMOTime start, const long now) {
505 12861 : std::ostringstream msg;
506 12861 : if (myLogExecutionTime) {
507 12533 : const long duration = now - mySimBeginMillis;
508 : // print performance notice
509 25066 : msg << "Performance:\n" << " Duration: " << elapsedMs2string(duration) << "\n";
510 12533 : if (duration != 0) {
511 12387 : if (TraCIServer::getInstance() != nullptr) {
512 4287 : msg << " TraCI-Duration: " << elapsedMs2string(myTraCIMillis) << "\n";
513 : }
514 12387 : msg << " Real time factor: " << (STEPS2TIME(myStep - start) * 1000. / (double)duration) << "\n";
515 : msg.setf(std::ios::fixed, std::ios::floatfield); // use decimal format
516 : msg.setf(std::ios::showpoint); // print decimal point
517 12387 : msg << " UPS: " << ((double)myVehiclesMoved / ((double)duration / 1000)) << "\n";
518 12387 : if (myPersonsMoved > 0) {
519 2355 : msg << " UPS-Persons: " << ((double)myPersonsMoved / ((double)duration / 1000)) << "\n";
520 : }
521 : }
522 : // print vehicle statistics
523 12533 : const std::string vehDiscardNotice = ((myVehicleControl->getLoadedVehicleNo() != myVehicleControl->getDepartedVehicleNo()) ?
524 16556 : " (Loaded: " + toString(myVehicleControl->getLoadedVehicleNo()) + ")" : "");
525 : msg << "Vehicles:\n"
526 12533 : << " Inserted: " << myVehicleControl->getDepartedVehicleNo() << vehDiscardNotice << "\n"
527 25066 : << " Running: " << myVehicleControl->getRunningVehicleNo() << "\n"
528 25066 : << " Waiting: " << myInserter->getWaitingVehicleNo() << "\n";
529 :
530 12533 : if (myVehicleControl->getTeleportCount() > 0 || myVehicleControl->getCollisionCount() > 0) {
531 : // print optional teleport statistics
532 : std::vector<std::string> reasons;
533 672 : if (myVehicleControl->getCollisionCount() > 0) {
534 628 : reasons.push_back("Collisions: " + toString(myVehicleControl->getCollisionCount()));
535 : }
536 672 : if (myVehicleControl->getTeleportsJam() > 0) {
537 444 : reasons.push_back("Jam: " + toString(myVehicleControl->getTeleportsJam()));
538 : }
539 672 : if (myVehicleControl->getTeleportsYield() > 0) {
540 190 : reasons.push_back("Yield: " + toString(myVehicleControl->getTeleportsYield()));
541 : }
542 672 : if (myVehicleControl->getTeleportsWrongLane() > 0) {
543 252 : reasons.push_back("Wrong Lane: " + toString(myVehicleControl->getTeleportsWrongLane()));
544 : }
545 2016 : msg << " Teleports: " << myVehicleControl->getTeleportCount() << " (" << joinToString(reasons, ", ") << ")\n";
546 672 : }
547 12533 : if (myVehicleControl->getEmergencyStops() > 0) {
548 60 : msg << " Emergency Stops: " << myVehicleControl->getEmergencyStops() << "\n";
549 : }
550 12533 : if (myVehicleControl->getEmergencyBrakingCount() > 0) {
551 287 : msg << " Emergency Braking: " << myVehicleControl->getEmergencyBrakingCount() << "\n";
552 : }
553 12533 : if (myPersonControl != nullptr && myPersonControl->getLoadedNumber() > 0) {
554 2407 : const std::string discardNotice = ((myPersonControl->getLoadedNumber() != myPersonControl->getDepartedNumber()) ?
555 2773 : " (Loaded: " + toString(myPersonControl->getLoadedNumber()) + ")" : "");
556 : msg << "Persons:\n"
557 2407 : << " Inserted: " << myPersonControl->getDepartedNumber() << discardNotice << "\n"
558 4814 : << " Running: " << myPersonControl->getRunningNumber() << "\n";
559 2407 : if (myPersonControl->getJammedNumber() > 0) {
560 53 : msg << " Jammed: " << myPersonControl->getJammedNumber() << "\n";
561 : }
562 2407 : if (myPersonControl->getTeleportCount() > 0) {
563 : std::vector<std::string> reasons;
564 7 : if (myPersonControl->getTeleportsAbortWait() > 0) {
565 0 : reasons.push_back("Abort Wait: " + toString(myPersonControl->getTeleportsAbortWait()));
566 : }
567 7 : if (myPersonControl->getTeleportsWrongDest() > 0) {
568 14 : reasons.push_back("Wrong Dest: " + toString(myPersonControl->getTeleportsWrongDest()));
569 : }
570 21 : msg << " Teleports: " << myPersonControl->getTeleportCount() << " (" << joinToString(reasons, ", ") << ")\n";
571 7 : }
572 : }
573 12533 : if (myContainerControl != nullptr && myContainerControl->getLoadedNumber() > 0) {
574 76 : const std::string discardNotice = ((myContainerControl->getLoadedNumber() != myContainerControl->getDepartedNumber()) ?
575 76 : " (Loaded: " + toString(myContainerControl->getLoadedNumber()) + ")" : "");
576 : msg << "Containers:\n"
577 76 : << " Inserted: " << myContainerControl->getDepartedNumber() << "\n"
578 152 : << " Running: " << myContainerControl->getRunningNumber() << "\n";
579 76 : if (myContainerControl->getJammedNumber() > 0) {
580 0 : msg << " Jammed: " << myContainerControl->getJammedNumber() << "\n";
581 : }
582 76 : if (myContainerControl->getTeleportCount() > 0) {
583 : std::vector<std::string> reasons;
584 0 : if (myContainerControl->getTeleportsAbortWait() > 0) {
585 0 : reasons.push_back("Abort Wait: " + toString(myContainerControl->getTeleportsAbortWait()));
586 : }
587 0 : if (myContainerControl->getTeleportsWrongDest() > 0) {
588 0 : reasons.push_back("Wrong Dest: " + toString(myContainerControl->getTeleportsWrongDest()));
589 : }
590 0 : msg << " Teleports: " << myContainerControl->getTeleportCount() << " (" << joinToString(reasons, ", ") << ")\n";
591 0 : }
592 : }
593 : }
594 25722 : if (OptionsCont::getOptions().getBool("duration-log.statistics")) {
595 6390 : msg << MSDevice_Tripinfo::printStatistics();
596 : }
597 : std::string result = msg.str();
598 : result.erase(result.end() - 1);
599 12861 : return result;
600 12861 : }
601 :
602 :
603 : void
604 10356 : MSNet::writeCollisions() const {
605 20712 : OutputDevice& od = OutputDevice::getDeviceByOption("collision-output");
606 10515 : for (const auto& item : myCollisions) {
607 318 : for (const auto& c : item.second) {
608 159 : if (c.time != SIMSTEP) {
609 18 : continue;
610 : }
611 282 : od.openTag("collision");
612 141 : od.writeAttr("time", time2string(getCurrentTimeStep()));
613 141 : od.writeAttr("type", c.type);
614 141 : od.writeAttr("lane", c.lane->getID());
615 141 : od.writeAttr("pos", c.pos);
616 141 : od.writeAttr("collider", item.first);
617 141 : od.writeAttr("victim", c.victim);
618 141 : od.writeAttr("colliderType", c.colliderType);
619 141 : od.writeAttr("victimType", c.victimType);
620 141 : od.writeAttr("colliderSpeed", c.colliderSpeed);
621 141 : od.writeAttr("victimSpeed", c.victimSpeed);
622 141 : od.writeAttr("colliderFront", c.colliderFront);
623 141 : od.writeAttr("colliderBack", c.colliderBack);
624 141 : od.writeAttr("victimFront", c.victimFront);
625 141 : od.writeAttr("victimBack", c.victimBack);
626 282 : od.closeTag();
627 : }
628 : }
629 10356 : }
630 :
631 :
632 : void
633 379 : MSNet::writeStatistics(const SUMOTime start, const long now) const {
634 379 : const long duration = now - mySimBeginMillis;
635 379 : OutputDevice& od = OutputDevice::getDeviceByOption("statistic-output");
636 379 : od.openTag("performance");
637 379 : od.writeAttr("clockBegin", time2string(mySimBeginMillis));
638 379 : od.writeAttr("clockEnd", time2string(now));
639 379 : od.writeAttr("clockDuration", time2string(duration));
640 379 : od.writeAttr("traciDuration", time2string(myTraCIMillis));
641 379 : od.writeAttr("realTimeFactor", duration != 0 ? (double)(myStep - start) / (double)duration : -1);
642 379 : od.writeAttr("vehicleUpdatesPerSecond", duration != 0 ? (double)myVehiclesMoved / ((double)duration / 1000) : -1);
643 379 : od.writeAttr("personUpdatesPerSecond", duration != 0 ? (double)myPersonsMoved / ((double)duration / 1000) : -1);
644 379 : od.writeAttr("begin", time2string(start));
645 379 : od.writeAttr("end", time2string(myStep));
646 379 : od.writeAttr("duration", time2string(myStep - start));
647 379 : od.closeTag();
648 379 : od.openTag("vehicles");
649 379 : od.writeAttr("loaded", myVehicleControl->getLoadedVehicleNo());
650 379 : od.writeAttr("inserted", myVehicleControl->getDepartedVehicleNo());
651 379 : od.writeAttr("running", myVehicleControl->getRunningVehicleNo());
652 379 : od.writeAttr("waiting", myInserter->getWaitingVehicleNo());
653 379 : od.closeTag();
654 379 : od.openTag("teleports");
655 379 : od.writeAttr("total", myVehicleControl->getTeleportCount());
656 379 : od.writeAttr("jam", myVehicleControl->getTeleportsJam());
657 379 : od.writeAttr("yield", myVehicleControl->getTeleportsYield());
658 379 : od.writeAttr("wrongLane", myVehicleControl->getTeleportsWrongLane());
659 379 : od.closeTag();
660 379 : od.openTag("safety");
661 379 : od.writeAttr("collisions", myVehicleControl->getCollisionCount());
662 379 : od.writeAttr("emergencyStops", myVehicleControl->getEmergencyStops());
663 379 : od.writeAttr("emergencyBraking", myVehicleControl->getEmergencyBrakingCount());
664 379 : od.closeTag();
665 379 : od.openTag("persons");
666 385 : od.writeAttr("loaded", myPersonControl != nullptr ? myPersonControl->getLoadedNumber() : 0);
667 385 : od.writeAttr("running", myPersonControl != nullptr ? myPersonControl->getRunningNumber() : 0);
668 385 : od.writeAttr("jammed", myPersonControl != nullptr ? myPersonControl->getJammedNumber() : 0);
669 379 : od.closeTag();
670 379 : od.openTag("personTeleports");
671 385 : od.writeAttr("total", myPersonControl != nullptr ? myPersonControl->getTeleportCount() : 0);
672 385 : od.writeAttr("abortWait", myPersonControl != nullptr ? myPersonControl->getTeleportsAbortWait() : 0);
673 385 : od.writeAttr("wrongDest", myPersonControl != nullptr ? myPersonControl->getTeleportsWrongDest() : 0);
674 379 : od.closeTag();
675 603 : if (OptionsCont::getOptions().isSet("tripinfo-output") || OptionsCont::getOptions().getBool("duration-log.statistics")) {
676 264 : MSDevice_Tripinfo::writeStatistics(od);
677 : }
678 379 : }
679 :
680 :
681 : void
682 56175779 : MSNet::writeSummaryOutput(bool finalStep) {
683 : // summary output
684 56175779 : const OptionsCont& oc = OptionsCont::getOptions();
685 56175779 : const bool hasOutput = oc.isSet("summary-output");
686 56175779 : const bool hasPersonOutput = oc.isSet("person-summary-output");
687 56175779 : if (hasOutput || hasPersonOutput) {
688 531771 : const SUMOTime period = string2time(oc.getString("summary-output.period"));
689 531771 : const SUMOTime begin = string2time(oc.getString("begin"));
690 531771 : if ((period > 0 && (myStep - begin) % period != 0 && !finalStep)
691 : // it's the final step but we already wrote output
692 530851 : || (finalStep && (period <= 0 || (myStep - begin) % period == 0))) {
693 : return;
694 : }
695 : }
696 530329 : if (hasOutput) {
697 522721 : OutputDevice& od = OutputDevice::getDeviceByOption("summary-output");
698 522721 : int departedVehiclesNumber = myVehicleControl->getDepartedVehicleNo();
699 522721 : const double meanWaitingTime = departedVehiclesNumber != 0 ? myVehicleControl->getTotalDepartureDelay() / (double) departedVehiclesNumber : -1.;
700 : int endedVehicleNumber = myVehicleControl->getEndedVehicleNo();
701 522721 : const double meanTravelTime = endedVehicleNumber != 0 ? myVehicleControl->getTotalTravelTime() / (double) endedVehicleNumber : -1.;
702 522721 : od.openTag("step");
703 522721 : od.writeAttr("time", time2string(myStep));
704 522721 : od.writeAttr("loaded", myVehicleControl->getLoadedVehicleNo());
705 522721 : od.writeAttr("inserted", myVehicleControl->getDepartedVehicleNo());
706 522721 : od.writeAttr("running", myVehicleControl->getRunningVehicleNo());
707 522721 : od.writeAttr("waiting", myInserter->getWaitingVehicleNo());
708 522721 : od.writeAttr("ended", myVehicleControl->getEndedVehicleNo());
709 522721 : od.writeAttr("arrived", myVehicleControl->getArrivedVehicleNo());
710 522721 : od.writeAttr("collisions", myVehicleControl->getCollisionCount());
711 522721 : od.writeAttr("teleports", myVehicleControl->getTeleportCount());
712 522721 : od.writeAttr("halting", myVehicleControl->getHaltingVehicleNo());
713 522721 : od.writeAttr("stopped", myVehicleControl->getStoppedVehiclesCount());
714 522721 : od.writeAttr("meanWaitingTime", meanWaitingTime);
715 522721 : od.writeAttr("meanTravelTime", meanTravelTime);
716 522721 : std::pair<double, double> meanSpeed = myVehicleControl->getVehicleMeanSpeeds();
717 522721 : od.writeAttr("meanSpeed", meanSpeed.first);
718 522721 : od.writeAttr("meanSpeedRelative", meanSpeed.second);
719 522721 : od.writeAttr("discarded", myVehicleControl->getDiscardedVehicleNo());
720 522721 : if (myLogExecutionTime) {
721 235433 : od.writeAttr("duration", mySimStepDuration);
722 : }
723 1045442 : od.closeTag();
724 : }
725 56174337 : if (hasPersonOutput) {
726 7608 : OutputDevice& od = OutputDevice::getDeviceByOption("person-summary-output");
727 7608 : MSTransportableControl& pc = getPersonControl();
728 7608 : od.openTag("step");
729 15216 : od.writeAttr("time", time2string(myStep));
730 7608 : od.writeAttr("loaded", pc.getLoadedNumber());
731 7608 : od.writeAttr("inserted", pc.getDepartedNumber());
732 7608 : od.writeAttr("walking", pc.getMovingNumber());
733 7608 : od.writeAttr("waitingForRide", pc.getWaitingForVehicleNumber());
734 7608 : od.writeAttr("riding", pc.getRidingNumber());
735 7608 : od.writeAttr("stopping", pc.getWaitingUntilNumber());
736 7608 : od.writeAttr("jammed", pc.getJammedNumber());
737 7608 : od.writeAttr("ended", pc.getEndedNumber());
738 7608 : od.writeAttr("arrived", pc.getArrivedNumber());
739 7608 : od.writeAttr("teleports", pc.getTeleportCount());
740 7608 : od.writeAttr("discarded", pc.getDiscardedNumber());
741 7608 : if (myLogExecutionTime) {
742 0 : od.writeAttr("duration", mySimStepDuration);
743 : }
744 15216 : od.closeTag();
745 : }
746 : }
747 :
748 :
749 : void
750 39692 : MSNet::closeSimulation(SUMOTime start, const std::string& reason) {
751 : // report the end when wished
752 79384 : WRITE_MESSAGE(TLF("Simulation ended at time: %.", time2string(getCurrentTimeStep())));
753 39692 : if (reason != "") {
754 78510 : WRITE_MESSAGE(TL("Reason: ") + reason);
755 : }
756 39692 : myDetectorControl->close(myStep);
757 41134 : if (MSStopOut::active() && OptionsCont::getOptions().getBool("stop-output.write-unfinished")) {
758 121 : MSStopOut::getInstance()->generateOutputForUnfinished();
759 : }
760 39692 : MSDevice_Vehroutes::writePendingOutput(OptionsCont::getOptions().getBool("vehroute-output.write-unfinished"));
761 79384 : if (OptionsCont::getOptions().getBool("tripinfo-output.write-unfinished")) {
762 1001 : MSDevice_Tripinfo::generateOutputForUnfinished();
763 : }
764 79384 : if (OptionsCont::getOptions().isSet("chargingstations-output")) {
765 228 : if (!OptionsCont::getOptions().getBool("chargingstations-output.aggregated")) {
766 94 : writeChargingStationOutput();
767 40 : } else if (OptionsCont::getOptions().getBool("chargingstations-output.aggregated.write-unfinished")) {
768 12 : MSChargingStationExport::write(OutputDevice::getDeviceByOption("chargingstations-output"), true);
769 : }
770 : }
771 79384 : if (OptionsCont::getOptions().isSet("overheadwiresegments-output")) {
772 5 : writeOverheadWireSegmentOutput();
773 : }
774 79384 : if (OptionsCont::getOptions().isSet("substations-output")) {
775 5 : writeSubstationOutput();
776 : }
777 39692 : writeRailSignalBlocks();
778 39692 : const long now = SysUtils::getCurrentMillis();
779 66851 : if (myLogExecutionTime || OptionsCont::getOptions().getBool("duration-log.statistics")) {
780 25722 : WRITE_MESSAGE(generateStatistics(start, now));
781 : }
782 79384 : if (OptionsCont::getOptions().isSet("statistic-output")) {
783 379 : writeStatistics(start, now);
784 : }
785 : // maybe write a final line of output if reporting is periodic
786 39692 : writeSummaryOutput(true);
787 39692 : }
788 :
789 :
790 : void
791 56139265 : MSNet::simulationStep(const bool onlyMove) {
792 56139265 : if (myStepCompletionMissing) {
793 4 : postMoveStep();
794 4 : myStepCompletionMissing = false;
795 2653 : return;
796 : }
797 : #ifdef DEBUG_SIMSTEP
798 : std::cout << SIMTIME << ": MSNet::simulationStep() called"
799 : << ", myStep = " << myStep
800 : << std::endl;
801 : #endif
802 : TraCIServer* t = TraCIServer::getInstance();
803 : int lastTraCICmd = 0;
804 56139261 : if (t != nullptr) {
805 10618083 : if (myLogExecutionTime) {
806 10421274 : myTraCIStepDuration = SysUtils::getCurrentMillis();
807 : }
808 10618083 : lastTraCICmd = t->processCommands(myStep);
809 : #ifdef DEBUG_SIMSTEP
810 : bool loadRequested = !TraCI::getLoadArgs().empty();
811 : assert(t->getTargetTime() >= myStep || loadRequested || TraCIServer::wasClosed());
812 : #endif
813 10617974 : if (myLogExecutionTime) {
814 10421192 : myTraCIStepDuration = SysUtils::getCurrentMillis() - myTraCIStepDuration;
815 : }
816 10617974 : if (TraCIServer::wasClosed() || !t->getLoadArgs().empty()) {
817 : return;
818 : }
819 : }
820 : #ifdef DEBUG_SIMSTEP
821 : std::cout << SIMTIME << ": TraCI target time: " << t->getTargetTime() << std::endl;
822 : #endif
823 : // execute beginOfTimestepEvents
824 56136507 : if (myLogExecutionTime) {
825 27211759 : mySimStepDuration = SysUtils::getCurrentMillis();
826 : }
827 : // simulation state output
828 56136507 : std::vector<SUMOTime>::iterator timeIt = std::find(myStateDumpTimes.begin(), myStateDumpTimes.end(), myStep);
829 56136507 : if (timeIt != myStateDumpTimes.end()) {
830 332 : const int dist = (int)distance(myStateDumpTimes.begin(), timeIt);
831 332 : MSStateHandler::saveState(myStateDumpFiles[dist], myStep);
832 : }
833 56136507 : if (myStateDumpPeriod > 0 && myStep % myStateDumpPeriod == 0) {
834 84 : std::string timeStamp = time2string(myStep);
835 : std::replace(timeStamp.begin(), timeStamp.end(), ':', '-');
836 84 : const std::string filename = myStateDumpPrefix + "_" + timeStamp + myStateDumpSuffix;
837 84 : MSStateHandler::saveState(filename, myStep);
838 84 : myPeriodicStateFiles.push_back(filename);
839 84 : int keep = OptionsCont::getOptions().getInt("save-state.period.keep");
840 84 : if (keep > 0 && (int)myPeriodicStateFiles.size() > keep) {
841 0 : std::remove(myPeriodicStateFiles.front().c_str());
842 : myPeriodicStateFiles.erase(myPeriodicStateFiles.begin());
843 : }
844 : }
845 56136507 : myBeginOfTimestepEvents->execute(myStep);
846 56136501 : if (MSRailSignalControl::hasInstance()) {
847 8693750 : MSRailSignalControl::getInstance().updateSignals(myStep);
848 : }
849 : #ifdef HAVE_FOX
850 56136501 : MSRoutingEngine::waitForAll();
851 : #endif
852 56136501 : if (MSGlobals::gCheck4Accidents && !MSGlobals::gUseMesoSim) {
853 40788936 : myEdges->detectCollisions(myStep, STAGE_EVENTS);
854 : }
855 : // check whether the tls programs need to be switched
856 56136501 : myLogics->check2Switch(myStep);
857 :
858 56136501 : if (MSGlobals::gUseMesoSim) {
859 15347565 : MSGlobals::gMesoNet->simulate(myStep);
860 : } else {
861 : // assure all lanes with vehicles are 'active'
862 40788936 : myEdges->patchActiveLanes();
863 :
864 : // compute safe velocities for all vehicles for the next few lanes
865 : // also register ApproachingVehicleInformation for all links
866 40788936 : myEdges->planMovements(myStep);
867 :
868 : // register junction approaches based on planned velocities as basis for right-of-way decision
869 40788936 : myEdges->setJunctionApproaches();
870 :
871 : // decide right-of-way and execute movements
872 40788936 : myEdges->executeMovements(myStep);
873 40788933 : if (MSGlobals::gCheck4Accidents) {
874 40788933 : myEdges->detectCollisions(myStep, STAGE_MOVEMENTS);
875 : }
876 :
877 : // vehicles may change lanes
878 40788933 : myEdges->changeLanes(myStep);
879 :
880 40788933 : if (MSGlobals::gCheck4Accidents) {
881 40788933 : myEdges->detectCollisions(myStep, STAGE_LANECHANGE);
882 : }
883 : }
884 : // flush arrived meso vehicles and micro vehicles that were removed due to collision
885 56136498 : myVehicleControl->removePending();
886 56136498 : loadRoutes();
887 :
888 : // persons
889 56136482 : if (myPersonControl != nullptr && myPersonControl->hasTransportables()) {
890 5418941 : myPersonControl->checkWaiting(this, myStep);
891 : }
892 : // containers
893 56136426 : if (myContainerControl != nullptr && myContainerControl->hasTransportables()) {
894 2868431 : myContainerControl->checkWaiting(this, myStep);
895 : }
896 56136426 : if (MSRailSignalControl::hasInstance()) {
897 8693750 : MSRailSignalControl::getInstance().resetWaitRelations();
898 : // preserve waitRelation from insertion for the next step
899 : }
900 : // insert vehicles
901 56136426 : myInserter->determineCandidates(myStep);
902 56136379 : myInsertionEvents->execute(myStep);
903 : #ifdef HAVE_FOX
904 56136284 : MSRoutingEngine::waitForAll();
905 : #endif
906 56136260 : myInserter->emitVehicles(myStep);
907 56136111 : if (MSGlobals::gCheck4Accidents && !MSGlobals::gUseMesoSim) {
908 : //myEdges->patchActiveLanes(); // @note required to detect collisions on lanes that were empty before insertion. wasteful?
909 40788655 : myEdges->detectCollisions(myStep, STAGE_INSERTIONS);
910 : }
911 56136111 : MSVehicleTransfer::getInstance()->checkInsertions(myStep);
912 :
913 : // execute endOfTimestepEvents
914 56136111 : myEndOfTimestepEvents->execute(myStep);
915 :
916 56136102 : if (myLogExecutionTime) {
917 27211586 : myTraCIStepDuration -= SysUtils::getCurrentMillis();
918 : }
919 56136102 : if (onlyMove) {
920 4 : myStepCompletionMissing = true;
921 4 : return;
922 : }
923 56136098 : if (t != nullptr && lastTraCICmd == libsumo::CMD_EXECUTEMOVE) {
924 6 : t->processCommands(myStep, true);
925 : }
926 56136098 : postMoveStep();
927 : }
928 :
929 :
930 : void
931 56136102 : MSNet::postMoveStep() {
932 56136102 : const int numControlled = libsumo::Helper::postProcessRemoteControl();
933 56136102 : if (numControlled > 0 && MSGlobals::gCheck4Accidents) {
934 1928301 : myEdges->detectCollisions(myStep, STAGE_REMOTECONTROL);
935 : }
936 56136102 : if (myLogExecutionTime) {
937 27211586 : myTraCIStepDuration += SysUtils::getCurrentMillis();
938 27211586 : myTraCIMillis += myTraCIStepDuration;
939 : }
940 56136102 : if (MSGlobals::gCheck4Accidents && !MSGlobals::gUseMesoSim) {
941 : // collisions from the previous step were kept to avoid duplicate
942 : // warnings. we must remove them now to ensure correct output.
943 40788650 : removeOutdatedCollisions();
944 : }
945 : // update and write (if needed) detector values
946 56136102 : mySimStepDuration = SysUtils::getCurrentMillis() - mySimStepDuration;
947 56136102 : writeOutput();
948 :
949 56136086 : if (myLogExecutionTime) {
950 27211586 : myVehiclesMoved += myVehicleControl->getRunningVehicleNo();
951 27211586 : if (myPersonControl != nullptr) {
952 4646149 : myPersonsMoved += myPersonControl->getRunningNumber();
953 : }
954 : }
955 56136086 : myStep += DELTA_T;
956 56136086 : }
957 :
958 :
959 : MSNet::SimulationState
960 56040036 : MSNet::simulationState(SUMOTime stopTime) const {
961 56040036 : if (TraCIServer::wasClosed()) {
962 : return SIMSTATE_CONNECTION_CLOSED;
963 : }
964 56037268 : if (TraCIServer::getInstance() != nullptr && !TraCIServer::getInstance()->getLoadArgs().empty()) {
965 : return SIMSTATE_LOADING;
966 : }
967 56037255 : if ((stopTime < 0 || myStep > stopTime) && TraCIServer::getInstance() == nullptr && (stopTime > 0 || myStep > myEdgeDataEndTime)) {
968 29301423 : if ((myVehicleControl->getActiveVehicleCount() == 0)
969 6126875 : && (myInserter->getPendingFlowCount() == 0)
970 1940073 : && (myPersonControl == nullptr || !myPersonControl->hasNonWaiting())
971 409188 : && (myContainerControl == nullptr || !myContainerControl->hasNonWaiting())
972 29362729 : && !MSDevice_Taxi::hasServableReservations()) {
973 : return SIMSTATE_NO_FURTHER_VEHICLES;
974 : }
975 : }
976 55991457 : if (stopTime >= 0 && myStep >= stopTime) {
977 : return SIMSTATE_END_STEP_REACHED;
978 : }
979 55970893 : if (myMaxTeleports >= 0 && myVehicleControl->getTeleportCount() > myMaxTeleports) {
980 : return SIMSTATE_TOO_MANY_TELEPORTS;
981 : }
982 55970885 : if (myAmInterrupted) {
983 6 : return SIMSTATE_INTERRUPTED;
984 : }
985 : return SIMSTATE_RUNNING;
986 : }
987 :
988 :
989 : MSNet::SimulationState
990 56031784 : MSNet::adaptToState(MSNet::SimulationState state, const bool isLibsumo) const {
991 56031784 : if (state == SIMSTATE_LOADING) {
992 13 : OptionsIO::setArgs(TraCIServer::getInstance()->getLoadArgs());
993 : TraCIServer::getInstance()->getLoadArgs().clear();
994 56031771 : } else if (state != SIMSTATE_RUNNING && ((TraCIServer::getInstance() != nullptr && !TraCIServer::wasClosed()) || isLibsumo)) {
995 : // overrides SIMSTATE_END_STEP_REACHED, e.g. (TraCI / Libsumo ignore SUMO's --end option)
996 23052 : return SIMSTATE_RUNNING;
997 56008719 : } else if (state == SIMSTATE_NO_FURTHER_VEHICLES) {
998 27757 : if (myPersonControl != nullptr) {
999 6804 : myPersonControl->abortAnyWaitingForVehicle();
1000 : }
1001 27757 : if (myContainerControl != nullptr) {
1002 1863 : myContainerControl->abortAnyWaitingForVehicle();
1003 : }
1004 27757 : myVehicleControl->abortWaiting();
1005 : }
1006 : return state;
1007 : }
1008 :
1009 :
1010 : std::string
1011 39088 : MSNet::getStateMessage(MSNet::SimulationState state) {
1012 39088 : switch (state) {
1013 : case MSNet::SIMSTATE_RUNNING:
1014 437 : return "";
1015 : case MSNet::SIMSTATE_END_STEP_REACHED:
1016 7880 : return TL("The final simulation step has been reached.");
1017 : case MSNet::SIMSTATE_NO_FURTHER_VEHICLES:
1018 28114 : return TL("All vehicles have left the simulation.");
1019 : case MSNet::SIMSTATE_CONNECTION_CLOSED:
1020 2632 : return TL("TraCI requested termination.");
1021 : case MSNet::SIMSTATE_ERROR_IN_SIM:
1022 0 : return TL("An error occurred (see log).");
1023 : case MSNet::SIMSTATE_INTERRUPTED:
1024 6 : return TL("Interrupted.");
1025 : case MSNet::SIMSTATE_TOO_MANY_TELEPORTS:
1026 6 : return TL("Too many teleports.");
1027 : case MSNet::SIMSTATE_LOADING:
1028 13 : return TL("TraCI issued load command.");
1029 : default:
1030 0 : return TL("Unknown reason.");
1031 : }
1032 : }
1033 :
1034 :
1035 : void
1036 41448 : MSNet::clearAll() {
1037 : // clear container
1038 41448 : MSEdge::clear();
1039 41448 : MSLane::clear();
1040 41448 : MSRoute::clear();
1041 41448 : delete MSVehicleTransfer::getInstance();
1042 41448 : MSDevice::cleanupAll();
1043 41448 : MSCalibrator::cleanup();
1044 83395 : while (!MSLaneSpeedTrigger::getInstances().empty()) {
1045 499 : delete MSLaneSpeedTrigger::getInstances().begin()->second;
1046 : }
1047 45513 : while (!MSTriggeredRerouter::getInstances().empty()) {
1048 4065 : delete MSTriggeredRerouter::getInstances().begin()->second;
1049 : }
1050 41448 : MSDevice_BTsender::cleanup();
1051 41448 : MSDevice_SSM::cleanup();
1052 41448 : MSDevice_ToC::cleanup();
1053 41448 : MSStopOut::cleanup();
1054 41448 : MSRailSignalConstraint::cleanup();
1055 41448 : MSRailSignalControl::cleanup();
1056 41448 : MSDriveWay::cleanup();
1057 : TraCIServer* t = TraCIServer::getInstance();
1058 41448 : if (t != nullptr) {
1059 2755 : t->cleanup();
1060 : }
1061 41448 : libsumo::Helper::cleanup();
1062 41448 : OutputDevice::closeAll(true);
1063 41448 : }
1064 :
1065 :
1066 : void
1067 168 : MSNet::clearState(const SUMOTime step, bool quickReload) {
1068 168 : MSGlobals::gClearState = true;
1069 168 : if (MSGlobals::gUseMesoSim) {
1070 16 : MSGlobals::gMesoNet->clearState();
1071 750 : for (MSEdge* const edge : MSEdge::getAllEdges()) {
1072 1488 : for (MESegment* s = MSGlobals::gMesoNet->getSegmentForEdge(*edge); s != nullptr; s = s->getNextSegment()) {
1073 754 : s->clearState();
1074 : }
1075 : }
1076 : } else {
1077 7336 : for (MSEdge* const edge : MSEdge::getAllEdges()) {
1078 15576 : for (MSLane* const lane : edge->getLanes()) {
1079 8544 : lane->getVehiclesSecure();
1080 8544 : lane->clearState();
1081 8544 : lane->releaseVehicles();
1082 : }
1083 7032 : edge->clearState();
1084 : }
1085 : }
1086 168 : myInserter->clearState();
1087 : // detectors may still reference persons/vehicles
1088 168 : myDetectorControl->updateDetectors(myStep);
1089 168 : myDetectorControl->writeOutput(myStep, true);
1090 168 : myDetectorControl->clearState(step);
1091 :
1092 168 : if (myPersonControl != nullptr) {
1093 23 : myPersonControl->clearState();
1094 : }
1095 168 : if (myContainerControl != nullptr) {
1096 0 : myContainerControl->clearState();
1097 : }
1098 : // delete vtypes after transportables have removed their types
1099 168 : myVehicleControl->clearState(true);
1100 168 : MSVehicleTransfer::getInstance()->clearState();
1101 168 : myLogics->clearState(step, quickReload);
1102 : // delete all routes after vehicles and detector output is done
1103 168 : MSRoute::dict_clearState();
1104 209 : for (auto& item : myStoppingPlaces) {
1105 82 : for (auto& item2 : item.second) {
1106 41 : item2.second->clearState();
1107 : }
1108 : }
1109 168 : myShapeContainer->clearState();
1110 168 : myBeginOfTimestepEvents->clearState(myStep, step);
1111 168 : myEndOfTimestepEvents->clearState(myStep, step);
1112 168 : myInsertionEvents->clearState(myStep, step);
1113 168 : MSRailSignalControl::clearState();
1114 168 : MSDriveWay::clearState();
1115 168 : myStep = step;
1116 168 : MSGlobals::gClearState = false;
1117 168 : }
1118 :
1119 :
1120 : void
1121 56136102 : MSNet::writeOutput() {
1122 : // update detector values
1123 56136102 : myDetectorControl->updateDetectors(myStep);
1124 56136093 : const OptionsCont& oc = OptionsCont::getOptions();
1125 :
1126 : // check state dumps
1127 112272186 : if (oc.isSet("netstate-dump")) {
1128 12936 : MSXMLRawOut::write(OutputDevice::getDeviceByOption("netstate-dump"), *myEdges, myStep,
1129 : oc.getInt("netstate-dump.precision"));
1130 : }
1131 :
1132 : // check fcd dumps
1133 112272186 : if (OptionsCont::getOptions().isSet("fcd-output")) {
1134 10089118 : if (OptionsCont::getOptions().isSet("person-fcd-output")) {
1135 24 : MSFCDExport::write(OutputDevice::getDeviceByOption("fcd-output"), myStep, SUMO_TAG_VEHICLE);
1136 48 : MSFCDExport::write(OutputDevice::getDeviceByOption("person-fcd-output"), myStep, SUMO_TAG_PERSON);
1137 : } else {
1138 10089070 : MSFCDExport::write(OutputDevice::getDeviceByOption("fcd-output"), myStep);
1139 : }
1140 : }
1141 :
1142 : // check emission dumps
1143 112272186 : if (OptionsCont::getOptions().isSet("emission-output")) {
1144 215992 : MSEmissionExport::write(OutputDevice::getDeviceByOption("emission-output"), myStep);
1145 : }
1146 :
1147 : // battery dumps
1148 112272186 : if (OptionsCont::getOptions().isSet("battery-output")) {
1149 140804 : MSBatteryExport::write(OutputDevice::getDeviceByOption("battery-output"), myStep,
1150 : oc.getInt("battery-output.precision"));
1151 : }
1152 :
1153 : // charging station aggregated dumps
1154 56223481 : if (OptionsCont::getOptions().isSet("chargingstations-output") && OptionsCont::getOptions().getBool("chargingstations-output.aggregated")) {
1155 22248 : MSChargingStationExport::write(OutputDevice::getDeviceByOption("chargingstations-output"));
1156 : }
1157 :
1158 : // elecHybrid dumps
1159 112272186 : if (OptionsCont::getOptions().isSet("elechybrid-output")) {
1160 450 : std::string output = OptionsCont::getOptions().getString("elechybrid-output");
1161 :
1162 900 : if (oc.getBool("elechybrid-output.aggregated")) {
1163 : // build a xml file with aggregated device.elechybrid output
1164 600 : MSElecHybridExport::writeAggregated(OutputDevice::getDeviceByOption("elechybrid-output"), myStep,
1165 : oc.getInt("elechybrid-output.precision"));
1166 : } else {
1167 : // build a separate xml file for each vehicle equipped with device.elechybrid
1168 : // RICE_TODO: Does this have to be placed here in MSNet.cpp ?
1169 150 : MSVehicleControl& vc = MSNet::getInstance()->getVehicleControl();
1170 204 : for (MSVehicleControl::constVehIt it = vc.loadedVehBegin(); it != vc.loadedVehEnd(); ++it) {
1171 54 : const SUMOVehicle* veh = it->second;
1172 54 : if (!veh->isOnRoad()) {
1173 0 : continue;
1174 : }
1175 54 : if (static_cast<MSDevice_ElecHybrid*>(veh->getDevice(typeid(MSDevice_ElecHybrid))) != nullptr) {
1176 : std::string vehID = veh->getID();
1177 54 : std::string filename2 = output + "_" + vehID + ".xml";
1178 54 : OutputDevice& dev = OutputDevice::getDevice(filename2);
1179 : std::map<SumoXMLAttr, std::string> attrs;
1180 54 : attrs[SUMO_ATTR_VEHICLE] = vehID;
1181 54 : attrs[SUMO_ATTR_MAXIMUMBATTERYCAPACITY] = toString(dynamic_cast<MSDevice_ElecHybrid*>(veh->getDevice(typeid(MSDevice_ElecHybrid)))->getMaximumBatteryCapacity());
1182 54 : attrs[SUMO_ATTR_RECUPERATIONENABLE] = toString(MSGlobals::gOverheadWireRecuperation);
1183 108 : dev.writeXMLHeader("elecHybrid-export", "", attrs);
1184 108 : MSElecHybridExport::write(OutputDevice::getDevice(filename2), veh, myStep, oc.getInt("elechybrid-output.precision"));
1185 : }
1186 : }
1187 : }
1188 : }
1189 :
1190 :
1191 : // check full dumps
1192 112272186 : if (OptionsCont::getOptions().isSet("full-output")) {
1193 1138 : MSGlobals::gHaveEmissions = true;
1194 2276 : MSFullExport::write(OutputDevice::getDeviceByOption("full-output"), myStep);
1195 : }
1196 :
1197 : // check queue dumps
1198 112272186 : if (OptionsCont::getOptions().isSet("queue-output")) {
1199 325614 : MSQueueExport::write(OutputDevice::getDeviceByOption("queue-output"), myStep);
1200 : }
1201 :
1202 : // check amitran dumps
1203 112272186 : if (OptionsCont::getOptions().isSet("amitran-output")) {
1204 2040 : MSAmitranTrajectories::write(OutputDevice::getDeviceByOption("amitran-output"), myStep);
1205 : }
1206 :
1207 : // check vtk dumps
1208 112272186 : if (OptionsCont::getOptions().isSet("vtk-output")) {
1209 :
1210 60 : if (MSNet::getInstance()->getVehicleControl().getRunningVehicleNo() > 0) {
1211 60 : std::string timestep = time2string(myStep);
1212 60 : if (TS >= 1.0) {
1213 48 : timestep = timestep.substr(0, timestep.length() - 3);
1214 36 : } else if (DELTA_T % 100 == 0) {
1215 72 : timestep = timestep.substr(0, timestep.length() - 1);
1216 : }
1217 66 : std::string output = OptionsCont::getOptions().getString("vtk-output");
1218 66 : std::string filename = output + "_" + timestep + ".vtp";
1219 :
1220 60 : OutputDevice_File dev(filename);
1221 :
1222 : //build a huge mass of xml files
1223 54 : MSVTKExport::write(dev, myStep);
1224 :
1225 54 : }
1226 :
1227 : }
1228 :
1229 56136087 : writeSummaryOutput();
1230 :
1231 : // write detector values
1232 56136087 : myDetectorControl->writeOutput(myStep + DELTA_T, false);
1233 :
1234 : // write link states
1235 112272172 : if (OptionsCont::getOptions().isSet("link-output")) {
1236 4048 : OutputDevice& od = OutputDevice::getDeviceByOption("link-output");
1237 4048 : od.openTag("timestep");
1238 4048 : od.writeAttr(SUMO_ATTR_ID, STEPS2TIME(myStep));
1239 85848 : for (const MSEdge* const edge : myEdges->getEdges()) {
1240 180200 : for (const MSLane* const lane : edge->getLanes()) {
1241 212304 : for (const MSLink* const link : lane->getLinkCont()) {
1242 227808 : link->writeApproaching(od, lane->getID());
1243 : }
1244 : }
1245 : }
1246 8096 : od.closeTag();
1247 : }
1248 :
1249 : // write SSM output
1250 58668988 : for (MSDevice_SSM* dev : MSDevice_SSM::getInstances()) {
1251 2532902 : dev->updateAndWriteOutput();
1252 : }
1253 :
1254 : // write ToC output
1255 56151805 : for (MSDevice_ToC* dev : MSDevice_ToC::getInstances()) {
1256 15719 : if (dev->generatesOutput()) {
1257 15513 : dev->writeOutput();
1258 : }
1259 : }
1260 :
1261 112272172 : if (OptionsCont::getOptions().isSet("collision-output")) {
1262 10356 : writeCollisions();
1263 : }
1264 56136086 : }
1265 :
1266 :
1267 : bool
1268 0 : MSNet::logSimulationDuration() const {
1269 0 : return myLogExecutionTime;
1270 : }
1271 :
1272 :
1273 : MSTransportableControl&
1274 26788986 : MSNet::getPersonControl() {
1275 26788986 : if (myPersonControl == nullptr) {
1276 6618 : myPersonControl = new MSTransportableControl(true);
1277 : }
1278 26788962 : return *myPersonControl;
1279 : }
1280 :
1281 :
1282 : MSTransportableControl&
1283 4915108 : MSNet::getContainerControl() {
1284 4915108 : if (myContainerControl == nullptr) {
1285 1782 : myContainerControl = new MSTransportableControl(false);
1286 : }
1287 4915108 : return *myContainerControl;
1288 : }
1289 :
1290 : MSDynamicShapeUpdater*
1291 23 : MSNet::makeDynamicShapeUpdater() {
1292 23 : myDynamicShapeUpdater = std::unique_ptr<MSDynamicShapeUpdater> (new MSDynamicShapeUpdater(*myShapeContainer));
1293 23 : return myDynamicShapeUpdater.get();
1294 : }
1295 :
1296 : MSEdgeWeightsStorage&
1297 6932926 : MSNet::getWeightsStorage() {
1298 6932926 : if (myEdgeWeights == nullptr) {
1299 1879 : myEdgeWeights = new MSEdgeWeightsStorage();
1300 : }
1301 6932926 : return *myEdgeWeights;
1302 : }
1303 :
1304 :
1305 : void
1306 127 : MSNet::preSimStepOutput() const {
1307 127 : std::cout << "Step #" << time2string(myStep);
1308 127 : }
1309 :
1310 :
1311 : void
1312 127 : MSNet::postSimStepOutput() const {
1313 127 : if (myLogExecutionTime) {
1314 125 : std::ostringstream oss;
1315 : oss.setf(std::ios::fixed, std::ios::floatfield); // use decimal format
1316 : oss.setf(std::ios::showpoint); // print decimal point
1317 125 : oss << std::setprecision(gPrecision);
1318 125 : if (mySimStepDuration != 0) {
1319 71 : const double durationSec = (double)mySimStepDuration / 1000.;
1320 71 : oss << " (" << mySimStepDuration << "ms ~= "
1321 71 : << (TS / durationSec) << "*RT, ~"
1322 71 : << ((double) myVehicleControl->getRunningVehicleNo() / durationSec);
1323 : } else {
1324 54 : oss << " (0ms ?*RT. ?";
1325 : }
1326 125 : oss << "UPS, ";
1327 125 : if (TraCIServer::getInstance() != nullptr) {
1328 79 : oss << "TraCI: " << myTraCIStepDuration << "ms, ";
1329 : }
1330 125 : oss << "vehicles TOT " << myVehicleControl->getDepartedVehicleNo()
1331 250 : << " ACT " << myVehicleControl->getRunningVehicleNo()
1332 125 : << " BUF " << myInserter->getWaitingVehicleNo()
1333 125 : << ") ";
1334 250 : std::string prev = "Step #" + time2string(myStep - DELTA_T);
1335 250 : std::cout << oss.str().substr(0, 90 - prev.length());
1336 125 : }
1337 127 : std::cout << '\r';
1338 127 : }
1339 :
1340 :
1341 : void
1342 11387 : MSNet::addVehicleStateListener(VehicleStateListener* listener) {
1343 11387 : if (find(myVehicleStateListeners.begin(), myVehicleStateListeners.end(), listener) == myVehicleStateListeners.end()) {
1344 11387 : myVehicleStateListeners.push_back(listener);
1345 : }
1346 11387 : }
1347 :
1348 :
1349 : void
1350 58 : MSNet::removeVehicleStateListener(VehicleStateListener* listener) {
1351 58 : std::vector<VehicleStateListener*>::iterator i = std::find(myVehicleStateListeners.begin(), myVehicleStateListeners.end(), listener);
1352 58 : if (i != myVehicleStateListeners.end()) {
1353 58 : myVehicleStateListeners.erase(i);
1354 : }
1355 58 : }
1356 :
1357 :
1358 : void
1359 15510250 : MSNet::informVehicleStateListener(const SUMOVehicle* const vehicle, VehicleState to, const std::string& info) {
1360 : #ifdef HAVE_FOX
1361 15510250 : ScopedLocker<> lock(myVehicleStateListenerMutex, MSGlobals::gNumThreads > 1);
1362 : #endif
1363 16196052 : for (VehicleStateListener* const listener : myVehicleStateListeners) {
1364 685802 : listener->vehicleStateChanged(vehicle, to, info);
1365 : }
1366 15510250 : }
1367 :
1368 :
1369 : void
1370 3899 : MSNet::addTransportableStateListener(TransportableStateListener* listener) {
1371 3899 : if (find(myTransportableStateListeners.begin(), myTransportableStateListeners.end(), listener) == myTransportableStateListeners.end()) {
1372 3899 : myTransportableStateListeners.push_back(listener);
1373 : }
1374 3899 : }
1375 :
1376 :
1377 : void
1378 0 : MSNet::removeTransportableStateListener(TransportableStateListener* listener) {
1379 0 : std::vector<TransportableStateListener*>::iterator i = std::find(myTransportableStateListeners.begin(), myTransportableStateListeners.end(), listener);
1380 0 : if (i != myTransportableStateListeners.end()) {
1381 0 : myTransportableStateListeners.erase(i);
1382 : }
1383 0 : }
1384 :
1385 :
1386 : void
1387 889070 : MSNet::informTransportableStateListener(const MSTransportable* const transportable, TransportableState to, const std::string& info) {
1388 : #ifdef HAVE_FOX
1389 889070 : ScopedLocker<> lock(myTransportableStateListenerMutex, MSGlobals::gNumThreads > 1);
1390 : #endif
1391 891826 : for (TransportableStateListener* const listener : myTransportableStateListeners) {
1392 2756 : listener->transportableStateChanged(transportable, to, info);
1393 : }
1394 889070 : }
1395 :
1396 :
1397 : bool
1398 10864 : MSNet::registerCollision(const SUMOTrafficObject* collider, const SUMOTrafficObject* victim, const std::string& collisionType, const MSLane* lane, double pos) {
1399 : auto it = myCollisions.find(collider->getID());
1400 10864 : if (it != myCollisions.end()) {
1401 5171 : for (Collision& old : it->second) {
1402 5063 : if (old.victim == victim->getID()) {
1403 : // collision from previous step continues
1404 4282 : old.continuationTime = myStep;
1405 : return false;
1406 : }
1407 : }
1408 : } else {
1409 : // maybe the roles have been reversed
1410 : auto it2 = myCollisions.find(victim->getID());
1411 6474 : if (it2 != myCollisions.end()) {
1412 521 : for (Collision& old : it2->second) {
1413 360 : if (old.victim == collider->getID()) {
1414 : // collision from previous step continues (keep the old roles)
1415 196 : old.continuationTime = myStep;
1416 : return false;
1417 : }
1418 : }
1419 : }
1420 : }
1421 : Collision c;
1422 : c.victim = victim->getID();
1423 6386 : c.colliderType = collider->getVehicleType().getID();
1424 6386 : c.victimType = victim->getVehicleType().getID();
1425 6386 : c.colliderSpeed = collider->getSpeed();
1426 6386 : c.victimSpeed = victim->getSpeed();
1427 6386 : c.colliderFront = collider->getPosition();
1428 6386 : c.victimFront = victim->getPosition();
1429 6386 : c.colliderBack = collider->getPosition(-collider->getVehicleType().getLength());
1430 6386 : c.victimBack = victim->getPosition(-victim->getVehicleType().getLength());
1431 : c.type = collisionType;
1432 6386 : c.lane = lane;
1433 6386 : c.pos = pos;
1434 6386 : c.time = myStep;
1435 6386 : c.continuationTime = myStep;
1436 6386 : myCollisions[collider->getID()].push_back(c);
1437 : return true;
1438 6386 : }
1439 :
1440 :
1441 : void
1442 40788650 : MSNet::removeOutdatedCollisions() {
1443 40803409 : for (auto it = myCollisions.begin(); it != myCollisions.end();) {
1444 29738 : for (auto it2 = it->second.begin(); it2 != it->second.end();) {
1445 14979 : if (it2->continuationTime != myStep) {
1446 6376 : it2 = it->second.erase(it2);
1447 : } else {
1448 : it2++;
1449 : }
1450 : }
1451 14759 : if (it->second.size() == 0) {
1452 : it = myCollisions.erase(it);
1453 : } else {
1454 : it++;
1455 : }
1456 : }
1457 40788650 : }
1458 :
1459 :
1460 : bool
1461 83766 : MSNet::addStoppingPlace(SumoXMLTag category, MSStoppingPlace* stop) {
1462 83766 : if (category == SUMO_TAG_TRAIN_STOP) {
1463 14037 : category = SUMO_TAG_BUS_STOP;
1464 : }
1465 83766 : const bool isNew = myStoppingPlaces[category].add(stop->getID(), stop);
1466 83766 : if (isNew && stop->getMyName() != "") {
1467 15959 : myNamedStoppingPlaces[category][stop->getMyName()].push_back(stop);
1468 : }
1469 83766 : return isNew;
1470 : }
1471 :
1472 :
1473 : bool
1474 17 : MSNet::addTractionSubstation(MSTractionSubstation* substation) {
1475 17 : if (find(myTractionSubstations.begin(), myTractionSubstations.end(), substation) == myTractionSubstations.end()) {
1476 17 : myTractionSubstations.push_back(substation);
1477 17 : return true;
1478 : }
1479 : return false;
1480 : }
1481 :
1482 :
1483 : MSStoppingPlace*
1484 1590035 : MSNet::getStoppingPlace(const std::string& id, const SumoXMLTag category) const {
1485 : if (myStoppingPlaces.count(category) > 0) {
1486 : return myStoppingPlaces.find(category)->second.get(id);
1487 : }
1488 : return nullptr;
1489 : }
1490 :
1491 :
1492 : MSStoppingPlace*
1493 172386 : MSNet::getStoppingPlace(const std::string& id) const {
1494 855359 : 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})) {
1495 719275 : MSStoppingPlace* result = getStoppingPlace(id, category);
1496 719275 : if (result != nullptr) {
1497 : return result;
1498 : }
1499 172386 : }
1500 136084 : return nullptr;
1501 : }
1502 :
1503 :
1504 : std::string
1505 459403 : MSNet::getStoppingPlaceID(const MSLane* lane, const double pos, const SumoXMLTag category) const {
1506 : if (myStoppingPlaces.count(category) > 0) {
1507 925554 : for (const auto& it : myStoppingPlaces.find(category)->second) {
1508 850260 : MSStoppingPlace* stop = it.second;
1509 850260 : if (&stop->getLane() == lane && stop->getBeginLanePosition() - POSITION_EPS <= pos && stop->getEndLanePosition() + POSITION_EPS >= pos) {
1510 : return stop->getID();
1511 : }
1512 : }
1513 : }
1514 354985 : return "";
1515 : }
1516 :
1517 :
1518 : const std::vector<MSStoppingPlace*>&
1519 1583 : MSNet::getStoppingPlaceAlternatives(const std::string& name, SumoXMLTag category) const {
1520 1583 : if (category == SUMO_TAG_TRAIN_STOP) {
1521 : category = SUMO_TAG_BUS_STOP;
1522 : }
1523 : auto it = myNamedStoppingPlaces.find(category);
1524 1583 : if (it != myNamedStoppingPlaces.end()) {
1525 : auto it2 = it->second.find(name);
1526 1515 : if (it2 != it->second.end()) {
1527 1515 : return it2->second;
1528 : }
1529 : }
1530 : return myEmptyStoppingPlaceVector;
1531 : }
1532 :
1533 :
1534 : const NamedObjectCont<MSStoppingPlace*>&
1535 14009 : MSNet::getStoppingPlaces(SumoXMLTag category) const {
1536 : auto it = myStoppingPlaces.find(category);
1537 14009 : if (it != myStoppingPlaces.end()) {
1538 13724 : return it->second;
1539 : } else {
1540 : return myEmptyStoppingPlaceCont;
1541 : }
1542 : }
1543 :
1544 :
1545 : void
1546 94 : MSNet::writeChargingStationOutput() const {
1547 : if (myStoppingPlaces.count(SUMO_TAG_CHARGING_STATION) > 0) {
1548 180 : OutputDevice& output = OutputDevice::getDeviceByOption("chargingstations-output");
1549 538 : for (const auto& it : myStoppingPlaces.find(SUMO_TAG_CHARGING_STATION)->second) {
1550 448 : static_cast<MSChargingStation*>(it.second)->writeChargingStationOutput(output);
1551 : }
1552 : }
1553 94 : }
1554 :
1555 :
1556 : void
1557 39692 : MSNet::writeRailSignalBlocks() const {
1558 79384 : if (OptionsCont::getOptions().isSet("railsignal-block-output")) {
1559 1352 : OutputDevice& output = OutputDevice::getDeviceByOption("railsignal-block-output");
1560 5368 : for (auto tls : myLogics->getAllLogics()) {
1561 4016 : MSRailSignal* rs = dynamic_cast<MSRailSignal*>(tls);
1562 4016 : if (rs != nullptr) {
1563 3972 : rs->writeBlocks(output, false);
1564 : }
1565 1352 : }
1566 1352 : MSDriveWay::writeDepatureBlocks(output, false);
1567 : }
1568 79384 : if (OptionsCont::getOptions().isSet("railsignal-vehicle-output")) {
1569 180 : OutputDevice& output = OutputDevice::getDeviceByOption("railsignal-vehicle-output");
1570 589 : for (auto tls : myLogics->getAllLogics()) {
1571 409 : MSRailSignal* rs = dynamic_cast<MSRailSignal*>(tls);
1572 409 : if (rs != nullptr) {
1573 409 : rs->writeBlocks(output, true);
1574 : }
1575 180 : }
1576 180 : MSDriveWay::writeDepatureBlocks(output, true);
1577 : }
1578 39692 : }
1579 :
1580 :
1581 : void
1582 5 : MSNet::writeOverheadWireSegmentOutput() const {
1583 : if (myStoppingPlaces.count(SUMO_TAG_OVERHEAD_WIRE_SEGMENT) > 0) {
1584 10 : OutputDevice& output = OutputDevice::getDeviceByOption("overheadwiresegments-output");
1585 53 : for (const auto& it : myStoppingPlaces.find(SUMO_TAG_OVERHEAD_WIRE_SEGMENT)->second) {
1586 48 : static_cast<MSOverheadWire*>(it.second)->writeOverheadWireSegmentOutput(output);
1587 : }
1588 : }
1589 5 : }
1590 :
1591 :
1592 : void
1593 5 : MSNet::writeSubstationOutput() const {
1594 5 : if (myTractionSubstations.size() > 0) {
1595 5 : OutputDevice& output = OutputDevice::getDeviceByOption("substations-output");
1596 10 : output.setPrecision(OptionsCont::getOptions().getInt("substations-output.precision"));
1597 13 : for (auto& it : myTractionSubstations) {
1598 8 : it->writeTractionSubstationOutput(output);
1599 : }
1600 : }
1601 5 : }
1602 :
1603 :
1604 : MSTractionSubstation*
1605 19 : MSNet::findTractionSubstation(const std::string& substationId) {
1606 22 : for (std::vector<MSTractionSubstation*>::iterator it = myTractionSubstations.begin(); it != myTractionSubstations.end(); ++it) {
1607 22 : if ((*it)->getID() == substationId) {
1608 : return *it;
1609 : }
1610 : }
1611 : return nullptr;
1612 : }
1613 :
1614 :
1615 : MSVehicleRouter&
1616 124679 : MSNet::getRouterTT(int rngIndex, const Prohibitions& prohibited) const {
1617 124679 : if (MSGlobals::gNumSimThreads == 1) {
1618 106128 : rngIndex = 0;
1619 : }
1620 : if (myRouterTT.count(rngIndex) == 0) {
1621 1416 : const std::string routingAlgorithm = OptionsCont::getOptions().getString("routing-algorithm");
1622 1416 : if (routingAlgorithm == "dijkstra") {
1623 1321 : myRouterTT[rngIndex] = new DijkstraRouter<MSEdge, SUMOVehicle>(MSEdge::getAllEdges(), true, &MSNet::getTravelTime, nullptr, false, nullptr, true);
1624 : } else {
1625 95 : if (routingAlgorithm != "astar") {
1626 0 : WRITE_WARNINGF(TL("TraCI and Triggers cannot use routing algorithm '%'. using 'astar' instead."), routingAlgorithm);
1627 : }
1628 95 : myRouterTT[rngIndex] = new AStarRouter<MSEdge, SUMOVehicle, MSMapMatcher>(MSEdge::getAllEdges(), true, &MSNet::getTravelTime, nullptr, true);
1629 : }
1630 : }
1631 124679 : myRouterTT[rngIndex]->prohibit(prohibited);
1632 124679 : return *myRouterTT[rngIndex];
1633 : }
1634 :
1635 :
1636 : MSVehicleRouter&
1637 11 : MSNet::getRouterEffort(int rngIndex, const Prohibitions& prohibited) const {
1638 11 : if (MSGlobals::gNumSimThreads == 1) {
1639 11 : rngIndex = 0;
1640 : }
1641 : if (myRouterEffort.count(rngIndex) == 0) {
1642 11 : myRouterEffort[rngIndex] = new DijkstraRouter<MSEdge, SUMOVehicle>(MSEdge::getAllEdges(), true, &MSNet::getEffort, &MSNet::getTravelTime, false, nullptr, true);
1643 : }
1644 11 : myRouterEffort[rngIndex]->prohibit(prohibited);
1645 11 : return *myRouterEffort[rngIndex];
1646 : }
1647 :
1648 :
1649 : MSPedestrianRouter&
1650 816409 : MSNet::getPedestrianRouter(int rngIndex, const Prohibitions& prohibited) const {
1651 816409 : if (MSGlobals::gNumSimThreads == 1) {
1652 727694 : rngIndex = 0;
1653 : }
1654 : if (myPedestrianRouter.count(rngIndex) == 0) {
1655 2810 : myPedestrianRouter[rngIndex] = new MSPedestrianRouter();
1656 : }
1657 816409 : myPedestrianRouter[rngIndex]->prohibit(prohibited);
1658 816409 : return *myPedestrianRouter[rngIndex];
1659 : }
1660 :
1661 :
1662 : MSTransportableRouter&
1663 169043 : MSNet::getIntermodalRouter(int rngIndex, const int routingMode, const Prohibitions& prohibited) const {
1664 169043 : if (MSGlobals::gNumSimThreads == 1) {
1665 : rngIndex = 0;
1666 : }
1667 169043 : const OptionsCont& oc = OptionsCont::getOptions();
1668 169043 : const int key = rngIndex * oc.getInt("thread-rngs") + routingMode;
1669 : if (myIntermodalRouter.count(key) == 0) {
1670 4147 : const int carWalk = SUMOVehicleParserHelper::parseCarWalkTransfer(oc, MSDevice_Taxi::hasFleet() || myInserter->hasTaxiFlow());
1671 3946 : const std::string routingAlgorithm = OptionsCont::getOptions().getString("routing-algorithm");
1672 3946 : const double taxiWait = STEPS2TIME(string2time(OptionsCont::getOptions().getString("persontrip.taxi.waiting-time")));
1673 3946 : if (routingMode == libsumo::ROUTING_MODE_COMBINED) {
1674 0 : myIntermodalRouter[key] = new MSTransportableRouter(MSNet::adaptIntermodalRouter, carWalk, taxiWait, routingAlgorithm, routingMode, new FareModul());
1675 : } else {
1676 3946 : myIntermodalRouter[key] = new MSTransportableRouter(MSNet::adaptIntermodalRouter, carWalk, taxiWait, routingAlgorithm, routingMode);
1677 : }
1678 : }
1679 169043 : myIntermodalRouter[key]->prohibit(prohibited);
1680 169043 : return *myIntermodalRouter[key];
1681 : }
1682 :
1683 :
1684 : void
1685 41247 : MSNet::resetIntermodalRouter() const {
1686 45192 : for (auto& router : myIntermodalRouter) {
1687 3945 : delete router.second;
1688 : }
1689 : myIntermodalRouter.clear();
1690 41247 : }
1691 :
1692 :
1693 : void
1694 4898 : MSNet::adaptIntermodalRouter(MSTransportableRouter& router) {
1695 9796 : double taxiWait = STEPS2TIME(string2time(OptionsCont::getOptions().getString("persontrip.taxi.waiting-time")));
1696 : // add access to all parking areas
1697 : EffortCalculator* const external = router.getExternalEffort();
1698 14647 : for (const auto& stopType : myInstance->myStoppingPlaces) {
1699 : // add access to all stopping places
1700 9749 : const SumoXMLTag element = stopType.first;
1701 35921 : for (const auto& i : stopType.second) {
1702 26172 : const MSEdge* const edge = &i.second->getLane().getEdge();
1703 26172 : router.getNetwork()->addAccess(i.first, edge, i.second->getBeginLanePosition(), i.second->getEndLanePosition(),
1704 : 0., element, false, taxiWait);
1705 26172 : if (element == SUMO_TAG_BUS_STOP) {
1706 : // add access to all public transport stops
1707 12709 : for (const auto& a : i.second->getAllAccessPos()) {
1708 1153 : router.getNetwork()->addAccess(i.first, &a.lane->getEdge(), a.startPos, a.endPos, a.length, element, true, taxiWait);
1709 : }
1710 11556 : if (external != nullptr) {
1711 0 : external->addStop(router.getNetwork()->getStopEdge(i.first)->getNumericalID(), *i.second);
1712 : }
1713 : }
1714 : }
1715 : }
1716 4898 : myInstance->getInsertionControl().adaptIntermodalRouter(router);
1717 4898 : myInstance->getVehicleControl().adaptIntermodalRouter(router);
1718 : // add access to transfer from walking to taxi-use
1719 4898 : if ((router.getCarWalkTransfer() & ModeChangeOptions::TAXI_PICKUP_ANYWHERE) != 0) {
1720 59954 : for (MSEdge* edge : myInstance->getEdgeControl().getEdges()) {
1721 59725 : if ((edge->getPermissions() & SVC_PEDESTRIAN) != 0 && (edge->getPermissions() & SVC_TAXI) != 0) {
1722 21531 : router.getNetwork()->addCarAccess(edge, SVC_TAXI, taxiWait);
1723 : }
1724 : }
1725 : }
1726 4898 : }
1727 :
1728 :
1729 : bool
1730 41311 : MSNet::checkElevation() {
1731 41311 : const MSEdgeVector& edges = myEdges->getEdges();
1732 1781946 : for (MSEdgeVector::const_iterator e = edges.begin(); e != edges.end(); ++e) {
1733 3833335 : for (std::vector<MSLane*>::const_iterator i = (*e)->getLanes().begin(); i != (*e)->getLanes().end(); ++i) {
1734 2092700 : if ((*i)->getShape().hasElevation()) {
1735 : return true;
1736 : }
1737 : }
1738 : }
1739 : return false;
1740 : }
1741 :
1742 :
1743 : bool
1744 41311 : MSNet::checkWalkingarea() {
1745 1227146 : for (const MSEdge* e : myEdges->getEdges()) {
1746 1196335 : if (e->getFunction() == SumoXMLEdgeFunc::WALKINGAREA) {
1747 : return true;
1748 : }
1749 : }
1750 : return false;
1751 : }
1752 :
1753 :
1754 : bool
1755 41311 : MSNet::checkBidiEdges() {
1756 1721679 : for (const MSEdge* e : myEdges->getEdges()) {
1757 1681465 : if (e->getBidiEdge() != nullptr) {
1758 : return true;
1759 : }
1760 : }
1761 : return false;
1762 : }
1763 :
1764 : bool
1765 303 : MSNet::warnOnce(const std::string& typeAndID) {
1766 303 : if (myWarnedOnce.find(typeAndID) == myWarnedOnce.end()) {
1767 303 : myWarnedOnce[typeAndID] = true;
1768 303 : return true;
1769 : }
1770 : return false;
1771 : }
1772 :
1773 :
1774 : MSMapMatcher*
1775 35 : MSNet::getMapMatcher() const {
1776 35 : auto loader = myRouteLoaders->getFirstLoader();
1777 35 : if (loader != nullptr) {
1778 35 : return dynamic_cast<MSMapMatcher*>(loader->getRouteHandler());
1779 : } else {
1780 : return nullptr;
1781 : }
1782 : }
1783 :
1784 : void
1785 0 : MSNet::quickReload() {
1786 0 : const OptionsCont& oc = OptionsCont::getOptions();
1787 0 : clearState(string2time(oc.getString("begin")), true);
1788 0 : NLBuilder::initRandomness();
1789 : // load traffic from additional files
1790 0 : for (std::string file : oc.getStringVector("additional-files")) {
1791 : // ignore failure on parsing calibrator flow
1792 0 : MSRouteHandler rh(file, true);
1793 0 : const long before = PROGRESS_BEGIN_TIME_MESSAGE("Loading traffic from '" + file + "'");
1794 0 : if (!XMLSubSys::runParser(rh, file, false)) {
1795 0 : throw ProcessError(TLF("Loading of % failed.", file));
1796 : }
1797 0 : PROGRESS_TIME_MESSAGE(before);
1798 0 : }
1799 0 : delete myRouteLoaders;
1800 0 : myRouteLoaders = NLBuilder::buildRouteLoaderControl(OptionsCont::getOptions());
1801 0 : updateGUI();
1802 0 : }
1803 :
1804 :
1805 : SUMOTime
1806 176 : MSNet::loadState(const std::string& fileName, const bool catchExceptions) {
1807 : // load time only
1808 176 : const SUMOTime newTime = MSStateHandler::MSStateTimeHandler::getTime(fileName);
1809 : // clean up state
1810 168 : clearState(newTime);
1811 : // load state
1812 168 : MSStateHandler h(fileName, 0);
1813 168 : XMLSubSys::runParser(h, fileName, false, false, false, catchExceptions);
1814 164 : if (MsgHandler::getErrorInstance()->wasInformed()) {
1815 0 : throw ProcessError(TLF("Loading state from '%' failed.", fileName));
1816 : }
1817 : // reset route loaders
1818 164 : delete myRouteLoaders;
1819 164 : myRouteLoaders = NLBuilder::buildRouteLoaderControl(OptionsCont::getOptions());
1820 : // prevent loading errors on rewound route file
1821 164 : MSGlobals::gStateLoaded = true;
1822 :
1823 164 : updateGUI();
1824 164 : return newTime;
1825 168 : }
1826 :
1827 :
1828 : /****************************************************************************/
|