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