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 41790 : MSVehicleControl::MSVehicleControl() :
47 41790 : myLoadedVehNo(0),
48 41790 : myRunningVehNo(0),
49 41790 : myEndedVehNo(0),
50 41790 : myDiscarded(0),
51 41790 : myCollisions(0),
52 41790 : myTeleportsCollision(0),
53 41790 : myTeleportsJam(0),
54 41790 : myTeleportsYield(0),
55 41790 : myTeleportsWrongLane(0),
56 41790 : myEmergencyStops(0),
57 41790 : myEmergencyBrakingCount(0),
58 41790 : myStoppedVehicles(0),
59 41790 : myTotalDepartureDelay(0),
60 41790 : myTotalTravelTime(0),
61 41790 : myWaitingForTransportable(0),
62 41790 : myMaxSpeedFactor(1),
63 41790 : myMinDeceleration(SUMOVTypeParameter::getDefaultDecel(SVC_IGNORING)),
64 41790 : myMinDecelerationRail(SUMOVTypeParameter::getDefaultDecel(SVC_RAIL)),
65 83580 : myPendingRemovals(MSGlobals::gNumSimThreads > 1) {
66 :
67 41790 : initDefaultTypes();
68 41790 : myScale = OptionsCont::getOptions().getFloat("scale");
69 41790 : myKeepTime = string2time(OptionsCont::getOptions().getString("keep-after-arrival"));
70 41790 : }
71 :
72 :
73 70245 : MSVehicleControl::~MSVehicleControl() {
74 41176 : clearState(false);
75 70245 : }
76 :
77 :
78 : void
79 41958 : MSVehicleControl::initDefaultTypes() {
80 41958 : SUMOVTypeParameter defType(DEFAULT_VTYPE_ID, SVC_PASSENGER);
81 41958 : myVTypeDict[DEFAULT_VTYPE_ID] = MSVehicleType::build(defType);
82 :
83 41958 : SUMOVTypeParameter defPedType(DEFAULT_PEDTYPE_ID, SVC_PEDESTRIAN);
84 41958 : defPedType.parametersSet |= VTYPEPARS_VEHICLECLASS_SET;
85 41958 : myVTypeDict[DEFAULT_PEDTYPE_ID] = MSVehicleType::build(defPedType);
86 :
87 41958 : SUMOVTypeParameter defBikeType(DEFAULT_BIKETYPE_ID, SVC_BICYCLE);
88 41958 : defBikeType.parametersSet |= VTYPEPARS_VEHICLECLASS_SET;
89 41958 : myVTypeDict[DEFAULT_BIKETYPE_ID] = MSVehicleType::build(defBikeType);
90 :
91 41958 : SUMOVTypeParameter defTaxiType(DEFAULT_TAXITYPE_ID, SVC_TAXI);
92 41958 : defTaxiType.parametersSet |= VTYPEPARS_VEHICLECLASS_SET;
93 41958 : myVTypeDict[DEFAULT_TAXITYPE_ID] = MSVehicleType::build(defTaxiType);
94 :
95 41958 : SUMOVTypeParameter defRailType(DEFAULT_RAILTYPE_ID, SVC_RAIL);
96 41958 : defRailType.parametersSet |= VTYPEPARS_VEHICLECLASS_SET;
97 41958 : myVTypeDict[DEFAULT_RAILTYPE_ID] = MSVehicleType::build(defRailType);
98 :
99 41958 : SUMOVTypeParameter defContainerType(DEFAULT_CONTAINERTYPE_ID, SVC_CONTAINER);
100 41958 : defContainerType.parametersSet |= VTYPEPARS_VEHICLECLASS_SET;
101 41958 : myVTypeDict[DEFAULT_CONTAINERTYPE_ID] = MSVehicleType::build(defContainerType);
102 :
103 : myReplaceableDefaultVTypes = DEFAULT_VTYPES;
104 41958 : }
105 :
106 :
107 : SUMOVehicle*
108 3848288 : MSVehicleControl::buildVehicle(SUMOVehicleParameter* defs,
109 : ConstMSRoutePtr route, MSVehicleType* type,
110 : const bool ignoreStopErrors, const VehicleDefinitionSource source, bool addRouteStops) {
111 3848288 : const double speedFactor = (source == VehicleDefinitionSource::STATE ? 1 :
112 3947246 : type->computeChosenSpeedDeviation(source == VehicleDefinitionSource::ROUTEFILE ? MSRouteHandler::getParsingRNG() : nullptr));
113 7696576 : MSVehicle* built = new MSVehicle(defs, route, type, speedFactor);
114 3848288 : initVehicle(built, ignoreStopErrors, addRouteStops, source);
115 3848232 : return built;
116 : }
117 :
118 :
119 : void
120 5255349 : MSVehicleControl::initVehicle(MSBaseVehicle* built, const bool ignoreStopErrors, bool addRouteStops, const VehicleDefinitionSource source) {
121 5255349 : myLoadedVehNo++;
122 : try {
123 5255349 : built->initDevices();
124 5255310 : if (source != VehicleDefinitionSource::STATE) {
125 5250661 : built->addStops(ignoreStopErrors, nullptr, addRouteStops);
126 : }
127 116 : } catch (ProcessError&) {
128 116 : delete built;
129 116 : throw;
130 116 : }
131 5255232 : MSNet::getInstance()->informVehicleStateListener(built, MSNet::VehicleState::BUILT);
132 5255232 : }
133 :
134 :
135 : void
136 4019499 : MSVehicleControl::scheduleVehicleRemoval(SUMOVehicle* veh, bool checkDuplicate) {
137 : assert(myRunningVehNo > 0);
138 4019499 : if (!checkDuplicate || !isPendingRemoval(veh)) {
139 4019499 : myPendingRemovals.push_back(veh);
140 : }
141 4019499 : }
142 :
143 :
144 : bool
145 17549 : MSVehicleControl::isPendingRemoval(SUMOVehicle* veh) {
146 : #ifdef HAVE_FOX
147 17549 : return myPendingRemovals.contains(veh);
148 : #else
149 : return std::find(myPendingRemovals.begin(), myPendingRemovals.end(), veh) == myPendingRemovals.end();
150 : #endif
151 : }
152 :
153 :
154 : void
155 96925457 : MSVehicleControl::removePending() {
156 113737782 : OutputDevice* const tripinfoOut = OptionsCont::getOptions().isSet("tripinfo-output") ? &OutputDevice::getDeviceByOption("tripinfo-output") : nullptr;
157 : #ifdef HAVE_FOX
158 : std::vector<SUMOVehicle*>& vehs = myPendingRemovals.getContainer();
159 : #else
160 : std::vector<SUMOVehicle*>& vehs = myPendingRemovals;
161 : #endif
162 96925457 : std::sort(vehs.begin(), vehs.end(), ComparatorNumericalIdLess());
163 100944952 : for (SUMOVehicle* const veh : vehs) {
164 4019495 : myTotalTravelTime += STEPS2TIME(MSNet::getInstance()->getCurrentTimeStep() - veh->getDeparture());
165 4019495 : myRunningVehNo--;
166 4019495 : MSNet::getInstance()->informVehicleStateListener(veh, MSNet::VehicleState::ARRIVED);
167 : // vehicle is equipped with tripinfo device (not all vehicles are)
168 4019495 : const bool hasTripinfo = veh->getDevice(typeid(MSDevice_Tripinfo)) != nullptr;
169 7088391 : for (MSVehicleDevice* const dev : veh->getDevices()) {
170 3785327 : dev->generateOutput(hasTripinfo ? tripinfoOut : nullptr);
171 : }
172 4019495 : if (tripinfoOut != nullptr && hasTripinfo) {
173 : // close tag after tripinfo (possibly including emissions from another device) have been written
174 473696 : tripinfoOut->closeTag();
175 : }
176 4019495 : if (myKeepTime == 0) {
177 4019483 : deleteVehicle(veh);
178 : } else {
179 12 : deleteKeptVehicle(veh);
180 : }
181 : }
182 : vehs.clear();
183 96925457 : if (tripinfoOut != nullptr) {
184 : // there seem to be people who think reading an unfinished xml is a good idea ;-)
185 : tripinfoOut->flush();
186 : }
187 : #ifdef HAVE_FOX
188 : myPendingRemovals.unlock();
189 : #endif
190 96925457 : }
191 :
192 :
193 : void
194 15 : MSVehicleControl::deleteKeptVehicle(SUMOVehicle* veh) {
195 15 : myEndedVehNo++;
196 15 : MSNet::getInstance()->getEndOfTimestepEvents()->addEvent(new DeleteKeptVehicle(veh), SIMSTEP + myKeepTime);
197 15 : }
198 :
199 : void
200 4167564 : MSVehicleControl::vehicleDeparted(const SUMOVehicle& v) {
201 4167564 : ++myRunningVehNo;
202 4167564 : myTotalDepartureDelay += STEPS2TIME(v.getDeparture() - STEPFLOOR(v.getParameter().depart));
203 4167564 : MSNet::getInstance()->informVehicleStateListener(&v, MSNet::VehicleState::DEPARTED);
204 4167564 : myMaxSpeedFactor = MAX2(myMaxSpeedFactor, v.getChosenSpeedFactor());
205 4167564 : if ((v.getVClass() & (SVC_PEDESTRIAN | SVC_NON_ROAD)) == 0) {
206 : // only worry about deceleration of road users
207 8120116 : myMinDeceleration = MIN2(myMinDeceleration, v.getVehicleType().getCarFollowModel().getMaxDecel());
208 7845 : } else if ((v.getVClass() & SVC_RAIL_CLASSES) != 0) {
209 14017 : myMinDecelerationRail = MIN2(myMinDecelerationRail, v.getVehicleType().getCarFollowModel().getMaxDecel());
210 : }
211 4167564 : }
212 :
213 :
214 : void
215 422 : MSVehicleControl::setState(int runningVehNo, int loadedVehNo, int endedVehNo, double totalDepartureDelay, double totalTravelTime, double maxSpeedFactor, double minDecel) {
216 422 : myRunningVehNo = runningVehNo;
217 422 : myLoadedVehNo = loadedVehNo;
218 422 : myEndedVehNo = endedVehNo;
219 422 : myTotalDepartureDelay = totalDepartureDelay;
220 422 : myTotalTravelTime = totalTravelTime;
221 422 : myMaxSpeedFactor = maxSpeedFactor;
222 422 : myMinDeceleration = minDecel;
223 422 : }
224 :
225 :
226 : void
227 496 : MSVehicleControl::saveState(OutputDevice& out) {
228 496 : out.openTag(SUMO_TAG_DELAY);
229 496 : out.writeAttr(SUMO_ATTR_NUMBER, myRunningVehNo);
230 496 : out.writeAttr(SUMO_ATTR_BEGIN, myLoadedVehNo);
231 496 : out.writeAttr(SUMO_ATTR_END, myEndedVehNo);
232 496 : out.writeAttr(SUMO_ATTR_DEPART, myTotalDepartureDelay);
233 496 : out.writeAttr(SUMO_ATTR_TIME, myTotalTravelTime);
234 496 : out.writeAttr(SUMO_ATTR_SPEEDFACTOR, myMaxSpeedFactor);
235 496 : out.writeAttr(SUMO_ATTR_DECEL, myMinDeceleration);
236 992 : out.closeTag();
237 : // save vehicle types
238 4253 : for (const auto& item : myVTypeDict) {
239 3757 : if (myReplaceableDefaultVTypes.count(item.first) == 0) {
240 1014 : item.second->getParameter().write(out);
241 : }
242 : }
243 676 : for (const auto& item : myVTypeDistDict) {
244 180 : out.openTag(SUMO_TAG_VTYPE_DISTRIBUTION).writeAttr(SUMO_ATTR_ID, item.first);
245 180 : out.writeAttr(SUMO_ATTR_VTYPES, item.second->getVals());
246 180 : out.writeAttr(SUMO_ATTR_PROBS, item.second->getProbs());
247 360 : out.closeTag();
248 : }
249 : std::vector<SUMOVehicle*> sortedVehs;
250 4823 : for (const auto& item : myVehicleDict) {
251 4327 : sortedVehs.push_back(item.second);
252 : }
253 496 : std::sort(sortedVehs.begin(), sortedVehs.end(), ComparatorNumericalIdLess());
254 4823 : for (SUMOVehicle* veh : sortedVehs) {
255 4327 : veh->saveState(out);
256 : }
257 496 : }
258 :
259 :
260 : void
261 41344 : MSVehicleControl::clearState(const bool reinit) {
262 352831 : for (const auto& item : myVehicleDict) {
263 311487 : delete item.second;
264 : }
265 : myVehicleDict.clear();
266 : // delete vehicle type distributions
267 41796 : for (const auto& item : myVTypeDistDict) {
268 904 : delete item.second;
269 : }
270 : myVTypeDistDict.clear();
271 : // delete vehicle types
272 340516 : for (const auto& item : myVTypeDict) {
273 299172 : delete item.second;
274 : }
275 : myVTypeDict.clear();
276 41344 : myPendingRemovals.clear(); // could be leftovers from MSVehicleTransfer::checkInsertions (teleport beyond arrival)
277 41344 : if (reinit) {
278 168 : initDefaultTypes();
279 : }
280 41344 : myLoadedVehNo = 0;
281 41344 : myRunningVehNo = 0;
282 41344 : myEndedVehNo = 0;
283 41344 : myDiscarded = 0;
284 41344 : myCollisions = 0;
285 41344 : myTeleportsCollision = 0;
286 41344 : myTeleportsJam = 0;
287 41344 : myTeleportsYield = 0;
288 41344 : myTeleportsWrongLane = 0;
289 41344 : myEmergencyStops = 0;
290 41344 : myEmergencyBrakingCount = 0;
291 41344 : myStoppedVehicles = 0;
292 41344 : myTotalDepartureDelay = 0;
293 41344 : myTotalTravelTime = 0;
294 41344 : }
295 :
296 :
297 : bool
298 5150133 : MSVehicleControl::addVehicle(const std::string& id, SUMOVehicle* v) {
299 : VehicleDictType::iterator it = myVehicleDict.find(id);
300 5150133 : if (it == myVehicleDict.end()) {
301 : // id not in myVehicleDict.
302 5150133 : myVehicleDict[id] = v;
303 5150133 : handleTriggeredDepart(v, true);
304 5150133 : const SUMOVehicleParameter& pars = v->getParameter();
305 5150133 : if (v->getVClass() != SVC_TAXI && pars.line != "" && pars.repetitionNumber < 0) {
306 1117 : myPTVehicles.push_back(v);
307 : }
308 5150133 : return true;
309 : }
310 : return false;
311 : }
312 :
313 :
314 : void
315 5154461 : MSVehicleControl::handleTriggeredDepart(SUMOVehicle* v, bool add) {
316 5154461 : const SUMOVehicleParameter& pars = v->getParameter();
317 5154461 : if (pars.departProcedure == DepartDefinition::TRIGGERED || pars.departProcedure == DepartDefinition::CONTAINER_TRIGGERED || pars.departProcedure == DepartDefinition::SPLIT) {
318 4212 : const MSEdge* const firstEdge = v->getRoute().getEdges()[pars.departEdge];
319 4212 : if (add) {
320 2171 : if (!MSGlobals::gUseMesoSim) {
321 : // position will be checked against person position later
322 1793 : static_cast<MSVehicle*>(v)->setTentativeLaneAndPosition(nullptr, v->getParameter().departPos);
323 : }
324 2171 : if (firstEdge->isTazConnector()) {
325 78 : for (MSEdge* out : firstEdge->getSuccessors()) {
326 51 : out->addWaiting(v);
327 : }
328 : } else {
329 2144 : firstEdge->addWaiting(v);
330 : }
331 : registerOneWaiting();
332 : } else {
333 2041 : if (firstEdge->isTazConnector()) {
334 14 : for (MSEdge* out : firstEdge->getSuccessors()) {
335 7 : out->removeWaiting(v);
336 : }
337 : } else {
338 2034 : firstEdge->removeWaiting(v);
339 : }
340 : unregisterOneWaiting();
341 : }
342 : }
343 5154461 : }
344 :
345 :
346 : SUMOVehicle*
347 22720425 : MSVehicleControl::getVehicle(const std::string& id) const {
348 : VehicleDictType::const_iterator it = myVehicleDict.find(id);
349 22720425 : if (it == myVehicleDict.end()) {
350 : return nullptr;
351 : }
352 17379461 : return it->second;
353 : }
354 :
355 :
356 : void
357 4943659 : MSVehicleControl::deleteVehicle(SUMOVehicle* veh, bool discard, bool wasKept) {
358 4943659 : if (!wasKept) {
359 4943647 : myEndedVehNo++;
360 4943647 : if (discard) {
361 924164 : myDiscarded++;
362 : }
363 : }
364 4943659 : if (veh != nullptr) {
365 : myVehicleDict.erase(veh->getID());
366 : }
367 4943659 : auto ptVehIt = std::find(myPTVehicles.begin(), myPTVehicles.end(), veh);
368 4943659 : if (ptVehIt != myPTVehicles.end()) {
369 941 : myPTVehicles.erase(ptVehIt);
370 : }
371 4943659 : delete veh;
372 4943659 : }
373 :
374 :
375 : bool
376 63208 : MSVehicleControl::checkVType(const std::string& id) {
377 63208 : if (myReplaceableDefaultVTypes.erase(id) > 0) {
378 9867 : delete myVTypeDict[id];
379 : myVTypeDict.erase(myVTypeDict.find(id));
380 : } else {
381 53341 : if (myVTypeDict.find(id) != myVTypeDict.end() || myVTypeDistDict.find(id) != myVTypeDistDict.end()) {
382 181 : return false;
383 : }
384 : }
385 : return true;
386 : }
387 :
388 :
389 : bool
390 62756 : MSVehicleControl::addVType(MSVehicleType* vehType) {
391 62756 : if (checkVType(vehType->getID())) {
392 62575 : myVTypeDict[vehType->getID()] = vehType;
393 62575 : return true;
394 : }
395 : return false;
396 : }
397 :
398 :
399 : void
400 1432 : MSVehicleControl::removeVType(const MSVehicleType* vehType) {
401 : assert(vehType != nullptr);
402 : assert(myVTypeDict.find(vehType->getID()) != myVTypeDict.end());
403 : myVTypeDict.erase(vehType->getID());
404 1432 : if (myVTypeToDist.find(vehType->getID()) != myVTypeToDist.end()) {
405 : myVTypeToDist.erase(vehType->getID());
406 : }
407 1432 : delete vehType;
408 1432 : }
409 :
410 :
411 : bool
412 452 : MSVehicleControl::addVTypeDistribution(const std::string& id, RandomDistributor<MSVehicleType*>* vehTypeDistribution) {
413 452 : if (checkVType(id)) {
414 452 : myVTypeDistDict[id] = vehTypeDistribution;
415 452 : std::vector<MSVehicleType*> vehTypes = vehTypeDistribution->getVals();
416 1688 : for (auto vehType : vehTypes) {
417 1236 : if (myVTypeToDist.find(vehType->getID()) != myVTypeToDist.end()) {
418 42 : myVTypeToDist[vehType->getID()].insert(id);
419 : } else {
420 3582 : myVTypeToDist[vehType->getID()] = { id };
421 : }
422 : }
423 : return true;
424 452 : }
425 : return false;
426 : }
427 :
428 :
429 : bool
430 46174 : MSVehicleControl::hasVType(const std::string& id) const {
431 46174 : return myVTypeDict.count(id) > 0 || myVTypeDistDict.count(id) > 0;
432 : }
433 :
434 :
435 : bool
436 19148 : MSVehicleControl::hasVTypeDistribution(const std::string& id) const {
437 19148 : return myVTypeDistDict.count(id) > 0;
438 : }
439 :
440 :
441 : MSVehicleType*
442 8107412 : MSVehicleControl::getVType(const std::string& id, SumoRNG* rng, bool readOnly) {
443 : VTypeDictType::iterator it = myVTypeDict.find(id);
444 8107412 : if (it == myVTypeDict.end()) {
445 : VTypeDistDictType::iterator it2 = myVTypeDistDict.find(id);
446 2227394 : if (it2 == myVTypeDistDict.end()) {
447 : return nullptr;
448 : }
449 86239 : return it2->second->get(rng);
450 : }
451 11735970 : if (!readOnly && myReplaceableDefaultVTypes.erase(id) > 0) {
452 19856 : it->second->check();
453 : }
454 5880018 : return it->second;
455 : }
456 :
457 :
458 : void
459 311 : MSVehicleControl::insertVTypeIDs(std::vector<std::string>& into) const {
460 311 : into.reserve(into.size() + myVTypeDict.size() + myVTypeDistDict.size());
461 2477 : for (VTypeDictType::const_iterator i = myVTypeDict.begin(); i != myVTypeDict.end(); ++i) {
462 2166 : into.push_back((*i).first);
463 : }
464 311 : for (VTypeDistDictType::const_iterator i = myVTypeDistDict.begin(); i != myVTypeDistDict.end(); ++i) {
465 0 : into.push_back((*i).first);
466 : }
467 311 : }
468 :
469 :
470 : const std::set<std::string>
471 149575 : MSVehicleControl::getVTypeDistributionMembership(const std::string& id) const {
472 : std::map<std::string, std::set<std::string>>::const_iterator it = myVTypeToDist.find(id);
473 149575 : if (it == myVTypeToDist.end()) {
474 60114 : return std::set<std::string>();
475 : }
476 : return it->second;
477 : }
478 :
479 :
480 : const RandomDistributor<MSVehicleType*>*
481 135263 : MSVehicleControl::getVTypeDistribution(const std::string& typeDistID) const {
482 : const auto it = myVTypeDistDict.find(typeDistID);
483 135263 : if (it != myVTypeDistDict.end()) {
484 2202 : return it->second;
485 : }
486 : return nullptr;
487 : }
488 :
489 :
490 : const std::vector<MSVehicleType*>
491 0 : MSVehicleControl::getPedestrianTypes(void) const {
492 : std::vector<MSVehicleType*> pedestrianTypes;
493 0 : for (auto const& e : myVTypeDict)
494 0 : if (e.second->getVehicleClass() == SUMOVehicleClass::SVC_PEDESTRIAN) {
495 0 : pedestrianTypes.push_back(e.second);
496 : }
497 0 : return pedestrianTypes;
498 0 : }
499 :
500 :
501 : void
502 27757 : MSVehicleControl::abortWaiting() {
503 29676 : for (VehicleDictType::iterator i = myVehicleDict.begin(); i != myVehicleDict.end(); ++i) {
504 1919 : SUMOVehicle* veh = i->second;
505 : std::string waitReason;
506 1919 : if (veh->isStoppedTriggered()) {
507 1845 : const MSStop& stop = veh->getNextStop();
508 1845 : if (stop.triggered) {
509 : waitReason = "for a person that will never come";
510 124 : } else if (stop.containerTriggered) {
511 : waitReason = "for a container that will never come";
512 36 : } else if (stop.joinTriggered) {
513 36 : if (stop.pars.join != "") {
514 48 : waitReason = "to be joined to vehicle '" + stop.pars.join + "'";
515 : } else {
516 : waitReason = "for a joining vehicle that will never come";
517 : }
518 : } else {
519 : waitReason = "for an unknown trigger";
520 : }
521 74 : } else if (!veh->hasDeparted()) {
522 74 : if (veh->getParameter().departProcedure == DepartDefinition::SPLIT) {
523 : waitReason = "for a train from which to split";
524 58 : } else if (veh->getParameter().departProcedure == DepartDefinition::TRIGGERED) {
525 : waitReason = "at insertion for a person that will never come";
526 22 : } else if (veh->getParameter().departProcedure == DepartDefinition::CONTAINER_TRIGGERED) {
527 : waitReason = "at insertion for a container that will never come";
528 : } else {
529 : waitReason = "for an unknown departure trigger";
530 : }
531 : } else {
532 : waitReason = "for an unknown reason";
533 : }
534 5757 : WRITE_WARNINGF(TL("Vehicle '%' aborted waiting %."), i->first, waitReason);
535 : }
536 27757 : }
537 :
538 :
539 : int
540 522721 : MSVehicleControl::getHaltingVehicleNo() const {
541 : int result = 0;
542 75575773 : for (MSVehicleControl::constVehIt it = loadedVehBegin(); it != loadedVehEnd(); ++it) {
543 75053052 : const SUMOVehicle* veh = it->second;
544 75053052 : if ((veh->isOnRoad() || veh->isRemoteControlled()) && veh->getSpeed() < SUMO_const_haltingSpeed) {
545 18905441 : result++;
546 : }
547 : }
548 522721 : return result;
549 : }
550 :
551 :
552 : std::pair<double, double>
553 522721 : MSVehicleControl::getVehicleMeanSpeeds() const {
554 : double speedSum = 0;
555 : double relSpeedSum = 0;
556 : int count = 0;
557 75575773 : for (MSVehicleControl::constVehIt it = loadedVehBegin(); it != loadedVehEnd(); ++it) {
558 75053052 : const SUMOVehicle* veh = it->second;
559 75053052 : if ((veh->isOnRoad() || veh->isRemoteControlled()) && !veh->isStopped()) {
560 42243186 : count++;
561 42243186 : speedSum += veh->getSpeed();
562 42243186 : relSpeedSum += veh->getEdge()->getSpeedLimit() > 0 ? veh->getSpeed() / veh->getEdge()->getSpeedLimit() : 0;
563 : }
564 : }
565 522721 : if (count > 0) {
566 427718 : return std::make_pair(speedSum / count, relSpeedSum / count);
567 : } else {
568 95003 : return std::make_pair(-1, -1);
569 : }
570 : }
571 :
572 :
573 : int
574 1325135 : MSVehicleControl::getQuota(double frac, int loaded) const {
575 1325135 : frac = frac < 0 ? myScale : frac;
576 : const int origLoaded = (loaded < 1
577 : // the vehicle in question has already been loaded, hence the '-1'
578 1325135 : ? frac > 1. ? (int)(myLoadedVehNo / frac) : myLoadedVehNo - 1
579 : // given transportable number reflects only previously loaded
580 459116 : : frac > 1. ? (int)(loaded / frac) : loaded);
581 1325135 : return getScalingQuota(frac, origLoaded);
582 : }
583 :
584 :
585 : int
586 552000 : MSVehicleControl::getTeleportCount() const {
587 552000 : return myTeleportsCollision + myTeleportsJam + myTeleportsYield + myTeleportsWrongLane;
588 : }
589 :
590 :
591 : void
592 4898 : MSVehicleControl::adaptIntermodalRouter(MSTransportableRouter& router) const {
593 5171 : for (const SUMOVehicle* const veh : myPTVehicles) {
594 : // add single vehicles with line attribute which are not part of a flow
595 273 : ConstMSRoutePtr const route = MSRoute::dictionary(veh->getParameter().routeid);
596 273 : router.getNetwork()->addSchedule(veh->getParameter(), route == nullptr ? nullptr : &route->getStops());
597 : }
598 4898 : }
599 :
600 : // ===========================================================================
601 : // MSVehicleControl::DeleteKeptVehicle method definitions
602 : // ===========================================================================
603 :
604 : SUMOTime
605 12 : MSVehicleControl::DeleteKeptVehicle::execute(SUMOTime /*currentTime*/) {
606 12 : MSNet::getInstance()->getVehicleControl().deleteVehicle(myVehicle, false, true);
607 12 : return 0;
608 : }
609 :
610 : /****************************************************************************/
|