Line data Source code
1 : /****************************************************************************/
2 : // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
3 : // Copyright (C) 2001-2026 German Aerospace Center (DLR) and others.
4 : // This program and the accompanying materials are made available under the
5 : // terms of the Eclipse Public License 2.0 which is available at
6 : // https://www.eclipse.org/legal/epl-2.0/
7 : // This Source Code may also be made available under the following Secondary
8 : // Licenses when the conditions for such availability set forth in the Eclipse
9 : // Public License 2.0 are satisfied: GNU General Public License, version 2
10 : // or later which is available at
11 : // https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
12 : // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
13 : /****************************************************************************/
14 : /// @file MSVehicleControl.cpp
15 : /// @author Daniel Krajzewicz
16 : /// @author Jakob Erdmann
17 : /// @author Michael Behrisch
18 : /// @date Wed, 10. Dec 2003
19 : ///
20 : // The class responsible for building and deletion of vehicles
21 : /****************************************************************************/
22 : #include <config.h>
23 :
24 : #include "MSVehicleControl.h"
25 : #include "MSVehicle.h"
26 : #include "MSLane.h"
27 : #include "MSEdge.h"
28 : #include "MSNet.h"
29 : #include "MSRouteHandler.h"
30 : #include "MSEventControl.h"
31 : #include "MSStop.h"
32 : #include <microsim/devices/MSVehicleDevice.h>
33 : #include <microsim/devices/MSDevice_Tripinfo.h>
34 : #include <utils/common/FileHelpers.h>
35 : #include <utils/common/Named.h>
36 : #include <utils/common/RGBColor.h>
37 : #include <utils/vehicle/SUMOVTypeParameter.h>
38 : #include <utils/iodevices/OutputDevice.h>
39 : #include <utils/options/OptionsCont.h>
40 : #include <utils/router/IntermodalRouter.h>
41 :
42 :
43 : // ===========================================================================
44 : // member method definitions
45 : // ===========================================================================
46 42366 : MSVehicleControl::MSVehicleControl() :
47 42366 : myLoadedVehNo(0),
48 42366 : myRunningVehNo(0),
49 42366 : myEndedVehNo(0),
50 42366 : myDiscarded(0),
51 42366 : myCollisions(0),
52 42366 : myTeleportsCollision(0),
53 42366 : myTeleportsJam(0),
54 42366 : myTeleportsYield(0),
55 42366 : myTeleportsWrongLane(0),
56 42366 : myEmergencyStops(0),
57 42366 : myEmergencyBrakingCount(0),
58 42366 : myStoppedVehicles(0),
59 42366 : myTotalDepartureDelay(0),
60 42366 : myTotalTravelTime(0),
61 42366 : myWaitingForTransportable(0),
62 42366 : myMaxSpeedFactor(1),
63 42366 : myMinDeceleration(SUMOVTypeParameter::getDefaultDecel(SVC_IGNORING)),
64 42366 : myMinDecelerationRail(SUMOVTypeParameter::getDefaultDecel(SVC_RAIL)),
65 84732 : myPendingRemovals(MSGlobals::gNumSimThreads > 1) {
66 :
67 42366 : initDefaultTypes();
68 42366 : myScale = OptionsCont::getOptions().getFloat("scale");
69 42366 : myKeepTime = string2time(OptionsCont::getOptions().getString("keep-after-arrival"));
70 42366 : }
71 :
72 :
73 71002 : MSVehicleControl::~MSVehicleControl() {
74 41745 : clearState(false);
75 71002 : }
76 :
77 :
78 : void
79 42534 : MSVehicleControl::initDefaultTypes() {
80 42534 : SUMOVTypeParameter defType(DEFAULT_VTYPE_ID, SVC_PASSENGER);
81 42534 : myVTypeDict[DEFAULT_VTYPE_ID] = MSVehicleType::build(defType);
82 :
83 42534 : SUMOVTypeParameter defPedType(DEFAULT_PEDTYPE_ID, SVC_PEDESTRIAN);
84 42534 : defPedType.parametersSet |= VTYPEPARS_VEHICLECLASS_SET;
85 42534 : myVTypeDict[DEFAULT_PEDTYPE_ID] = MSVehicleType::build(defPedType);
86 :
87 42534 : SUMOVTypeParameter defBikeType(DEFAULT_BIKETYPE_ID, SVC_BICYCLE);
88 42534 : defBikeType.parametersSet |= VTYPEPARS_VEHICLECLASS_SET;
89 42534 : myVTypeDict[DEFAULT_BIKETYPE_ID] = MSVehicleType::build(defBikeType);
90 :
91 42534 : SUMOVTypeParameter defTaxiType(DEFAULT_TAXITYPE_ID, SVC_TAXI);
92 42534 : defTaxiType.parametersSet |= VTYPEPARS_VEHICLECLASS_SET;
93 42534 : myVTypeDict[DEFAULT_TAXITYPE_ID] = MSVehicleType::build(defTaxiType);
94 :
95 42534 : SUMOVTypeParameter defRailType(DEFAULT_RAILTYPE_ID, SVC_RAIL);
96 42534 : defRailType.parametersSet |= VTYPEPARS_VEHICLECLASS_SET;
97 42534 : myVTypeDict[DEFAULT_RAILTYPE_ID] = MSVehicleType::build(defRailType);
98 :
99 42534 : SUMOVTypeParameter defContainerType(DEFAULT_CONTAINERTYPE_ID, SVC_CONTAINER);
100 42534 : defContainerType.parametersSet |= VTYPEPARS_VEHICLECLASS_SET;
101 42534 : myVTypeDict[DEFAULT_CONTAINERTYPE_ID] = MSVehicleType::build(defContainerType);
102 :
103 : myReplaceableDefaultVTypes = DEFAULT_VTYPES;
104 42534 : }
105 :
106 :
107 : SUMOVehicle*
108 3858568 : MSVehicleControl::buildVehicle(SUMOVehicleParameter* defs,
109 : ConstMSRoutePtr route, MSVehicleType* type,
110 : const bool ignoreStopErrors, const VehicleDefinitionSource source, bool addRouteStops) {
111 3963536 : const double speedFactor = type->computeChosenSpeedDeviation(defs->speedFactor, source == VehicleDefinitionSource::ROUTEFILE ? MSRouteHandler::getParsingRNG() : nullptr);
112 7717136 : MSVehicle* built = new MSVehicle(defs, route, type, speedFactor);
113 3858568 : initVehicle(built, ignoreStopErrors, addRouteStops, source);
114 3858512 : return built;
115 : }
116 :
117 :
118 : void
119 5261700 : MSVehicleControl::initVehicle(MSBaseVehicle* built, const bool ignoreStopErrors, bool addRouteStops, const VehicleDefinitionSource source) {
120 5261700 : myLoadedVehNo++;
121 : try {
122 5261700 : built->initDevices();
123 5261661 : if (source != VehicleDefinitionSource::STATE) {
124 5256871 : built->addStops(ignoreStopErrors, nullptr, addRouteStops);
125 : }
126 116 : } catch (ProcessError&) {
127 116 : delete built;
128 116 : throw;
129 116 : }
130 5261583 : MSNet::getInstance()->informVehicleStateListener(built, MSNet::VehicleState::BUILT);
131 5261583 : }
132 :
133 :
134 : void
135 4022335 : MSVehicleControl::scheduleVehicleRemoval(SUMOVehicle* veh, bool checkDuplicate) {
136 : assert(myRunningVehNo > 0);
137 4022335 : if (!checkDuplicate || !isPendingRemoval(veh)) {
138 4022335 : myPendingRemovals.push_back(veh);
139 : }
140 4022335 : }
141 :
142 :
143 : bool
144 17549 : MSVehicleControl::isPendingRemoval(SUMOVehicle* veh) {
145 : #ifdef HAVE_FOX
146 17549 : return myPendingRemovals.contains(veh);
147 : #else
148 : return std::find(myPendingRemovals.begin(), myPendingRemovals.end(), veh) == myPendingRemovals.end();
149 : #endif
150 : }
151 :
152 :
153 : void
154 102306971 : MSVehicleControl::removePending() {
155 118482665 : OutputDevice* const tripinfoOut = OptionsCont::getOptions().isSet("tripinfo-output") ? &OutputDevice::getDeviceByOption("tripinfo-output") : nullptr;
156 : #ifdef HAVE_FOX
157 : std::vector<SUMOVehicle*>& vehs = myPendingRemovals.getContainer();
158 : #else
159 : std::vector<SUMOVehicle*>& vehs = myPendingRemovals;
160 : #endif
161 102306971 : std::sort(vehs.begin(), vehs.end(), ComparatorNumericalIdLess());
162 106329302 : for (SUMOVehicle* const veh : vehs) {
163 4022331 : myTotalTravelTime += STEPS2TIME(MSNet::getInstance()->getCurrentTimeStep() - veh->getDeparture());
164 4022331 : myRunningVehNo--;
165 4022331 : MSNet::getInstance()->informVehicleStateListener(veh, MSNet::VehicleState::ARRIVED);
166 : // vehicle is equipped with tripinfo device (not all vehicles are)
167 4022331 : const bool hasTripinfo = veh->getDevice(typeid(MSDevice_Tripinfo)) != nullptr;
168 7081343 : for (MSVehicleDevice* const dev : veh->getDevices()) {
169 3772879 : dev->generateOutput(hasTripinfo ? tripinfoOut : nullptr);
170 : }
171 4022331 : if (tripinfoOut != nullptr && hasTripinfo) {
172 : // close tag after tripinfo (possibly including emissions from another device) have been written
173 479354 : tripinfoOut->closeTag();
174 : }
175 4022331 : if (myKeepTime == 0) {
176 4022319 : deleteVehicle(veh);
177 : } else {
178 12 : deleteKeptVehicle(veh);
179 : }
180 : }
181 : vehs.clear();
182 102306971 : if (tripinfoOut != nullptr) {
183 : // there seem to be people who think reading an unfinished xml is a good idea ;-)
184 : tripinfoOut->flush();
185 : }
186 : #ifdef HAVE_FOX
187 : myPendingRemovals.unlock();
188 : #endif
189 102306971 : }
190 :
191 :
192 : void
193 15 : MSVehicleControl::deleteKeptVehicle(SUMOVehicle* veh) {
194 15 : myEndedVehNo++;
195 15 : MSNet::getInstance()->getEndOfTimestepEvents()->addEvent(new DeleteKeptVehicle(veh), SIMSTEP + myKeepTime);
196 15 : }
197 :
198 : void
199 4172824 : MSVehicleControl::vehicleDeparted(const SUMOVehicle& v) {
200 4172824 : ++myRunningVehNo;
201 4172824 : myTotalDepartureDelay += STEPS2TIME(v.getDeparture() - STEPFLOOR(v.getParameter().depart));
202 4172824 : MSNet::getInstance()->informVehicleStateListener(&v, MSNet::VehicleState::DEPARTED);
203 4172824 : myMaxSpeedFactor = MAX2(myMaxSpeedFactor, v.getChosenSpeedFactor());
204 4172824 : if ((v.getVClass() & (SVC_PEDESTRIAN | SVC_NON_ROAD)) == 0) {
205 : // only worry about deceleration of road users
206 8131460 : myMinDeceleration = MIN2(myMinDeceleration, v.getVehicleType().getCarFollowModel().getMaxDecel());
207 8083 : } else if ((v.getVClass() & SVC_RAIL_CLASSES) != 0) {
208 14305 : myMinDecelerationRail = MIN2(myMinDecelerationRail, v.getVehicleType().getCarFollowModel().getMaxDecel());
209 : }
210 4172824 : }
211 :
212 :
213 : void
214 441 : MSVehicleControl::setState(int runningVehNo, int loadedVehNo, int endedVehNo, double totalDepartureDelay, double totalTravelTime, double maxSpeedFactor, double minDecel) {
215 441 : myRunningVehNo = runningVehNo;
216 441 : myLoadedVehNo = loadedVehNo;
217 441 : myEndedVehNo = endedVehNo;
218 441 : myTotalDepartureDelay = totalDepartureDelay;
219 441 : myTotalTravelTime = totalTravelTime;
220 441 : myMaxSpeedFactor = maxSpeedFactor;
221 441 : myMinDeceleration = minDecel;
222 441 : }
223 :
224 :
225 : void
226 513 : MSVehicleControl::saveState(OutputDevice& out) {
227 513 : out.openTag(SUMO_TAG_DELAY);
228 513 : out.writeAttr(SUMO_ATTR_NUMBER, myRunningVehNo);
229 513 : out.writeAttr(SUMO_ATTR_BEGIN, myLoadedVehNo);
230 513 : out.writeAttr(SUMO_ATTR_END, myEndedVehNo);
231 513 : out.writeAttr(SUMO_ATTR_DEPART, myTotalDepartureDelay);
232 513 : out.writeAttr(SUMO_ATTR_TIME, myTotalTravelTime);
233 513 : out.writeAttr(SUMO_ATTR_SPEEDFACTOR, myMaxSpeedFactor);
234 513 : out.writeAttr(SUMO_ATTR_DECEL, myMinDeceleration);
235 513 : const SUMOTime loaderTime = MSNet::getInstance()->getLoaderTime();
236 513 : if (loaderTime > 0 && loaderTime != SUMOTime_MAX) {
237 32 : out.writeAttr(SUMO_ATTR_LOADERTIME, MSNet::getInstance()->getLoaderTime());
238 : }
239 1026 : out.closeTag();
240 : // save vehicle types
241 4383 : for (const auto& item : myVTypeDict) {
242 3870 : if (myReplaceableDefaultVTypes.count(item.first) == 0) {
243 1043 : item.second->getParameter().write(out);
244 : }
245 : }
246 693 : for (const auto& item : myVTypeDistDict) {
247 180 : out.openTag(SUMO_TAG_VTYPE_DISTRIBUTION).writeAttr(SUMO_ATTR_ID, item.first);
248 180 : out.writeAttr(SUMO_ATTR_VTYPES, item.second->getVals());
249 180 : out.writeAttr(SUMO_ATTR_PROBS, item.second->getProbs());
250 360 : out.closeTag();
251 : }
252 : std::vector<SUMOVehicle*> sortedVehs;
253 4859 : for (const auto& item : myVehicleDict) {
254 4346 : sortedVehs.push_back(item.second);
255 : }
256 513 : std::sort(sortedVehs.begin(), sortedVehs.end(), ComparatorNumericalIdLess());
257 4859 : for (SUMOVehicle* veh : sortedVehs) {
258 4346 : veh->saveState(out);
259 : }
260 513 : }
261 :
262 :
263 : void
264 41913 : MSVehicleControl::clearState(const bool reinit) {
265 356631 : for (const auto& item : myVehicleDict) {
266 314718 : delete item.second;
267 : }
268 : myVehicleDict.clear();
269 : // delete vehicle type distributions
270 42360 : for (const auto& item : myVTypeDistDict) {
271 894 : delete item.second;
272 : }
273 : myVTypeDistDict.clear();
274 : // delete vehicle types
275 344739 : for (const auto& item : myVTypeDict) {
276 302826 : delete item.second;
277 : }
278 : myVTypeDict.clear();
279 41913 : myPendingRemovals.clear(); // could be leftovers from MSVehicleTransfer::checkInsertions (teleport beyond arrival)
280 41913 : if (reinit) {
281 168 : initDefaultTypes();
282 : }
283 41913 : myLoadedVehNo = 0;
284 41913 : myRunningVehNo = 0;
285 41913 : myEndedVehNo = 0;
286 41913 : myDiscarded = 0;
287 41913 : myCollisions = 0;
288 41913 : myTeleportsCollision = 0;
289 41913 : myTeleportsJam = 0;
290 41913 : myTeleportsYield = 0;
291 41913 : myTeleportsWrongLane = 0;
292 41913 : myEmergencyStops = 0;
293 41913 : myEmergencyBrakingCount = 0;
294 41913 : myStoppedVehicles = 0;
295 41913 : myTotalDepartureDelay = 0;
296 41913 : myTotalTravelTime = 0;
297 41913 : }
298 :
299 :
300 : bool
301 5156462 : MSVehicleControl::addVehicle(const std::string& id, SUMOVehicle* v) {
302 : VehicleDictType::iterator it = myVehicleDict.find(id);
303 5156462 : if (it == myVehicleDict.end()) {
304 : // id not in myVehicleDict.
305 5156462 : myVehicleDict[id] = v;
306 5156462 : handleTriggeredDepart(v, true);
307 5156462 : const SUMOVehicleParameter& pars = v->getParameter();
308 5156462 : if (v->getVClass() != SVC_TAXI && pars.line != "" && pars.repetitionNumber < 0) {
309 1153 : myPTVehicles.push_back(v);
310 : }
311 5156462 : return true;
312 : }
313 : return false;
314 : }
315 :
316 :
317 : void
318 5160836 : MSVehicleControl::handleTriggeredDepart(SUMOVehicle* v, bool add) {
319 5160836 : const SUMOVehicleParameter& pars = v->getParameter();
320 5160836 : if (pars.departProcedure == DepartDefinition::TRIGGERED || pars.departProcedure == DepartDefinition::CONTAINER_TRIGGERED || pars.departProcedure == DepartDefinition::SPLIT) {
321 4256 : const MSEdge* const firstEdge = v->getRoute().getEdges()[pars.departEdge];
322 4256 : if (add) {
323 2193 : if (!MSGlobals::gUseMesoSim) {
324 : // position will be checked against person position later
325 1804 : static_cast<MSVehicle*>(v)->setTentativeLaneAndPosition(nullptr, v->getParameter().departPos);
326 : }
327 2193 : if (firstEdge->isTazConnector()) {
328 78 : for (MSEdge* out : firstEdge->getSuccessors()) {
329 51 : out->addWaiting(v);
330 : }
331 : } else {
332 2166 : firstEdge->addWaiting(v);
333 : }
334 : registerOneWaiting();
335 : } else {
336 2063 : if (firstEdge->isTazConnector()) {
337 14 : for (MSEdge* out : firstEdge->getSuccessors()) {
338 7 : out->removeWaiting(v);
339 : }
340 : } else {
341 2056 : firstEdge->removeWaiting(v);
342 : }
343 : unregisterOneWaiting();
344 : }
345 : }
346 5160836 : }
347 :
348 :
349 : SUMOVehicle*
350 22535436 : MSVehicleControl::getVehicle(const std::string& id) const {
351 : VehicleDictType::const_iterator it = myVehicleDict.find(id);
352 22535436 : if (it == myVehicleDict.end()) {
353 : return nullptr;
354 : }
355 17186467 : return it->second;
356 : }
357 :
358 :
359 : void
360 4946779 : MSVehicleControl::deleteVehicle(SUMOVehicle* veh, bool discard, bool wasKept) {
361 4946779 : if (!wasKept) {
362 4946767 : myEndedVehNo++;
363 4946767 : if (discard) {
364 924448 : myDiscarded++;
365 : }
366 : }
367 4946779 : if (veh != nullptr) {
368 : myVehicleDict.erase(veh->getID());
369 : }
370 4946779 : auto ptVehIt = std::find(myPTVehicles.begin(), myPTVehicles.end(), veh);
371 4946779 : if (ptVehIt != myPTVehicles.end()) {
372 946 : myPTVehicles.erase(ptVehIt);
373 : }
374 4946779 : delete veh;
375 4946779 : }
376 :
377 :
378 : bool
379 63606 : MSVehicleControl::checkVType(const std::string& id) {
380 63606 : if (myReplaceableDefaultVTypes.erase(id) > 0) {
381 10054 : delete myVTypeDict[id];
382 : myVTypeDict.erase(myVTypeDict.find(id));
383 : } else {
384 53552 : if (myVTypeDict.find(id) != myVTypeDict.end() || myVTypeDistDict.find(id) != myVTypeDistDict.end()) {
385 187 : return false;
386 : }
387 : }
388 : return true;
389 : }
390 :
391 :
392 : bool
393 63159 : MSVehicleControl::addVType(MSVehicleType* vehType) {
394 63159 : if (checkVType(vehType->getID())) {
395 62972 : myVTypeDict[vehType->getID()] = vehType;
396 62972 : return true;
397 : }
398 : return false;
399 : }
400 :
401 :
402 : void
403 1414 : MSVehicleControl::removeVType(const MSVehicleType* vehType) {
404 : assert(vehType != nullptr);
405 : assert(myVTypeDict.find(vehType->getID()) != myVTypeDict.end());
406 : myVTypeDict.erase(vehType->getID());
407 1414 : if (myVTypeToDist.find(vehType->getID()) != myVTypeToDist.end()) {
408 : myVTypeToDist.erase(vehType->getID());
409 : }
410 1414 : delete vehType;
411 1414 : }
412 :
413 :
414 : bool
415 447 : MSVehicleControl::addVTypeDistribution(const std::string& id, RandomDistributor<MSVehicleType*>* vehTypeDistribution) {
416 447 : if (checkVType(id)) {
417 447 : myVTypeDistDict[id] = vehTypeDistribution;
418 447 : std::vector<MSVehicleType*> vehTypes = vehTypeDistribution->getVals();
419 1673 : for (auto vehType : vehTypes) {
420 1226 : if (myVTypeToDist.find(vehType->getID()) != myVTypeToDist.end()) {
421 42 : myVTypeToDist[vehType->getID()].insert(id);
422 : } else {
423 3552 : myVTypeToDist[vehType->getID()] = { id };
424 : }
425 : }
426 : return true;
427 447 : }
428 : return false;
429 : }
430 :
431 :
432 : bool
433 46295 : MSVehicleControl::hasVType(const std::string& id) const {
434 46295 : return myVTypeDict.count(id) > 0 || myVTypeDistDict.count(id) > 0;
435 : }
436 :
437 :
438 : bool
439 19505 : MSVehicleControl::hasVTypeDistribution(const std::string& id) const {
440 19505 : return myVTypeDistDict.count(id) > 0;
441 : }
442 :
443 :
444 : MSVehicleType*
445 8508615 : MSVehicleControl::getVType(const std::string& id, SumoRNG* rng, bool readOnly) {
446 : VTypeDictType::iterator it = myVTypeDict.find(id);
447 8508615 : if (it == myVTypeDict.end()) {
448 : VTypeDistDictType::iterator it2 = myVTypeDistDict.find(id);
449 2616706 : if (it2 == myVTypeDistDict.end()) {
450 : return nullptr;
451 : }
452 82052 : return it2->second->get(rng);
453 : }
454 11759349 : if (!readOnly && myReplaceableDefaultVTypes.erase(id) > 0) {
455 20116 : it->second->check();
456 : }
457 5891909 : return it->second;
458 : }
459 :
460 :
461 : void
462 309 : MSVehicleControl::insertVTypeIDs(std::vector<std::string>& into) const {
463 309 : into.reserve(into.size() + myVTypeDict.size() + myVTypeDistDict.size());
464 2458 : for (VTypeDictType::const_iterator i = myVTypeDict.begin(); i != myVTypeDict.end(); ++i) {
465 2149 : into.push_back((*i).first);
466 : }
467 309 : for (VTypeDistDictType::const_iterator i = myVTypeDistDict.begin(); i != myVTypeDistDict.end(); ++i) {
468 0 : into.push_back((*i).first);
469 : }
470 309 : }
471 :
472 :
473 : const std::set<std::string>
474 139050 : MSVehicleControl::getVTypeDistributionMembership(const std::string& id) const {
475 : std::map<std::string, std::set<std::string>>::const_iterator it = myVTypeToDist.find(id);
476 139050 : if (it == myVTypeToDist.end()) {
477 60214 : return std::set<std::string>();
478 : }
479 : return it->second;
480 : }
481 :
482 :
483 : const RandomDistributor<MSVehicleType*>*
484 135515 : MSVehicleControl::getVTypeDistribution(const std::string& typeDistID) const {
485 : const auto it = myVTypeDistDict.find(typeDistID);
486 135515 : if (it != myVTypeDistDict.end()) {
487 2184 : return it->second;
488 : }
489 : return nullptr;
490 : }
491 :
492 :
493 : const std::vector<MSVehicleType*>
494 0 : MSVehicleControl::getPedestrianTypes(void) const {
495 : std::vector<MSVehicleType*> pedestrianTypes;
496 0 : for (auto const& e : myVTypeDict)
497 0 : if (e.second->getVehicleClass() == SUMOVehicleClass::SVC_PEDESTRIAN) {
498 0 : pedestrianTypes.push_back(e.second);
499 : }
500 0 : return pedestrianTypes;
501 0 : }
502 :
503 :
504 : void
505 28011 : MSVehicleControl::abortWaiting() {
506 29955 : for (VehicleDictType::iterator i = myVehicleDict.begin(); i != myVehicleDict.end(); ++i) {
507 1944 : SUMOVehicle* veh = i->second;
508 : std::string waitReason;
509 1944 : if (veh->isStoppedTriggered()) {
510 1870 : const MSStop& stop = veh->getNextStop();
511 1870 : if (stop.triggered) {
512 : waitReason = "for a person that will never come";
513 124 : } else if (stop.containerTriggered) {
514 : waitReason = "for a container that will never come";
515 36 : } else if (stop.joinTriggered) {
516 36 : if (stop.pars.join != "") {
517 48 : waitReason = "to be joined to vehicle '" + stop.pars.join + "'";
518 : } else {
519 : waitReason = "for a joining vehicle that will never come";
520 : }
521 : } else {
522 : waitReason = "for an unknown trigger";
523 : }
524 74 : } else if (!veh->hasDeparted()) {
525 74 : if (veh->getParameter().departProcedure == DepartDefinition::SPLIT) {
526 : waitReason = "for a train from which to split";
527 58 : } else if (veh->getParameter().departProcedure == DepartDefinition::TRIGGERED) {
528 : waitReason = "at insertion for a person that will never come";
529 22 : } else if (veh->getParameter().departProcedure == DepartDefinition::CONTAINER_TRIGGERED) {
530 : waitReason = "at insertion for a container that will never come";
531 : } else {
532 : waitReason = "for an unknown departure trigger";
533 : }
534 : } else {
535 : waitReason = "for an unknown reason";
536 : }
537 5832 : WRITE_WARNINGF(TL("Vehicle '%' aborted waiting %."), i->first, waitReason);
538 : }
539 28011 : }
540 :
541 :
542 : int
543 522721 : MSVehicleControl::getHaltingVehicleNo() const {
544 : int result = 0;
545 75575773 : for (MSVehicleControl::constVehIt it = loadedVehBegin(); it != loadedVehEnd(); ++it) {
546 75053052 : const SUMOVehicle* veh = it->second;
547 75053052 : if ((veh->isOnRoad() || veh->isRemoteControlled()) && veh->getSpeed() < SUMO_const_haltingSpeed) {
548 18905441 : result++;
549 : }
550 : }
551 522721 : return result;
552 : }
553 :
554 :
555 : std::pair<double, double>
556 522721 : MSVehicleControl::getVehicleMeanSpeeds() const {
557 : double speedSum = 0;
558 : double relSpeedSum = 0;
559 : int count = 0;
560 75575773 : for (MSVehicleControl::constVehIt it = loadedVehBegin(); it != loadedVehEnd(); ++it) {
561 75053052 : const SUMOVehicle* veh = it->second;
562 75053052 : if ((veh->isOnRoad() || veh->isRemoteControlled()) && !veh->isStopped()) {
563 42243186 : count++;
564 42243186 : speedSum += veh->getSpeed();
565 42243186 : relSpeedSum += veh->getEdge()->getSpeedLimit() > 0 ? veh->getSpeed() / veh->getEdge()->getSpeedLimit() : 0;
566 : }
567 : }
568 522721 : if (count > 0) {
569 427718 : return std::make_pair(speedSum / count, relSpeedSum / count);
570 : } else {
571 95003 : return std::make_pair(-1, -1);
572 : }
573 : }
574 :
575 :
576 : int
577 1331971 : MSVehicleControl::getQuota(double frac, int loaded) const {
578 1331971 : frac = frac < 0 ? myScale : frac;
579 : const int origLoaded = (loaded < 1
580 : // the vehicle in question has already been loaded, hence the '-1'
581 1331971 : ? frac > 1. ? (int)(myLoadedVehNo / frac) : myLoadedVehNo - 1
582 : // given transportable number reflects only previously loaded
583 459447 : : frac > 1. ? (int)(loaded / frac) : loaded);
584 1331971 : return getScalingQuota(frac, origLoaded);
585 : }
586 :
587 :
588 : int
589 552214 : MSVehicleControl::getTeleportCount() const {
590 552214 : return myTeleportsCollision + myTeleportsJam + myTeleportsYield + myTeleportsWrongLane;
591 : }
592 :
593 :
594 : void
595 4934 : MSVehicleControl::adaptIntermodalRouter(MSTransportableRouter& router) const {
596 5214 : for (const SUMOVehicle* const veh : myPTVehicles) {
597 : // add single vehicles with line attribute which are not part of a flow
598 280 : ConstMSRoutePtr const route = MSRoute::dictionary(veh->getParameter().routeid);
599 280 : router.getNetwork()->addSchedule(veh->getParameter(), route == nullptr ? nullptr : &route->getStops());
600 : }
601 4934 : }
602 :
603 : // ===========================================================================
604 : // MSVehicleControl::DeleteKeptVehicle method definitions
605 : // ===========================================================================
606 :
607 : SUMOTime
608 12 : MSVehicleControl::DeleteKeptVehicle::execute(SUMOTime /*currentTime*/) {
609 12 : MSNet::getInstance()->getVehicleControl().deleteVehicle(myVehicle, false, true);
610 12 : return 0;
611 : }
612 :
613 : /****************************************************************************/
|