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