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 HAVE_JUPEDSIM
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 10232 : MSTransportableControl::MSTransportableControl(const bool isPerson):
50 10232 : myLoadedNumber(0),
51 10232 : myDiscardedNumber(0),
52 10232 : myRunningNumber(0),
53 10232 : myJammedNumber(0),
54 10232 : myWaitingForDepartureNumber(0),
55 10232 : myWaitingForVehicleNumber(0),
56 10232 : myWaitingUntilNumber(0),
57 10232 : myAccessNumber(0),
58 10232 : myEndedNumber(0),
59 10232 : myArrivedNumber(0),
60 10232 : myTeleportsAbortWait(0),
61 10232 : myTeleportsWrongDest(0),
62 10232 : myHaveNewWaiting(false) {
63 10232 : const OptionsCont& oc = OptionsCont::getOptions();
64 10232 : MSNet* const net = MSNet::getInstance();
65 10232 : myMovementModel = myNonInteractingModel = new MSPModel_NonInteracting(oc, net);
66 10232 : if (isPerson) {
67 8277 : const std::string& model = oc.getString("pedestrian.model");
68 8277 : if (model == "striping") {
69 6128 : myMovementModel = new MSPModel_Striping(oc, net);
70 : #ifdef HAVE_JUPEDSIM
71 : } else if (model == "jupedsim") {
72 : myMovementModel = new MSPModel_JuPedSim(oc, net);
73 : #endif
74 2149 : } else if (model != "nonInteracting") {
75 24 : delete myNonInteractingModel;
76 72 : throw ProcessError(TLF("Unknown pedestrian model '%'", model));
77 : }
78 : }
79 20416 : if (oc.isSet("vehroute-output")) {
80 1672 : myRouteInfos.routeOut = &OutputDevice::getDeviceByOption("vehroute-output");
81 : }
82 20416 : 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 20416 : if (oc.isSet("personinfo-output")) {
87 36 : OutputDevice::createDeviceByOption("personinfo-output", "tripinfos", "tripinfo_file.xsd");
88 : }
89 10208 : myAbortWaitingTimeout = string2time(oc.getString("time-to-teleport.ride"));
90 10208 : myMaxTransportableNumber = isPerson ? oc.getInt("max-num-persons") : -1;
91 10256 : }
92 :
93 :
94 18613 : MSTransportableControl::~MSTransportableControl() {
95 10185 : clearState();
96 10185 : if (myMovementModel != myNonInteractingModel) {
97 6116 : delete myMovementModel;
98 : }
99 10185 : delete myNonInteractingModel;
100 18613 : }
101 :
102 :
103 : bool
104 530483 : MSTransportableControl::add(MSTransportable* transportable) {
105 530483 : const SUMOVehicleParameter& param = transportable->getParameter();
106 530483 : if (myTransportables.find(param.id) == myTransportables.end()) {
107 530467 : myTransportables[param.id] = transportable;
108 530467 : const SUMOTime step = param.depart % DELTA_T == 0 ? param.depart : (param.depart / DELTA_T + 1) * DELTA_T;
109 530467 : myWaiting4Departure[step].push_back(transportable);
110 530467 : myLoadedNumber++;
111 530467 : myWaitingForDepartureNumber++;
112 : return true;
113 : }
114 : return false;
115 : }
116 :
117 :
118 : void
119 219 : MSTransportableControl::fixLoadCount(const MSTransportable* transportable) {
120 219 : myLoadedNumber--;
121 219 : if (transportable->hasDeparted()) {
122 134 : const SUMOVehicleParameter& param = transportable->getParameter();
123 134 : const SUMOTime step = param.depart % DELTA_T == 0 ? param.depart : (param.depart / DELTA_T + 1) * DELTA_T;
124 134 : TransportableVector& waiting = myWaiting4Departure[step];
125 134 : auto it = std::find(waiting.begin(), waiting.end(), transportable);
126 134 : if (it != waiting.end()) {
127 : waiting.erase(it);
128 134 : if (waiting.size() == 0) {
129 : myWaiting4Departure.erase(step);
130 : }
131 : }
132 : }
133 219 : }
134 :
135 :
136 : MSTransportable*
137 13800610 : MSTransportableControl::get(const std::string& id) const {
138 : std::map<std::string, MSTransportable*>::const_iterator i = myTransportables.find(id);
139 13800610 : if (i == myTransportables.end()) {
140 : return nullptr;
141 : }
142 13793157 : return (*i).second;
143 : }
144 :
145 :
146 : void
147 500416 : MSTransportableControl::erase(MSTransportable* transportable) {
148 500416 : const OptionsCont& oc = OptionsCont::getOptions();
149 1000832 : if (oc.isSet("personinfo-output")) {
150 360 : transportable->tripInfoOutput(OutputDevice::getDeviceByOption("personinfo-output"));
151 1000472 : } else if (oc.isSet("tripinfo-output")) {
152 71344 : transportable->tripInfoOutput(OutputDevice::getDeviceByOption("tripinfo-output"));
153 929128 : } else if (oc.getBool("duration-log.statistics")) {
154 : // collecting statistics is a sideffect
155 21785 : OutputDevice_String dev;
156 21785 : transportable->tripInfoOutput(dev);
157 21785 : }
158 996965 : if (oc.isSet("vehroute-output") || oc.isSet("personroute-output")) {
159 4109 : if (transportable->hasArrived() || oc.getBool("vehroute-output.write-unfinished")) {
160 : // @todo: adapt this if we ever introduce person-device.vehroute
161 7634 : if (transportable->getBoolParam("has.vehroute.person-device", false, true)) {
162 7394 : 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->getNumericalID(), od.getString());
168 122 : } else {
169 7150 : 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 500416 : if (i != myTransportables.end()) {
176 500416 : if (i->second->hasDeparted()) {
177 500130 : myRunningNumber--;
178 : }
179 500416 : myEndedNumber++;
180 1198183 : MSNet::getInstance()->informTransportableStateListener(transportable,
181 500416 : transportable->isPerson() ? MSNet::TransportableState::PERSON_ARRIVED : MSNet::TransportableState::CONTAINER_ARRIVED);
182 500416 : delete i->second;
183 : myTransportables.erase(i);
184 : }
185 500416 : }
186 :
187 :
188 : void
189 647 : MSTransportableControl::eraseAll() {
190 : // avoid taxi device having dangling references to erased customers
191 647 : MSDevice_Taxi::allCustomersErased();
192 879 : while (loadedBegin() != loadedEnd()) {
193 232 : erase(loadedBegin()->second);
194 : }
195 647 : }
196 :
197 :
198 : void
199 125097 : MSTransportableControl::setWaitEnd(const SUMOTime time, MSTransportable* transportable) {
200 125097 : const SUMOTime step = time % DELTA_T == 0 ? time : (time / DELTA_T + 1) * DELTA_T;
201 : // avoid double registration
202 125097 : const TransportableVector& transportables = myWaitingUntil[step];
203 125097 : if (std::find(transportables.begin(), transportables.end(), transportable) == transportables.end()) {
204 125097 : myWaitingUntil[step].push_back(transportable);
205 125097 : myWaitingUntilNumber++;
206 : }
207 125097 : }
208 :
209 :
210 : void
211 81277797 : MSTransportableControl::checkWaiting(MSNet* net, const SUMOTime time) {
212 81277797 : myHaveNewWaiting = false;
213 162864892 : while (myWaiting4Departure.find(time) != myWaiting4Departure.end()) {
214 309340 : TransportableVector& transportables = myWaiting4Departure[time];
215 : // we cannot use an iterator here because there might be additions to the vector while proceeding
216 818771 : for (auto it = transportables.begin(); it != transportables.end();) {
217 509577 : MSTransportable* t = *it;
218 509577 : 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 509473 : } else if (myMaxTransportableNumber == 0) {
224 160 : erase(t);
225 : it = transportables.erase(it);
226 160 : continue;
227 : }
228 : it = transportables.erase(it);
229 509313 : myWaitingForDepartureNumber--;
230 509313 : const bool isPerson = t->isPerson();
231 509313 : t->setDeparted(time);
232 509313 : if (t->proceed(net, time)) {
233 509271 : myRunningNumber++;
234 706654 : MSNet::getInstance()->informTransportableStateListener(t,
235 : isPerson ? MSNet::TransportableState::PERSON_DEPARTED : MSNet::TransportableState::CONTAINER_DEPARTED);
236 509271 : const OptionsCont& oc = OptionsCont::getOptions();
237 1018542 : 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 81355578 : while (myWaitingUntil.find(time) != myWaitingUntil.end()) {
252 : // make a copy because 0-duration stops might modify the vector
253 77829 : const TransportableVector transportables = myWaitingUntil[time];
254 : myWaitingUntil.erase(time);
255 202643 : for (MSTransportable* t : transportables) {
256 124820 : myWaitingUntilNumber--;
257 124820 : if (!t->proceed(net, time)) {
258 18635 : erase(t);
259 : }
260 : }
261 77829 : }
262 81277749 : }
263 :
264 :
265 : #ifndef THREAD_POOL
266 : #ifdef HAVE_FOX
267 : void
268 4512 : MSTransportableControl::addPendingRouting(MSTransportable* transportable) {
269 4512 : myPendingRouting.push_back(transportable);
270 4512 : }
271 :
272 :
273 : void
274 83067811 : MSTransportableControl::processPendingRouting(MSNet* net, const SUMOTime time) {
275 83072314 : for (MSTransportable* t : myPendingRouting) {
276 4511 : if (!t->proceed(net, time)) {
277 0 : erase(t);
278 : }
279 : }
280 : myPendingRouting.clear();
281 83067803 : }
282 : #endif
283 : #endif
284 :
285 :
286 : void
287 42 : MSTransportableControl::forceDeparture() {
288 42 : myRunningNumber++;
289 42 : }
290 :
291 :
292 : void
293 134628 : MSTransportableControl::addWaiting(const MSEdge* const edge, MSTransportable* transportable) {
294 134628 : myWaiting4Vehicle[edge].push_back(transportable);
295 134628 : myWaitingForVehicleNumber++;
296 134628 : myHaveNewWaiting = true;
297 134628 : if (myAbortWaitingTimeout >= 0) {
298 16 : transportable->setAbortWaiting(myAbortWaitingTimeout);
299 : }
300 134628 : }
301 :
302 :
303 : bool
304 83 : MSTransportableControl::hasAnyWaiting(const MSEdge* edge, SUMOVehicle* vehicle) const {
305 : const auto wait = myWaiting4Vehicle.find(edge);
306 83 : if (wait != myWaiting4Vehicle.end()) {
307 44 : for (const MSTransportable* t : wait->second) {
308 : if (t->isWaitingFor(vehicle)
309 39 : && vehicle->allowsBoarding(t)
310 78 : && vehicle->isStoppedInRange(t->getEdgePos(), MSGlobals::gStopTolerance, true)) {
311 : return true;
312 : }
313 : }
314 : }
315 : return false;
316 : }
317 :
318 :
319 : bool
320 5923783 : MSTransportableControl::loadAnyWaiting(const MSEdge* edge, SUMOVehicle* vehicle, SUMOTime& timeToLoadNext, SUMOTime& stopDuration, MSTransportable* const force) {
321 : bool ret = false;
322 : const auto wait = myWaiting4Vehicle.find(edge);
323 5923783 : if (wait != myWaiting4Vehicle.end()) {
324 4152950 : const SUMOTime currentTime = SIMSTEP;
325 4152950 : TransportableVector& transportables = wait->second;
326 4688675 : for (TransportableVector::iterator i = transportables.begin(); i != transportables.end();) {
327 4629530 : MSTransportable* const t = *i;
328 9205707 : if (t->isWaitingFor(vehicle) && (t == force ||
329 4576177 : (vehicle->allowsBoarding(t)
330 4330545 : && timeToLoadNext - DELTA_T <= currentTime
331 4166614 : && vehicle->isStoppedInRange(t->getEdgePos(), MSGlobals::gStopTolerance)))) {
332 4163393 : edge->removeTransportable(t);
333 4163393 : vehicle->addTransportable(t);
334 69588 : if (myAbortWaitingTimeout >= 0) {
335 0 : t->setAbortWaiting(-1);
336 : }
337 69588 : if (timeToLoadNext >= 0) { // meso does not have loading times
338 75588 : const SUMOTime loadingDuration = (SUMOTime)((double)vehicle->getVehicleType().getLoadingDuration(t->isPerson()) * t->getVehicleType().getBoardingFactor());
339 : //update the time point at which the next transportable can be loaded on the vehicle
340 37794 : if (timeToLoadNext > currentTime - DELTA_T) {
341 34503 : timeToLoadNext += loadingDuration;
342 : } else {
343 3291 : timeToLoadNext = currentTime + loadingDuration;
344 : }
345 : }
346 :
347 69588 : static_cast<MSStageDriving*>(t->getCurrentStage())->setVehicle(vehicle);
348 69588 : if (t->getCurrentStage()->getOriginStop() != nullptr) {
349 64119 : t->getCurrentStage()->getOriginStop()->removeTransportable(*i);
350 : }
351 : i = transportables.erase(i);
352 69588 : myWaitingForVehicleNumber--;
353 : ret = true;
354 : } else {
355 : ++i;
356 : }
357 : }
358 59145 : if (transportables.empty()) {
359 : myWaiting4Vehicle.erase(wait);
360 : }
361 59145 : if (ret && timeToLoadNext >= 0) {
362 : //if the time a transportable needs to get loaded on the vehicle extends the duration of the stop of the vehicle extend
363 : //the duration by setting it to the loading duration of the transportable
364 8253 : stopDuration = MAX2(stopDuration, timeToLoadNext - currentTime);
365 : }
366 : }
367 1829978 : return ret;
368 : }
369 :
370 :
371 : bool
372 89441166 : MSTransportableControl::hasTransportables() const {
373 89441166 : return !myTransportables.empty();
374 : }
375 :
376 :
377 : bool
378 72769366 : MSTransportableControl::hasNonWaiting() const {
379 72769366 : return !myWaiting4Departure.empty() || getMovingNumber() > 0 || myWaitingUntilNumber > 0 || myHaveNewWaiting;
380 : }
381 :
382 :
383 : int
384 86116 : MSTransportableControl::getActiveCount() {
385 86116 : return (int)myWaiting4Departure.size() + myRunningNumber - myWaitingForVehicleNumber;
386 : }
387 :
388 :
389 : int
390 72073254 : MSTransportableControl::getMovingNumber() const {
391 72073254 : return myMovementModel->getActiveNumber() + myAccessNumber;
392 : }
393 :
394 :
395 : int
396 7752 : MSTransportableControl::getRidingNumber() const {
397 7752 : return myRunningNumber - myWaitingUntilNumber - myWaitingForVehicleNumber - getMovingNumber();
398 : }
399 :
400 : int
401 12756 : MSTransportableControl::getDepartedNumber() const {
402 12756 : return myLoadedNumber - myWaitingForDepartureNumber - myDiscardedNumber;
403 : }
404 :
405 : void
406 8736 : MSTransportableControl::abortAnyWaitingForVehicle() {
407 10669 : for (const auto& it : myWaiting4Vehicle) {
408 1933 : const MSEdge* edge = it.first;
409 66567 : for (MSTransportable* const p : it.second) {
410 64634 : edge->removeTransportable(p);
411 64634 : MSStageDriving* stage = dynamic_cast<MSStageDriving*>(p->getCurrentStage());
412 64634 : const std::string waitDescription = stage == nullptr ? "waiting" : stage->getWaitingDescription();
413 129268 : WRITE_WARNING(p->getObjectType() + " '" + p->getID() + "' aborted " + waitDescription + ".");
414 64634 : if (myAbortWaitingTimeout >= 0) {
415 0 : p->setAbortWaiting(-1);
416 : }
417 64634 : erase(p);
418 : }
419 : }
420 : myWaiting4Vehicle.clear();
421 8736 : myWaitingForVehicleNumber = 0;
422 8736 : }
423 :
424 : void
425 108 : MSTransportableControl::abortWaitingForVehicle(MSTransportable* t) {
426 108 : const MSEdge* edge = t->getEdge();
427 : auto it = myWaiting4Vehicle.find(edge);
428 108 : if (it != myWaiting4Vehicle.end()) {
429 108 : TransportableVector& waiting = it->second;
430 108 : auto it2 = std::find(waiting.begin(), waiting.end(), t);
431 108 : if (it2 != waiting.end()) {
432 108 : if (myAbortWaitingTimeout >= 0) {
433 16 : (*it2)->setAbortWaiting(-1);
434 : }
435 : waiting.erase(it2);
436 108 : myWaitingForVehicleNumber--;
437 : }
438 : }
439 108 : }
440 :
441 : void
442 42 : MSTransportableControl::abortWaiting(MSTransportable* t) {
443 84 : for (std::map<SUMOTime, TransportableVector>::iterator it = myWaiting4Departure.begin(); it != myWaiting4Departure.end(); ++it) {
444 42 : TransportableVector& ts = it->second;
445 42 : TransportableVector::iterator it2 = std::find(ts.begin(), ts.end(), t);
446 42 : if (it2 != ts.end()) {
447 : ts.erase(it2);
448 : }
449 : }
450 42 : for (std::map<SUMOTime, TransportableVector>::iterator it = myWaitingUntil.begin(); it != myWaitingUntil.end(); ++it) {
451 0 : TransportableVector& ts = it->second;
452 0 : TransportableVector::iterator it2 = std::find(ts.begin(), ts.end(), t);
453 0 : if (it2 != ts.end()) {
454 : ts.erase(it2);
455 : }
456 : }
457 42 : }
458 :
459 :
460 : MSTransportable*
461 302991 : MSTransportableControl::buildPerson(const SUMOVehicleParameter* pars, MSVehicleType* vtype, MSTransportable::MSTransportablePlan* plan,
462 : SumoRNG* rng) const {
463 302991 : const double speedFactor = vtype->computeChosenSpeedDeviation(pars->speedFactor, rng);
464 302991 : return new MSPerson(pars, vtype, plan, speedFactor);
465 : }
466 :
467 :
468 : MSTransportable*
469 196944 : MSTransportableControl::buildContainer(const SUMOVehicleParameter* pars, MSVehicleType* vtype, MSTransportable::MSTransportablePlan* plan) const {
470 196944 : return new MSTransportable(pars, vtype, plan, false);
471 : }
472 :
473 :
474 : void
475 53 : MSTransportableControl::saveState(OutputDevice& out) {
476 53 : std::ostringstream oss;
477 318 : oss << myRunningNumber << " " << myLoadedNumber << " " << myEndedNumber << " " << myWaitingForDepartureNumber << " " << myArrivedNumber << " " << myDiscardedNumber;
478 159 : oss << " " << myJammedNumber << " " << myWaitingForVehicleNumber << " " << myHaveNewWaiting;
479 53 : out.writeAttr(SUMO_ATTR_STATE, oss.str());
480 268 : for (const auto& it : myTransportables) {
481 215 : it.second->saveState(out);
482 : }
483 53 : }
484 :
485 :
486 : void
487 57 : MSTransportableControl::loadState(const std::string& state) {
488 57 : std::istringstream iss(state);
489 57 : iss >> myRunningNumber >> myLoadedNumber >> myEndedNumber >> myWaitingForDepartureNumber >> myArrivedNumber >> myDiscardedNumber;
490 57 : iss >> myJammedNumber >> myWaitingForVehicleNumber >> myHaveNewWaiting;
491 57 : }
492 :
493 : void
494 10203 : MSTransportableControl::clearState() {
495 40200 : for (std::map<std::string, MSTransportable*>::iterator i = myTransportables.begin(); i != myTransportables.end(); ++i) {
496 29997 : delete (*i).second;
497 : }
498 : myTransportables.clear();
499 : myWaiting4Vehicle.clear();
500 : myWaiting4Departure.clear();
501 : myWaitingUntil.clear();
502 10203 : myLoadedNumber = 0;
503 10203 : myDiscardedNumber = 0;
504 10203 : myRunningNumber = 0;
505 10203 : myJammedNumber = 0;
506 10203 : myWaitingForDepartureNumber = 0;
507 10203 : myWaitingForVehicleNumber = 0;
508 10203 : myWaitingUntilNumber = 0;
509 10203 : myEndedNumber = 0;
510 10203 : myArrivedNumber = 0;
511 10203 : myHaveNewWaiting = false;
512 10203 : if (myMovementModel != myNonInteractingModel) {
513 6134 : myMovementModel->clearState();
514 : }
515 10203 : myNonInteractingModel->clearState();
516 10203 : }
517 :
518 : /****************************************************************************/
|