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 MSTransportableControl.cpp
15 : /// @author Daniel Krajzewicz
16 : /// @author Jakob Erdmann
17 : /// @author Sascha Krieg
18 : /// @author Michael Behrisch
19 : /// @date Mon, 9 Jul 2001
20 : ///
21 : // Stores all persons in the net and handles their waiting for cars.
22 : /****************************************************************************/
23 : #include <config.h>
24 :
25 : #include <vector>
26 : #include <algorithm>
27 : #include <utils/iodevices/OutputDevice.h>
28 : #include <utils/iodevices/OutputDevice_String.h>
29 : #include <utils/options/OptionsCont.h>
30 : #include <microsim/transportables/MSPerson.h>
31 : #include <microsim/transportables/MSStageDriving.h>
32 : #include <microsim/transportables/MSPModel_NonInteracting.h>
33 : #ifdef JPS_VERSION
34 : #include <microsim/transportables/MSPModel_JuPedSim.h>
35 : #endif
36 : #include <microsim/transportables/MSPModel_Striping.h>
37 : #include <microsim/transportables/MSTransportableControl.h>
38 : #include <microsim/devices/MSDevice_Vehroutes.h>
39 : #include <microsim/devices/MSDevice_Taxi.h>
40 : #include <microsim/MSNet.h>
41 : #include <microsim/MSEdge.h>
42 : #include <microsim/MSVehicle.h>
43 : #include <microsim/MSStoppingPlace.h>
44 :
45 :
46 : // ===========================================================================
47 : // method definitions
48 : // ===========================================================================
49 10064 : MSTransportableControl::MSTransportableControl(const bool isPerson):
50 10064 : myLoadedNumber(0),
51 10064 : myDiscardedNumber(0),
52 10064 : myRunningNumber(0),
53 10064 : myJammedNumber(0),
54 10064 : myWaitingForDepartureNumber(0),
55 10064 : myWaitingForVehicleNumber(0),
56 10064 : myWaitingUntilNumber(0),
57 10064 : myAccessNumber(0),
58 10064 : myEndedNumber(0),
59 10064 : myArrivedNumber(0),
60 10064 : myTeleportsAbortWait(0),
61 10064 : myTeleportsWrongDest(0),
62 10064 : myHaveNewWaiting(false) {
63 10064 : const OptionsCont& oc = OptionsCont::getOptions();
64 10064 : MSNet* const net = MSNet::getInstance();
65 10064 : myMovementModel = myNonInteractingModel = new MSPModel_NonInteracting(oc, net);
66 10064 : if (isPerson) {
67 8109 : const std::string& model = oc.getString("pedestrian.model");
68 8109 : if (model == "striping") {
69 6083 : myMovementModel = new MSPModel_Striping(oc, net);
70 : #ifdef JPS_VERSION
71 : } else if (model == "jupedsim") {
72 : myMovementModel = new MSPModel_JuPedSim(oc, net);
73 : #endif
74 2026 : } else if (model != "nonInteracting") {
75 24 : delete myNonInteractingModel;
76 72 : throw ProcessError(TLF("Unknown pedestrian model '%'", model));
77 : }
78 : }
79 20080 : if (oc.isSet("vehroute-output")) {
80 1588 : myRouteInfos.routeOut = &OutputDevice::getDeviceByOption("vehroute-output");
81 : }
82 20080 : if (oc.isSet("personroute-output")) {
83 24 : OutputDevice::createDeviceByOption("personroute-output", "routes", "routes_file.xsd");
84 12 : myRouteInfos.routeOut = &OutputDevice::getDeviceByOption("personroute-output");
85 : }
86 20080 : if (oc.isSet("personinfo-output")) {
87 36 : OutputDevice::createDeviceByOption("personinfo-output", "tripinfos", "tripinfo_file.xsd");
88 : }
89 10040 : myAbortWaitingTimeout = string2time(oc.getString("time-to-teleport.ride"));
90 10040 : myMaxTransportableNumber = isPerson ? oc.getInt("max-num-persons") : -1;
91 10064 : }
92 :
93 :
94 18311 : MSTransportableControl::~MSTransportableControl() {
95 10019 : clearState();
96 10019 : if (myMovementModel != myNonInteractingModel) {
97 6073 : delete myMovementModel;
98 : }
99 10019 : delete myNonInteractingModel;
100 18311 : }
101 :
102 :
103 : bool
104 509044 : MSTransportableControl::add(MSTransportable* transportable) {
105 509044 : const SUMOVehicleParameter& param = transportable->getParameter();
106 509044 : if (myTransportables.find(param.id) == myTransportables.end()) {
107 509028 : myTransportables[param.id] = transportable;
108 509028 : const SUMOTime step = param.depart % DELTA_T == 0 ? param.depart : (param.depart / DELTA_T + 1) * DELTA_T;
109 509028 : myWaiting4Departure[step].push_back(transportable);
110 509028 : myLoadedNumber++;
111 509028 : myWaitingForDepartureNumber++;
112 : return true;
113 : }
114 : return false;
115 : }
116 :
117 :
118 : void
119 48 : MSTransportableControl::fixLoadCount(const MSTransportable* transportable) {
120 48 : myLoadedNumber--;
121 48 : if (transportable->hasDeparted()) {
122 42 : const SUMOVehicleParameter& param = transportable->getParameter();
123 42 : const SUMOTime step = param.depart % DELTA_T == 0 ? param.depart : (param.depart / DELTA_T + 1) * DELTA_T;
124 42 : TransportableVector& waiting = myWaiting4Departure[step];
125 42 : auto it = std::find(waiting.begin(), waiting.end(), transportable);
126 42 : if (it != waiting.end()) {
127 : waiting.erase(it);
128 42 : if (waiting.size() == 0) {
129 : myWaiting4Departure.erase(step);
130 : }
131 : }
132 : }
133 48 : }
134 :
135 :
136 : MSTransportable*
137 516744 : MSTransportableControl::get(const std::string& id) const {
138 : std::map<std::string, MSTransportable*>::const_iterator i = myTransportables.find(id);
139 516744 : if (i == myTransportables.end()) {
140 : return nullptr;
141 : }
142 509516 : return (*i).second;
143 : }
144 :
145 :
146 : void
147 475379 : MSTransportableControl::erase(MSTransportable* transportable) {
148 475379 : const OptionsCont& oc = OptionsCont::getOptions();
149 950758 : if (oc.isSet("personinfo-output")) {
150 360 : transportable->tripInfoOutput(OutputDevice::getDeviceByOption("personinfo-output"));
151 950398 : } else if (oc.isSet("tripinfo-output")) {
152 70494 : transportable->tripInfoOutput(OutputDevice::getDeviceByOption("tripinfo-output"));
153 879904 : } else if (oc.getBool("duration-log.statistics")) {
154 : // collecting statistics is a sideffect
155 21731 : OutputDevice_String dev;
156 21731 : transportable->tripInfoOutput(dev);
157 21731 : }
158 947320 : if (oc.isSet("vehroute-output") || oc.isSet("personroute-output")) {
159 3648 : if (transportable->hasArrived() || oc.getBool("vehroute-output.write-unfinished")) {
160 : // @todo: adapt this if we ever introduce person-device.vehroute
161 6772 : if (transportable->getBoolParam("has.vehroute.person-device", false, true)) {
162 6532 : if (oc.getBool("vehroute-output.sorted")) {
163 122 : const SUMOTime departure = oc.getBool("vehroute-output.intended-depart") ? transportable->getParameter().depart : transportable->getDeparture();
164 122 : OutputDevice_String od(1);
165 122 : transportable->routeOutput(od, oc.getBool("vehroute-output.route-length"));
166 122 : MSDevice_Vehroutes::writeSortedOutput(&myRouteInfos,
167 122 : departure, transportable->getID(), od.getString());
168 122 : } else {
169 6288 : transportable->routeOutput(*myRouteInfos.routeOut, oc.getBool("vehroute-output.route-length"));
170 : }
171 : }
172 : }
173 : }
174 : const std::map<std::string, MSTransportable*>::iterator i = myTransportables.find(transportable->getID());
175 475379 : if (i != myTransportables.end()) {
176 475379 : if (i->second->hasDeparted()) {
177 475093 : myRunningNumber--;
178 : }
179 475379 : myEndedNumber++;
180 1148109 : MSNet::getInstance()->informTransportableStateListener(transportable,
181 475379 : transportable->isPerson() ? MSNet::TransportableState::PERSON_ARRIVED : MSNet::TransportableState::CONTAINER_ARRIVED);
182 475379 : delete i->second;
183 : myTransportables.erase(i);
184 : }
185 475379 : }
186 :
187 :
188 : void
189 591 : MSTransportableControl::eraseAll() {
190 : // avoid taxi device having dangling references to erased customers
191 591 : MSDevice_Taxi::allCustomersErased();
192 807 : while (loadedBegin() != loadedEnd()) {
193 216 : erase(loadedBegin()->second);
194 : }
195 591 : }
196 :
197 :
198 : void
199 65935 : MSTransportableControl::setWaitEnd(const SUMOTime time, MSTransportable* transportable) {
200 65935 : const SUMOTime step = time % DELTA_T == 0 ? time : (time / DELTA_T + 1) * DELTA_T;
201 : // avoid double registration
202 65935 : const TransportableVector& transportables = myWaitingUntil[step];
203 65935 : if (std::find(transportables.begin(), transportables.end(), transportable) == transportables.end()) {
204 65935 : myWaitingUntil[step].push_back(transportable);
205 65935 : myWaitingUntilNumber++;
206 : }
207 65935 : }
208 :
209 :
210 : void
211 8506334 : MSTransportableControl::checkWaiting(MSNet* net, const SUMOTime time) {
212 8506334 : myHaveNewWaiting = false;
213 17318519 : while (myWaiting4Departure.find(time) != myWaiting4Departure.end()) {
214 305894 : TransportableVector& transportables = myWaiting4Departure[time];
215 : // we cannot use an iterator here because there might be additions to the vector while proceeding
216 793753 : for (auto it = transportables.begin(); it != transportables.end();) {
217 488006 : MSTransportable* t = *it;
218 488006 : if (myMaxTransportableNumber > 0 && myRunningNumber >= myMaxTransportableNumber) {
219 104 : TransportableVector& nextStep = myWaiting4Departure[time + DELTA_T];
220 104 : nextStep.insert(nextStep.begin(), transportables.begin(), transportables.end());
221 : transportables.clear();
222 : break;
223 487902 : } else if (myMaxTransportableNumber == 0) {
224 160 : erase(t);
225 : it = transportables.erase(it);
226 160 : continue;
227 : }
228 : it = transportables.erase(it);
229 487742 : myWaitingForDepartureNumber--;
230 487742 : const bool isPerson = t->isPerson();
231 487742 : t->setDeparted(time);
232 487742 : if (t->proceed(net, time)) {
233 487699 : myRunningNumber++;
234 685082 : MSNet::getInstance()->informTransportableStateListener(t,
235 : isPerson ? MSNet::TransportableState::PERSON_DEPARTED : MSNet::TransportableState::CONTAINER_DEPARTED);
236 487699 : const OptionsCont& oc = OptionsCont::getOptions();
237 975398 : if (oc.getBool("vehroute-output.sorted")) {
238 132 : const SUMOTime departure = oc.getBool("vehroute-output.intended-depart") ? t->getParameter().depart : time;
239 264 : if (oc.isSet("personroute-output")) {
240 24 : myRouteInfos.departureCounts[departure]++;
241 : } else {
242 108 : MSDevice_Vehroutes::registerTransportableDepart(departure);
243 : }
244 : }
245 : } else {
246 0 : erase(t);
247 : }
248 : }
249 : myWaiting4Departure.erase(time);
250 : }
251 8570876 : while (myWaitingUntil.find(time) != myWaitingUntil.end()) {
252 : // make a copy because 0-duration stops might modify the vector
253 64592 : const TransportableVector transportables = myWaitingUntil[time];
254 : myWaitingUntil.erase(time);
255 130298 : for (MSTransportable* t : transportables) {
256 65713 : myWaitingUntilNumber--;
257 65713 : if (!t->proceed(net, time)) {
258 18629 : erase(t);
259 : }
260 : }
261 64592 : }
262 8506284 : }
263 :
264 :
265 : void
266 47 : MSTransportableControl::forceDeparture() {
267 47 : myRunningNumber++;
268 47 : }
269 :
270 :
271 : void
272 75121 : MSTransportableControl::addWaiting(const MSEdge* const edge, MSTransportable* transportable) {
273 75121 : myWaiting4Vehicle[edge].push_back(transportable);
274 75121 : myWaitingForVehicleNumber++;
275 75121 : myHaveNewWaiting = true;
276 75121 : if (myAbortWaitingTimeout >= 0) {
277 16 : transportable->setAbortWaiting(myAbortWaitingTimeout);
278 : }
279 75121 : }
280 :
281 :
282 : bool
283 83 : MSTransportableControl::hasAnyWaiting(const MSEdge* edge, SUMOVehicle* vehicle) const {
284 : const auto wait = myWaiting4Vehicle.find(edge);
285 83 : if (wait != myWaiting4Vehicle.end()) {
286 44 : for (const MSTransportable* t : wait->second) {
287 : if (t->isWaitingFor(vehicle)
288 39 : && vehicle->allowsBoarding(t)
289 78 : && vehicle->isStoppedInRange(t->getEdgePos(), MSGlobals::gStopTolerance, true)) {
290 : return true;
291 : }
292 : }
293 : }
294 : return false;
295 : }
296 :
297 :
298 : bool
299 6069353 : MSTransportableControl::loadAnyWaiting(const MSEdge* edge, SUMOVehicle* vehicle, SUMOTime& timeToLoadNext, SUMOTime& stopDuration, MSTransportable* const force) {
300 : bool ret = false;
301 : const auto wait = myWaiting4Vehicle.find(edge);
302 6069353 : if (wait != myWaiting4Vehicle.end()) {
303 4367769 : const SUMOTime currentTime = SIMSTEP;
304 4367769 : TransportableVector& transportables = wait->second;
305 4739787 : for (TransportableVector::iterator i = transportables.begin(); i != transportables.end();) {
306 4684725 : MSTransportable* const t = *i;
307 9315696 : if (t->isWaitingFor(vehicle) && (t == force ||
308 4630971 : (vehicle->allowsBoarding(t)
309 4438321 : && timeToLoadNext - DELTA_T <= currentTime
310 4325892 : && vehicle->isStoppedInRange(t->getEdgePos(), MSGlobals::gStopTolerance)))) {
311 4322809 : edge->removeTransportable(t);
312 4322809 : vehicle->addTransportable(t);
313 10102 : if (myAbortWaitingTimeout >= 0) {
314 0 : t->setAbortWaiting(-1);
315 : }
316 10102 : if (timeToLoadNext >= 0) { // meso does not have loading times
317 16024 : const SUMOTime loadingDuration = (SUMOTime)((double)vehicle->getVehicleType().getLoadingDuration(t->isPerson()) * t->getVehicleType().getBoardingFactor());
318 : //update the time point at which the next transportable can be loaded on the vehicle
319 8012 : if (timeToLoadNext > currentTime - DELTA_T) {
320 5167 : timeToLoadNext += loadingDuration;
321 : } else {
322 2845 : timeToLoadNext = currentTime + loadingDuration;
323 : }
324 : }
325 :
326 10102 : static_cast<MSStageDriving*>(t->getCurrentStage())->setVehicle(vehicle);
327 10102 : if (t->getCurrentStage()->getOriginStop() != nullptr) {
328 5013 : t->getCurrentStage()->getOriginStop()->removeTransportable(*i);
329 : }
330 : i = transportables.erase(i);
331 10102 : myWaitingForVehicleNumber--;
332 : ret = true;
333 : } else {
334 : ++i;
335 : }
336 : }
337 55062 : if (transportables.empty()) {
338 : myWaiting4Vehicle.erase(wait);
339 : }
340 55062 : if (ret && timeToLoadNext >= 0) {
341 : //if the time a transportable needs to get loaded on the vehicle extends the duration of the stop of the vehicle extend
342 : //the duration by setting it to the loading duration of the transportable
343 5382 : stopDuration = MAX2(stopDuration, timeToLoadNext - currentTime);
344 : }
345 : }
346 1756646 : return ret;
347 : }
348 :
349 :
350 : bool
351 14645307 : MSTransportableControl::hasTransportables() const {
352 14645307 : return !myTransportables.empty();
353 : }
354 :
355 :
356 : bool
357 2065067 : MSTransportableControl::hasNonWaiting() const {
358 2065067 : return !myWaiting4Departure.empty() || getMovingNumber() > 0 || myWaitingUntilNumber > 0 || myHaveNewWaiting;
359 : }
360 :
361 :
362 : int
363 77342 : MSTransportableControl::getActiveCount() {
364 77342 : return (int)myWaiting4Departure.size() + myRunningNumber - myWaitingForVehicleNumber;
365 : }
366 :
367 :
368 : int
369 1352679 : MSTransportableControl::getMovingNumber() const {
370 1352679 : return myMovementModel->getActiveNumber() + myAccessNumber;
371 : }
372 :
373 :
374 : int
375 4752 : MSTransportableControl::getRidingNumber() const {
376 4752 : return myRunningNumber - myWaitingUntilNumber - myWaitingForVehicleNumber - getMovingNumber();
377 : }
378 :
379 : int
380 9692 : MSTransportableControl::getDepartedNumber() const {
381 9692 : return myLoadedNumber - myWaitingForDepartureNumber - myDiscardedNumber;
382 : }
383 :
384 : void
385 8618 : MSTransportableControl::abortAnyWaitingForVehicle() {
386 10554 : for (const auto& it : myWaiting4Vehicle) {
387 1936 : const MSEdge* edge = it.first;
388 66571 : for (MSTransportable* const p : it.second) {
389 64635 : edge->removeTransportable(p);
390 64635 : MSStageDriving* stage = dynamic_cast<MSStageDriving*>(p->getCurrentStage());
391 64635 : const std::string waitDescription = stage == nullptr ? "waiting" : stage->getWaitingDescription();
392 129270 : WRITE_WARNING(p->getObjectType() + " '" + p->getID() + "' aborted " + waitDescription + ".");
393 64635 : if (myAbortWaitingTimeout >= 0) {
394 0 : p->setAbortWaiting(-1);
395 : }
396 64635 : erase(p);
397 : }
398 : }
399 : myWaiting4Vehicle.clear();
400 8618 : myWaitingForVehicleNumber = 0;
401 8618 : }
402 :
403 : void
404 105 : MSTransportableControl::abortWaitingForVehicle(MSTransportable* t) {
405 105 : const MSEdge* edge = t->getEdge();
406 : auto it = myWaiting4Vehicle.find(edge);
407 105 : if (it != myWaiting4Vehicle.end()) {
408 105 : TransportableVector& waiting = it->second;
409 105 : auto it2 = std::find(waiting.begin(), waiting.end(), t);
410 105 : if (it2 != waiting.end()) {
411 105 : if (myAbortWaitingTimeout >= 0) {
412 16 : (*it2)->setAbortWaiting(-1);
413 : }
414 : waiting.erase(it2);
415 105 : myWaitingForVehicleNumber--;
416 : }
417 : }
418 105 : }
419 :
420 : void
421 47 : MSTransportableControl::abortWaiting(MSTransportable* t) {
422 94 : for (std::map<SUMOTime, TransportableVector>::iterator it = myWaiting4Departure.begin(); it != myWaiting4Departure.end(); ++it) {
423 47 : TransportableVector& ts = it->second;
424 47 : TransportableVector::iterator it2 = std::find(ts.begin(), ts.end(), t);
425 47 : if (it2 != ts.end()) {
426 : ts.erase(it2);
427 : }
428 : }
429 47 : for (std::map<SUMOTime, TransportableVector>::iterator it = myWaitingUntil.begin(); it != myWaitingUntil.end(); ++it) {
430 0 : TransportableVector& ts = it->second;
431 0 : TransportableVector::iterator it2 = std::find(ts.begin(), ts.end(), t);
432 0 : if (it2 != ts.end()) {
433 : ts.erase(it2);
434 : }
435 : }
436 47 : }
437 :
438 :
439 : MSTransportable*
440 282179 : MSTransportableControl::buildPerson(const SUMOVehicleParameter* pars, MSVehicleType* vtype, MSTransportable::MSTransportablePlan* plan,
441 : SumoRNG* rng) const {
442 282179 : const double speedFactor = vtype->computeChosenSpeedDeviation(rng);
443 282179 : return new MSPerson(pars, vtype, plan, speedFactor);
444 : }
445 :
446 :
447 : MSTransportable*
448 196944 : MSTransportableControl::buildContainer(const SUMOVehicleParameter* pars, MSVehicleType* vtype, MSTransportable::MSTransportablePlan* plan) const {
449 196944 : return new MSTransportable(pars, vtype, plan, false);
450 : }
451 :
452 :
453 : void
454 29 : MSTransportableControl::saveState(OutputDevice& out) {
455 29 : std::ostringstream oss;
456 174 : oss << myRunningNumber << " " << myLoadedNumber << " " << myEndedNumber << " " << myWaitingForDepartureNumber << " " << myArrivedNumber << " " << myDiscardedNumber;
457 116 : oss << " " << myJammedNumber << " " << myWaitingForVehicleNumber << " " << myWaitingUntilNumber << " " << myHaveNewWaiting;
458 58 : out.writeAttr(SUMO_ATTR_STATE, oss.str());
459 72 : for (const auto& it : myTransportables) {
460 43 : it.second->saveState(out);
461 : }
462 29 : }
463 :
464 :
465 : void
466 34 : MSTransportableControl::loadState(const std::string& state) {
467 34 : std::istringstream iss(state);
468 34 : iss >> myRunningNumber >> myLoadedNumber >> myEndedNumber >> myWaitingForDepartureNumber >> myArrivedNumber >> myDiscardedNumber;
469 34 : iss >> myJammedNumber >> myWaitingForVehicleNumber >> myWaitingUntilNumber >> myHaveNewWaiting;
470 34 : }
471 :
472 : void
473 10044 : MSTransportableControl::clearState() {
474 43638 : for (std::map<std::string, MSTransportable*>::iterator i = myTransportables.begin(); i != myTransportables.end(); ++i) {
475 33594 : delete (*i).second;
476 : }
477 : myTransportables.clear();
478 : myWaiting4Vehicle.clear();
479 : myWaiting4Departure.clear();
480 : myWaitingUntil.clear();
481 10044 : myLoadedNumber = 0;
482 10044 : myDiscardedNumber = 0;
483 10044 : myRunningNumber = 0;
484 10044 : myJammedNumber = 0;
485 10044 : myWaitingForDepartureNumber = 0;
486 10044 : myWaitingForVehicleNumber = 0;
487 10044 : myWaitingUntilNumber = 0;
488 10044 : myEndedNumber = 0;
489 10044 : myArrivedNumber = 0;
490 10044 : myHaveNewWaiting = false;
491 10044 : if (myMovementModel != myNonInteractingModel) {
492 6098 : myMovementModel->clearState();
493 : }
494 10044 : myNonInteractingModel->clearState();
495 10044 : }
496 :
497 : /****************************************************************************/
|