Line data Source code
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 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 40412 : MSVehicleControl::MSVehicleControl() :
47 40412 : myLoadedVehNo(0),
48 40412 : myRunningVehNo(0),
49 40412 : myEndedVehNo(0),
50 40412 : myDiscarded(0),
51 40412 : myCollisions(0),
52 40412 : myTeleportsCollision(0),
53 40412 : myTeleportsJam(0),
54 40412 : myTeleportsYield(0),
55 40412 : myTeleportsWrongLane(0),
56 40412 : myEmergencyStops(0),
57 40412 : myEmergencyBrakingCount(0),
58 40412 : myStoppedVehicles(0),
59 40412 : myTotalDepartureDelay(0),
60 40412 : myTotalTravelTime(0),
61 40412 : myWaitingForTransportable(0),
62 40412 : myMaxSpeedFactor(1),
63 40412 : myMinDeceleration(SUMOVTypeParameter::getDefaultDecel(SVC_IGNORING)),
64 40412 : myMinDecelerationRail(SUMOVTypeParameter::getDefaultDecel(SVC_RAIL)),
65 80824 : myPendingRemovals(MSGlobals::gNumSimThreads > 1) {
66 :
67 40412 : initDefaultTypes();
68 40412 : myScale = OptionsCont::getOptions().getFloat("scale");
69 40412 : myKeepTime = string2time(OptionsCont::getOptions().getString("keep-after-arrival"));
70 40412 : }
71 :
72 :
73 68458 : MSVehicleControl::~MSVehicleControl() {
74 39792 : clearState(false);
75 68458 : }
76 :
77 :
78 : void
79 40599 : MSVehicleControl::initDefaultTypes() {
80 40599 : SUMOVTypeParameter defType(DEFAULT_VTYPE_ID, SVC_PASSENGER);
81 40599 : myVTypeDict[DEFAULT_VTYPE_ID] = MSVehicleType::build(defType);
82 :
83 40599 : SUMOVTypeParameter defPedType(DEFAULT_PEDTYPE_ID, SVC_PEDESTRIAN);
84 40599 : defPedType.parametersSet |= VTYPEPARS_VEHICLECLASS_SET;
85 40599 : myVTypeDict[DEFAULT_PEDTYPE_ID] = MSVehicleType::build(defPedType);
86 :
87 40599 : SUMOVTypeParameter defBikeType(DEFAULT_BIKETYPE_ID, SVC_BICYCLE);
88 40599 : defBikeType.parametersSet |= VTYPEPARS_VEHICLECLASS_SET;
89 40599 : myVTypeDict[DEFAULT_BIKETYPE_ID] = MSVehicleType::build(defBikeType);
90 :
91 40599 : SUMOVTypeParameter defTaxiType(DEFAULT_TAXITYPE_ID, SVC_TAXI);
92 40599 : defTaxiType.parametersSet |= VTYPEPARS_VEHICLECLASS_SET;
93 40599 : myVTypeDict[DEFAULT_TAXITYPE_ID] = MSVehicleType::build(defTaxiType);
94 :
95 40599 : SUMOVTypeParameter defRailType(DEFAULT_RAILTYPE_ID, SVC_RAIL);
96 40599 : defRailType.parametersSet |= VTYPEPARS_VEHICLECLASS_SET;
97 40599 : myVTypeDict[DEFAULT_RAILTYPE_ID] = MSVehicleType::build(defRailType);
98 :
99 40599 : SUMOVTypeParameter defContainerType(DEFAULT_CONTAINERTYPE_ID, SVC_CONTAINER);
100 40599 : defContainerType.parametersSet |= VTYPEPARS_VEHICLECLASS_SET;
101 40599 : myVTypeDict[DEFAULT_CONTAINERTYPE_ID] = MSVehicleType::build(defContainerType);
102 :
103 : myReplaceableDefaultVTypes = DEFAULT_VTYPES;
104 40599 : }
105 :
106 :
107 : SUMOVehicle*
108 4087395 : MSVehicleControl::buildVehicle(SUMOVehicleParameter* defs,
109 : ConstMSRoutePtr route, MSVehicleType* type,
110 : const bool ignoreStopErrors, const VehicleDefinitionSource source, bool addRouteStops) {
111 4087395 : const double speedFactor = (source == VehicleDefinitionSource::STATE ? 1 :
112 4185938 : type->computeChosenSpeedDeviation(source == VehicleDefinitionSource::ROUTEFILE ? MSRouteHandler::getParsingRNG() : nullptr));
113 8174790 : MSVehicle* built = new MSVehicle(defs, route, type, speedFactor);
114 4087395 : initVehicle(built, ignoreStopErrors, addRouteStops, source);
115 4087339 : return built;
116 : }
117 :
118 :
119 : void
120 5336321 : MSVehicleControl::initVehicle(MSBaseVehicle* built, const bool ignoreStopErrors, bool addRouteStops, const VehicleDefinitionSource source) {
121 5336321 : myLoadedVehNo++;
122 : try {
123 5336321 : built->initDevices();
124 5336282 : if (source != VehicleDefinitionSource::STATE) {
125 5330747 : built->addStops(ignoreStopErrors, nullptr, addRouteStops);
126 : }
127 72 : } catch (ProcessError&) {
128 72 : delete built;
129 72 : throw;
130 72 : }
131 5336248 : MSNet::getInstance()->informVehicleStateListener(built, MSNet::VehicleState::BUILT);
132 5336248 : }
133 :
134 :
135 : void
136 4111780 : MSVehicleControl::scheduleVehicleRemoval(SUMOVehicle* veh, bool checkDuplicate) {
137 : assert(myRunningVehNo > 0);
138 4111780 : if (!checkDuplicate || !isPendingRemoval(veh)) {
139 4111780 : myPendingRemovals.push_back(veh);
140 : }
141 4111780 : }
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 91928231 : MSVehicleControl::removePending() {
156 107205979 : 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 91928231 : std::sort(vehs.begin(), vehs.end(), ComparatorNumericalIdLess());
163 96040007 : for (SUMOVehicle* const veh : vehs) {
164 4111776 : myTotalTravelTime += STEPS2TIME(MSNet::getInstance()->getCurrentTimeStep() - veh->getDeparture());
165 4111776 : myRunningVehNo--;
166 4111776 : MSNet::getInstance()->informVehicleStateListener(veh, MSNet::VehicleState::ARRIVED);
167 : // vehicle is equipped with tripinfo device (not all vehicles are)
168 4111776 : const bool hasTripinfo = veh->getDevice(typeid(MSDevice_Tripinfo)) != nullptr;
169 7174628 : for (MSVehicleDevice* const dev : veh->getDevices()) {
170 3924105 : dev->generateOutput(hasTripinfo ? tripinfoOut : nullptr);
171 : }
172 4111776 : if (tripinfoOut != nullptr && hasTripinfo) {
173 : // close tag after tripinfo (possibly including emissions from another device) have been written
174 465324 : tripinfoOut->closeTag();
175 : }
176 4111776 : if (myKeepTime == 0) {
177 4111762 : deleteVehicle(veh);
178 : } else {
179 14 : deleteKeptVehicle(veh);
180 : }
181 : }
182 : vehs.clear();
183 91928231 : 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 91928231 : }
191 :
192 :
193 : void
194 18 : MSVehicleControl::deleteKeptVehicle(SUMOVehicle* veh) {
195 18 : myEndedVehNo++;
196 18 : MSNet::getInstance()->getEndOfTimestepEvents()->addEvent(new DeleteKeptVehicle(veh), SIMSTEP + myKeepTime);
197 18 : }
198 :
199 : void
200 4248606 : MSVehicleControl::vehicleDeparted(const SUMOVehicle& v) {
201 4248606 : ++myRunningVehNo;
202 4248606 : myTotalDepartureDelay += STEPS2TIME(v.getDeparture() - STEPFLOOR(v.getParameter().depart));
203 4248606 : MSNet::getInstance()->informVehicleStateListener(&v, MSNet::VehicleState::DEPARTED);
204 4248606 : myMaxSpeedFactor = MAX2(myMaxSpeedFactor, v.getChosenSpeedFactor());
205 4248606 : if ((v.getVClass() & (SVC_PEDESTRIAN | SVC_NON_ROAD)) == 0) {
206 : // only worry about deceleration of road users
207 8284271 : myMinDeceleration = MIN2(myMinDeceleration, v.getVehicleType().getCarFollowModel().getMaxDecel());
208 7350 : } else if ((v.getVClass() & SVC_RAIL_CLASSES) != 0) {
209 13146 : myMinDecelerationRail = MIN2(myMinDecelerationRail, v.getVehicleType().getCarFollowModel().getMaxDecel());
210 : }
211 4248606 : }
212 :
213 :
214 : void
215 428 : MSVehicleControl::setState(int runningVehNo, int loadedVehNo, int endedVehNo, double totalDepartureDelay, double totalTravelTime) {
216 428 : myRunningVehNo = runningVehNo;
217 428 : myLoadedVehNo = loadedVehNo;
218 428 : myEndedVehNo = endedVehNo;
219 428 : myTotalDepartureDelay = totalDepartureDelay;
220 428 : myTotalTravelTime = totalTravelTime;
221 428 : }
222 :
223 :
224 : void
225 476 : MSVehicleControl::saveState(OutputDevice& out) {
226 476 : out.openTag(SUMO_TAG_DELAY);
227 476 : out.writeAttr(SUMO_ATTR_NUMBER, myRunningVehNo);
228 476 : out.writeAttr(SUMO_ATTR_BEGIN, myLoadedVehNo);
229 476 : out.writeAttr(SUMO_ATTR_END, myEndedVehNo);
230 476 : out.writeAttr(SUMO_ATTR_DEPART, myTotalDepartureDelay);
231 952 : out.writeAttr(SUMO_ATTR_TIME, myTotalTravelTime).closeTag();
232 : // save vehicle types
233 4097 : for (const auto& item : myVTypeDict) {
234 3621 : if (myReplaceableDefaultVTypes.count(item.first) == 0) {
235 982 : item.second->getParameter().write(out);
236 : }
237 : }
238 654 : for (const auto& item : myVTypeDistDict) {
239 178 : out.openTag(SUMO_TAG_VTYPE_DISTRIBUTION).writeAttr(SUMO_ATTR_ID, item.first);
240 178 : out.writeAttr(SUMO_ATTR_VTYPES, item.second->getVals());
241 178 : out.writeAttr(SUMO_ATTR_PROBS, item.second->getProbs());
242 356 : out.closeTag();
243 : }
244 : std::vector<SUMOVehicle*> sortedVehs;
245 4735 : for (const auto& item : myVehicleDict) {
246 4259 : sortedVehs.push_back(item.second);
247 : }
248 476 : std::sort(sortedVehs.begin(), sortedVehs.end(), ComparatorNumericalIdLess());
249 4735 : for (SUMOVehicle* veh : sortedVehs) {
250 4259 : veh->saveState(out);
251 : }
252 476 : }
253 :
254 :
255 : void
256 39979 : MSVehicleControl::clearState(const bool reinit) {
257 367626 : for (const auto& item : myVehicleDict) {
258 327647 : delete item.second;
259 : }
260 : myVehicleDict.clear();
261 : // delete vehicle type distributions
262 40425 : for (const auto& item : myVTypeDistDict) {
263 892 : delete item.second;
264 : }
265 : myVTypeDistDict.clear();
266 : // delete vehicle types
267 330432 : for (const auto& item : myVTypeDict) {
268 290453 : delete item.second;
269 : }
270 : myVTypeDict.clear();
271 39979 : myPendingRemovals.clear(); // could be leftovers from MSVehicleTransfer::checkInsertions (teleport beyond arrival)
272 39979 : if (reinit) {
273 187 : initDefaultTypes();
274 : }
275 39979 : myLoadedVehNo = 0;
276 39979 : myRunningVehNo = 0;
277 39979 : myEndedVehNo = 0;
278 39979 : myDiscarded = 0;
279 39979 : myCollisions = 0;
280 39979 : myTeleportsCollision = 0;
281 39979 : myTeleportsJam = 0;
282 39979 : myTeleportsYield = 0;
283 39979 : myTeleportsWrongLane = 0;
284 39979 : myEmergencyStops = 0;
285 39979 : myEmergencyBrakingCount = 0;
286 39979 : myStoppedVehicles = 0;
287 39979 : myTotalDepartureDelay = 0;
288 39979 : myTotalTravelTime = 0;
289 39979 : }
290 :
291 :
292 : bool
293 5231234 : MSVehicleControl::addVehicle(const std::string& id, SUMOVehicle* v) {
294 : VehicleDictType::iterator it = myVehicleDict.find(id);
295 5231234 : if (it == myVehicleDict.end()) {
296 : // id not in myVehicleDict.
297 5231234 : myVehicleDict[id] = v;
298 5231234 : handleTriggeredDepart(v, true);
299 5231234 : const SUMOVehicleParameter& pars = v->getParameter();
300 5231234 : if (v->getVClass() != SVC_TAXI && pars.line != "" && pars.repetitionNumber < 0) {
301 1073 : myPTVehicles.push_back(v);
302 : }
303 5231234 : return true;
304 : }
305 : return false;
306 : }
307 :
308 :
309 : void
310 5235774 : MSVehicleControl::handleTriggeredDepart(SUMOVehicle* v, bool add) {
311 5235774 : const SUMOVehicleParameter& pars = v->getParameter();
312 5235774 : if (pars.departProcedure == DepartDefinition::TRIGGERED || pars.departProcedure == DepartDefinition::CONTAINER_TRIGGERED || pars.departProcedure == DepartDefinition::SPLIT) {
313 4244 : const MSEdge* const firstEdge = v->getRoute().getEdges()[pars.departEdge];
314 4244 : if (add) {
315 2187 : if (!MSGlobals::gUseMesoSim) {
316 : // position will be checked against person position later
317 1802 : static_cast<MSVehicle*>(v)->setTentativeLaneAndPosition(nullptr, v->getParameter().departPos);
318 : }
319 2187 : if (firstEdge->isTazConnector()) {
320 78 : for (MSEdge* out : firstEdge->getSuccessors()) {
321 51 : out->addWaiting(v);
322 : }
323 : } else {
324 2160 : firstEdge->addWaiting(v);
325 : }
326 : registerOneWaiting();
327 : } else {
328 2057 : if (firstEdge->isTazConnector()) {
329 14 : for (MSEdge* out : firstEdge->getSuccessors()) {
330 7 : out->removeWaiting(v);
331 : }
332 : } else {
333 2050 : firstEdge->removeWaiting(v);
334 : }
335 : unregisterOneWaiting();
336 : }
337 : }
338 5235774 : }
339 :
340 :
341 : SUMOVehicle*
342 22174518 : MSVehicleControl::getVehicle(const std::string& id) const {
343 : VehicleDictType::const_iterator it = myVehicleDict.find(id);
344 22174518 : if (it == myVehicleDict.end()) {
345 : return nullptr;
346 : }
347 16769132 : return it->second;
348 : }
349 :
350 :
351 : void
352 5008508 : MSVehicleControl::deleteVehicle(SUMOVehicle* veh, bool discard, bool wasKept) {
353 5008508 : if (!wasKept) {
354 5008494 : myEndedVehNo++;
355 5008494 : if (discard) {
356 896732 : myDiscarded++;
357 : }
358 : }
359 5008508 : if (veh != nullptr) {
360 : myVehicleDict.erase(veh->getID());
361 : }
362 5008508 : auto ptVehIt = std::find(myPTVehicles.begin(), myPTVehicles.end(), veh);
363 5008508 : if (ptVehIt != myPTVehicles.end()) {
364 936 : myPTVehicles.erase(ptVehIt);
365 : }
366 5008508 : delete veh;
367 5008508 : }
368 :
369 :
370 : bool
371 62409 : MSVehicleControl::checkVType(const std::string& id) {
372 62409 : if (myReplaceableDefaultVTypes.erase(id) > 0) {
373 9633 : delete myVTypeDict[id];
374 : myVTypeDict.erase(myVTypeDict.find(id));
375 : } else {
376 52776 : if (myVTypeDict.find(id) != myVTypeDict.end() || myVTypeDistDict.find(id) != myVTypeDistDict.end()) {
377 184 : return false;
378 : }
379 : }
380 : return true;
381 : }
382 :
383 :
384 : bool
385 61963 : MSVehicleControl::addVType(MSVehicleType* vehType) {
386 61963 : if (checkVType(vehType->getID())) {
387 61779 : myVTypeDict[vehType->getID()] = vehType;
388 61779 : return true;
389 : }
390 : return false;
391 : }
392 :
393 :
394 : void
395 1407 : MSVehicleControl::removeVType(const MSVehicleType* vehType) {
396 : assert(vehType != nullptr);
397 : assert(myVTypeDict.find(vehType->getID()) != myVTypeDict.end());
398 : myVTypeDict.erase(vehType->getID());
399 1407 : if (myVTypeToDist.find(vehType->getID()) != myVTypeToDist.end()) {
400 : myVTypeToDist.erase(vehType->getID());
401 : }
402 1407 : delete vehType;
403 1407 : }
404 :
405 :
406 : bool
407 446 : MSVehicleControl::addVTypeDistribution(const std::string& id, RandomDistributor<MSVehicleType*>* vehTypeDistribution) {
408 446 : if (checkVType(id)) {
409 446 : myVTypeDistDict[id] = vehTypeDistribution;
410 446 : std::vector<MSVehicleType*> vehTypes = vehTypeDistribution->getVals();
411 1670 : for (auto vehType : vehTypes) {
412 1224 : if (myVTypeToDist.find(vehType->getID()) != myVTypeToDist.end()) {
413 42 : myVTypeToDist[vehType->getID()].insert(id);
414 : } else {
415 3546 : myVTypeToDist[vehType->getID()] = { id };
416 : }
417 : }
418 : return true;
419 446 : }
420 : return false;
421 : }
422 :
423 :
424 : bool
425 45320 : MSVehicleControl::hasVType(const std::string& id) const {
426 45320 : return myVTypeDict.count(id) > 0 || myVTypeDistDict.count(id) > 0;
427 : }
428 :
429 :
430 : bool
431 18046 : MSVehicleControl::hasVTypeDistribution(const std::string& id) const {
432 18046 : return myVTypeDistDict.count(id) > 0;
433 : }
434 :
435 :
436 : MSVehicleType*
437 10080025 : MSVehicleControl::getVType(const std::string& id, SumoRNG* rng, bool readOnly) {
438 : VTypeDictType::iterator it = myVTypeDict.find(id);
439 10080025 : if (it == myVTypeDict.end()) {
440 : VTypeDistDictType::iterator it2 = myVTypeDistDict.find(id);
441 4110727 : if (it2 == myVTypeDistDict.end()) {
442 : return nullptr;
443 : }
444 85935 : return it2->second->get(rng);
445 : }
446 11915669 : if (!readOnly && myReplaceableDefaultVTypes.erase(id) > 0) {
447 19124 : it->second->check();
448 : }
449 5969298 : return it->second;
450 : }
451 :
452 :
453 : void
454 335 : MSVehicleControl::insertVTypeIDs(std::vector<std::string>& into) const {
455 335 : into.reserve(into.size() + myVTypeDict.size() + myVTypeDistDict.size());
456 2650 : for (VTypeDictType::const_iterator i = myVTypeDict.begin(); i != myVTypeDict.end(); ++i) {
457 2315 : into.push_back((*i).first);
458 : }
459 335 : for (VTypeDistDictType::const_iterator i = myVTypeDistDict.begin(); i != myVTypeDistDict.end(); ++i) {
460 0 : into.push_back((*i).first);
461 : }
462 335 : }
463 :
464 :
465 : const std::set<std::string>
466 144596 : MSVehicleControl::getVTypeDistributionMembership(const std::string& id) const {
467 : std::map<std::string, std::set<std::string>>::const_iterator it = myVTypeToDist.find(id);
468 144596 : if (it == myVTypeToDist.end()) {
469 60089 : return std::set<std::string>();
470 : }
471 : return it->second;
472 : }
473 :
474 :
475 : const RandomDistributor<MSVehicleType*>*
476 133465 : MSVehicleControl::getVTypeDistribution(const std::string& typeDistID) const {
477 : const auto it = myVTypeDistDict.find(typeDistID);
478 133465 : if (it != myVTypeDistDict.end()) {
479 2184 : return it->second;
480 : }
481 : return nullptr;
482 : }
483 :
484 :
485 : const std::vector<MSVehicleType*>
486 0 : MSVehicleControl::getPedestrianTypes(void) const {
487 : std::vector<MSVehicleType*> pedestrianTypes;
488 0 : for (auto const& e : myVTypeDict)
489 0 : if (e.second->getVehicleClass() == SUMOVehicleClass::SVC_PEDESTRIAN) {
490 0 : pedestrianTypes.push_back(e.second);
491 : }
492 0 : return pedestrianTypes;
493 0 : }
494 :
495 :
496 : void
497 26936 : MSVehicleControl::abortWaiting() {
498 28750 : for (VehicleDictType::iterator i = myVehicleDict.begin(); i != myVehicleDict.end(); ++i) {
499 1814 : SUMOVehicle* veh = i->second;
500 : std::string waitReason;
501 1814 : if (veh->isStoppedTriggered()) {
502 1740 : const MSStop& stop = veh->getNextStop();
503 1740 : if (stop.triggered) {
504 : waitReason = "for a person that will never come";
505 124 : } else if (stop.containerTriggered) {
506 : waitReason = "for a container that will never come";
507 36 : } else if (stop.joinTriggered) {
508 36 : if (stop.pars.join != "") {
509 48 : waitReason = "to be joined to vehicle '" + stop.pars.join + "'";
510 : } else {
511 : waitReason = "for a joining vehicle that will never come";
512 : }
513 : } else {
514 : waitReason = "for an unknown trigger";
515 : }
516 74 : } else if (!veh->hasDeparted()) {
517 74 : if (veh->getParameter().departProcedure == DepartDefinition::SPLIT) {
518 : waitReason = "for a train from which to split";
519 58 : } else if (veh->getParameter().departProcedure == DepartDefinition::TRIGGERED) {
520 : waitReason = "at insertion for a person that will never come";
521 22 : } else if (veh->getParameter().departProcedure == DepartDefinition::CONTAINER_TRIGGERED) {
522 : waitReason = "at insertion for a container that will never come";
523 : } else {
524 : waitReason = "for an unknown departure trigger";
525 : }
526 : } else {
527 : waitReason = "for an unknown reason";
528 : }
529 5442 : WRITE_WARNINGF(TL("Vehicle '%' aborted waiting %."), i->first, waitReason);
530 : }
531 26936 : }
532 :
533 :
534 : int
535 520101 : MSVehicleControl::getHaltingVehicleNo() const {
536 : int result = 0;
537 75235659 : for (MSVehicleControl::constVehIt it = loadedVehBegin(); it != loadedVehEnd(); ++it) {
538 74715558 : const SUMOVehicle* veh = it->second;
539 74715558 : if ((veh->isOnRoad() || veh->isRemoteControlled()) && veh->getSpeed() < SUMO_const_haltingSpeed) {
540 18838282 : result++;
541 : }
542 : }
543 520101 : return result;
544 : }
545 :
546 :
547 : std::pair<double, double>
548 520101 : MSVehicleControl::getVehicleMeanSpeeds() const {
549 : double speedSum = 0;
550 : double relSpeedSum = 0;
551 : int count = 0;
552 75235659 : for (MSVehicleControl::constVehIt it = loadedVehBegin(); it != loadedVehEnd(); ++it) {
553 74715558 : const SUMOVehicle* veh = it->second;
554 74715558 : if ((veh->isOnRoad() || veh->isRemoteControlled()) && !veh->isStopped()) {
555 41921982 : count++;
556 41921982 : speedSum += veh->getSpeed();
557 41921982 : relSpeedSum += veh->getEdge()->getSpeedLimit() > 0 ? veh->getSpeed() / veh->getEdge()->getSpeedLimit() : 0;
558 : }
559 : }
560 520101 : if (count > 0) {
561 425592 : return std::make_pair(speedSum / count, relSpeedSum / count);
562 : } else {
563 94509 : return std::make_pair(-1, -1);
564 : }
565 : }
566 :
567 :
568 : int
569 1309729 : MSVehicleControl::getQuota(double frac, int loaded) const {
570 1309729 : frac = frac < 0 ? myScale : frac;
571 : const int origLoaded = (loaded < 1
572 : // the vehicle in question has already been loaded, hence the '-1'
573 1309729 : ? frac > 1. ? (int)(myLoadedVehNo / frac) : myLoadedVehNo - 1
574 : // given transportable number reflects only previously loaded
575 471579 : : frac > 1. ? (int)(loaded / frac) : loaded);
576 1309729 : return getScalingQuota(frac, origLoaded);
577 : }
578 :
579 :
580 : int
581 549076 : MSVehicleControl::getTeleportCount() const {
582 549076 : return myTeleportsCollision + myTeleportsJam + myTeleportsYield + myTeleportsWrongLane;
583 : }
584 :
585 :
586 : void
587 4806 : MSVehicleControl::adaptIntermodalRouter(MSTransportableRouter& router) const {
588 5039 : for (const SUMOVehicle* const veh : myPTVehicles) {
589 : // add single vehicles with line attribute which are not part of a flow
590 233 : ConstMSRoutePtr const route = MSRoute::dictionary(veh->getParameter().routeid);
591 233 : router.getNetwork()->addSchedule(veh->getParameter(), route == nullptr ? nullptr : &route->getStops());
592 : }
593 4806 : }
594 :
595 : // ===========================================================================
596 : // MSVehicleControl::DeleteKeptVehicle method definitions
597 : // ===========================================================================
598 :
599 : SUMOTime
600 14 : MSVehicleControl::DeleteKeptVehicle::execute(SUMOTime /*currentTime*/) {
601 14 : MSNet::getInstance()->getVehicleControl().deleteVehicle(myVehicle, false, true);
602 14 : return 0;
603 : }
604 :
605 : /****************************************************************************/
|