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 10207 : MSTransportableControl::MSTransportableControl(const bool isPerson):
50 10207 : myLoadedNumber(0),
51 10207 : myDiscardedNumber(0),
52 10207 : myRunningNumber(0),
53 10207 : myJammedNumber(0),
54 10207 : myWaitingForDepartureNumber(0),
55 10207 : myWaitingForVehicleNumber(0),
56 10207 : myWaitingUntilNumber(0),
57 10207 : myAccessNumber(0),
58 10207 : myEndedNumber(0),
59 10207 : myArrivedNumber(0),
60 10207 : myTeleportsAbortWait(0),
61 10207 : myTeleportsWrongDest(0),
62 10207 : myHaveNewWaiting(false) {
63 10207 : const OptionsCont& oc = OptionsCont::getOptions();
64 10207 : MSNet* const net = MSNet::getInstance();
65 10207 : myMovementModel = myNonInteractingModel = new MSPModel_NonInteracting(oc, net);
66 10207 : if (isPerson) {
67 8253 : const std::string& model = oc.getString("pedestrian.model");
68 8253 : if (model == "striping") {
69 6121 : 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 2132 : } else if (model != "nonInteracting") {
75 24 : delete myNonInteractingModel;
76 72 : throw ProcessError(TLF("Unknown pedestrian model '%'", model));
77 : }
78 : }
79 20366 : if (oc.isSet("vehroute-output")) {
80 1680 : myRouteInfos.routeOut = &OutputDevice::getDeviceByOption("vehroute-output");
81 : }
82 20366 : 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 20366 : if (oc.isSet("personinfo-output")) {
87 34 : OutputDevice::createDeviceByOption("personinfo-output", "tripinfos", "tripinfo_file.xsd");
88 : }
89 10183 : myAbortWaitingTimeout = string2time(oc.getString("time-to-teleport.ride"));
90 10183 : myMaxTransportableNumber = isPerson ? oc.getInt("max-num-persons") : -1;
91 10207 : }
92 :
93 :
94 18569 : MSTransportableControl::~MSTransportableControl() {
95 10157 : clearState();
96 10157 : if (myMovementModel != myNonInteractingModel) {
97 6106 : delete myMovementModel;
98 : }
99 10157 : delete myNonInteractingModel;
100 18569 : }
101 :
102 :
103 : bool
104 528612 : MSTransportableControl::add(MSTransportable* transportable) {
105 528612 : const SUMOVehicleParameter& param = transportable->getParameter();
106 528612 : if (myTransportables.find(param.id) == myTransportables.end()) {
107 528596 : myTransportables[param.id] = transportable;
108 528596 : const SUMOTime step = param.depart % DELTA_T == 0 ? param.depart : (param.depart / DELTA_T + 1) * DELTA_T;
109 528596 : myWaiting4Departure[step].push_back(transportable);
110 528596 : myLoadedNumber++;
111 528596 : 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 11924559 : MSTransportableControl::get(const std::string& id) const {
138 : std::map<std::string, MSTransportable*>::const_iterator i = myTransportables.find(id);
139 11924559 : if (i == myTransportables.end()) {
140 : return nullptr;
141 : }
142 11917114 : return (*i).second;
143 : }
144 :
145 :
146 : void
147 498734 : MSTransportableControl::erase(MSTransportable* transportable) {
148 498734 : const OptionsCont& oc = OptionsCont::getOptions();
149 997468 : if (oc.isSet("personinfo-output")) {
150 340 : transportable->tripInfoOutput(OutputDevice::getDeviceByOption("personinfo-output"));
151 997128 : } else if (oc.isSet("tripinfo-output")) {
152 71330 : transportable->tripInfoOutput(OutputDevice::getDeviceByOption("tripinfo-output"));
153 925798 : } 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 993589 : if (oc.isSet("vehroute-output") || oc.isSet("personroute-output")) {
159 4121 : if (transportable->hasArrived() || oc.getBool("vehroute-output.write-unfinished")) {
160 : // @todo: adapt this if we ever introduce person-device.vehroute
161 7658 : if (transportable->getBoolParam("has.vehroute.person-device", false, true)) {
162 7418 : 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 7174 : 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 498734 : if (i != myTransportables.end()) {
176 498734 : if (i->second->hasDeparted()) {
177 498448 : myRunningNumber--;
178 : }
179 498734 : myEndedNumber++;
180 1194809 : MSNet::getInstance()->informTransportableStateListener(transportable,
181 498734 : transportable->isPerson() ? MSNet::TransportableState::PERSON_ARRIVED : MSNet::TransportableState::CONTAINER_ARRIVED);
182 498734 : delete i->second;
183 : myTransportables.erase(i);
184 : }
185 498734 : }
186 :
187 :
188 : void
189 641 : MSTransportableControl::eraseAll() {
190 : // avoid taxi device having dangling references to erased customers
191 641 : MSDevice_Taxi::allCustomersErased();
192 873 : while (loadedBegin() != loadedEnd()) {
193 232 : erase(loadedBegin()->second);
194 : }
195 641 : }
196 :
197 :
198 : void
199 125007 : MSTransportableControl::setWaitEnd(const SUMOTime time, MSTransportable* transportable) {
200 125007 : const SUMOTime step = time % DELTA_T == 0 ? time : (time / DELTA_T + 1) * DELTA_T;
201 : // avoid double registration
202 125007 : const TransportableVector& transportables = myWaitingUntil[step];
203 125007 : if (std::find(transportables.begin(), transportables.end(), transportable) == transportables.end()) {
204 125007 : myWaitingUntil[step].push_back(transportable);
205 125007 : myWaitingUntilNumber++;
206 : }
207 125007 : }
208 :
209 :
210 : void
211 9970950 : MSTransportableControl::checkWaiting(MSNet* net, const SUMOTime time) {
212 9970950 : myHaveNewWaiting = false;
213 20250166 : while (myWaiting4Departure.find(time) != myWaiting4Departure.end()) {
214 308315 : TransportableVector& transportables = myWaiting4Departure[time];
215 : // we cannot use an iterator here because there might be additions to the vector while proceeding
216 816108 : for (auto it = transportables.begin(); it != transportables.end();) {
217 507946 : MSTransportable* t = *it;
218 507946 : 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 507842 : } else if (myMaxTransportableNumber == 0) {
224 160 : erase(t);
225 : it = transportables.erase(it);
226 160 : continue;
227 : }
228 : it = transportables.erase(it);
229 507682 : myWaitingForDepartureNumber--;
230 507682 : const bool isPerson = t->isPerson();
231 507682 : t->setDeparted(time);
232 507682 : if (t->proceed(net, time)) {
233 507633 : myRunningNumber++;
234 705006 : MSNet::getInstance()->informTransportableStateListener(t,
235 : isPerson ? MSNet::TransportableState::PERSON_DEPARTED : MSNet::TransportableState::CONTAINER_DEPARTED);
236 507633 : const OptionsCont& oc = OptionsCont::getOptions();
237 1015266 : 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 10048711 : while (myWaitingUntil.find(time) != myWaitingUntil.end()) {
252 : // make a copy because 0-duration stops might modify the vector
253 77817 : const TransportableVector transportables = myWaitingUntil[time];
254 : myWaitingUntil.erase(time);
255 202542 : for (MSTransportable* t : transportables) {
256 124732 : myWaitingUntilNumber--;
257 124732 : if (!t->proceed(net, time)) {
258 18633 : erase(t);
259 : }
260 : }
261 77817 : }
262 9970894 : }
263 :
264 :
265 : void
266 42 : MSTransportableControl::forceDeparture() {
267 42 : myRunningNumber++;
268 42 : }
269 :
270 :
271 : void
272 134439 : MSTransportableControl::addWaiting(const MSEdge* const edge, MSTransportable* transportable) {
273 134439 : myWaiting4Vehicle[edge].push_back(transportable);
274 134439 : myWaitingForVehicleNumber++;
275 134439 : myHaveNewWaiting = true;
276 134439 : if (myAbortWaitingTimeout >= 0) {
277 16 : transportable->setAbortWaiting(myAbortWaitingTimeout);
278 : }
279 134439 : }
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 5632900 : 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 5632900 : if (wait != myWaiting4Vehicle.end()) {
303 3873288 : const SUMOTime currentTime = SIMSTEP;
304 3873288 : TransportableVector& transportables = wait->second;
305 4408827 : for (TransportableVector::iterator i = transportables.begin(); i != transportables.end();) {
306 4349740 : MSTransportable* const t = *i;
307 8646086 : if (t->isWaitingFor(vehicle) && (t == force ||
308 4296346 : (vehicle->allowsBoarding(t)
309 4050717 : && timeToLoadNext - DELTA_T <= currentTime
310 3886782 : && vehicle->isStoppedInRange(t->getEdgePos(), MSGlobals::gStopTolerance)))) {
311 3883605 : edge->removeTransportable(t);
312 3883605 : vehicle->addTransportable(t);
313 69404 : if (myAbortWaitingTimeout >= 0) {
314 0 : t->setAbortWaiting(-1);
315 : }
316 69404 : if (timeToLoadNext >= 0) { // meso does not have loading times
317 75572 : 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 37786 : if (timeToLoadNext > currentTime - DELTA_T) {
320 34514 : timeToLoadNext += loadingDuration;
321 : } else {
322 3272 : timeToLoadNext = currentTime + loadingDuration;
323 : }
324 : }
325 :
326 69404 : static_cast<MSStageDriving*>(t->getCurrentStage())->setVehicle(vehicle);
327 69404 : if (t->getCurrentStage()->getOriginStop() != nullptr) {
328 64036 : t->getCurrentStage()->getOriginStop()->removeTransportable(*i);
329 : }
330 : i = transportables.erase(i);
331 69404 : myWaitingForVehicleNumber--;
332 : ret = true;
333 : } else {
334 : ++i;
335 : }
336 : }
337 59087 : if (transportables.empty()) {
338 : myWaiting4Vehicle.erase(wait);
339 : }
340 59087 : 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 8239 : stopDuration = MAX2(stopDuration, timeToLoadNext - currentTime);
344 : }
345 : }
346 1818699 : return ret;
347 : }
348 :
349 :
350 : bool
351 17535821 : MSTransportableControl::hasTransportables() const {
352 17535821 : return !myTransportables.empty();
353 : }
354 :
355 :
356 : bool
357 2063837 : MSTransportableControl::hasNonWaiting() const {
358 2063837 : return !myWaiting4Departure.empty() || getMovingNumber() > 0 || myWaitingUntilNumber > 0 || myHaveNewWaiting;
359 : }
360 :
361 :
362 : int
363 86445 : MSTransportableControl::getActiveCount() {
364 86445 : return (int)myWaiting4Departure.size() + myRunningNumber - myWaitingForVehicleNumber;
365 : }
366 :
367 :
368 : int
369 1367941 : MSTransportableControl::getMovingNumber() const {
370 1367941 : return myMovementModel->getActiveNumber() + myAccessNumber;
371 : }
372 :
373 :
374 : int
375 7608 : MSTransportableControl::getRidingNumber() const {
376 7608 : return myRunningNumber - myWaitingUntilNumber - myWaitingForVehicleNumber - getMovingNumber();
377 : }
378 :
379 : int
380 12596 : MSTransportableControl::getDepartedNumber() const {
381 12596 : return myLoadedNumber - myWaitingForDepartureNumber - myDiscardedNumber;
382 : }
383 :
384 : void
385 8715 : MSTransportableControl::abortAnyWaitingForVehicle() {
386 10647 : for (const auto& it : myWaiting4Vehicle) {
387 1932 : const MSEdge* edge = it.first;
388 66564 : for (MSTransportable* const p : it.second) {
389 64632 : edge->removeTransportable(p);
390 64632 : MSStageDriving* stage = dynamic_cast<MSStageDriving*>(p->getCurrentStage());
391 64632 : const std::string waitDescription = stage == nullptr ? "waiting" : stage->getWaitingDescription();
392 129264 : WRITE_WARNING(p->getObjectType() + " '" + p->getID() + "' aborted " + waitDescription + ".");
393 64632 : if (myAbortWaitingTimeout >= 0) {
394 0 : p->setAbortWaiting(-1);
395 : }
396 64632 : erase(p);
397 : }
398 : }
399 : myWaiting4Vehicle.clear();
400 8715 : myWaitingForVehicleNumber = 0;
401 8715 : }
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 42 : MSTransportableControl::abortWaiting(MSTransportable* t) {
422 84 : for (std::map<SUMOTime, TransportableVector>::iterator it = myWaiting4Departure.begin(); it != myWaiting4Departure.end(); ++it) {
423 42 : TransportableVector& ts = it->second;
424 42 : TransportableVector::iterator it2 = std::find(ts.begin(), ts.end(), t);
425 42 : if (it2 != ts.end()) {
426 : ts.erase(it2);
427 : }
428 : }
429 42 : 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 42 : }
437 :
438 :
439 : MSTransportable*
440 301639 : MSTransportableControl::buildPerson(const SUMOVehicleParameter* pars, MSVehicleType* vtype, MSTransportable::MSTransportablePlan* plan,
441 : SumoRNG* rng) const {
442 301639 : const double speedFactor = vtype->computeChosenSpeedDeviation(pars->speedFactor, rng);
443 301639 : 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 53 : MSTransportableControl::saveState(OutputDevice& out) {
455 53 : std::ostringstream oss;
456 318 : oss << myRunningNumber << " " << myLoadedNumber << " " << myEndedNumber << " " << myWaitingForDepartureNumber << " " << myArrivedNumber << " " << myDiscardedNumber;
457 159 : oss << " " << myJammedNumber << " " << myWaitingForVehicleNumber << " " << myHaveNewWaiting;
458 53 : out.writeAttr(SUMO_ATTR_STATE, oss.str());
459 268 : for (const auto& it : myTransportables) {
460 215 : it.second->saveState(out);
461 : }
462 53 : }
463 :
464 :
465 : void
466 57 : MSTransportableControl::loadState(const std::string& state) {
467 57 : std::istringstream iss(state);
468 57 : iss >> myRunningNumber >> myLoadedNumber >> myEndedNumber >> myWaitingForDepartureNumber >> myArrivedNumber >> myDiscardedNumber;
469 57 : iss >> myJammedNumber >> myWaitingForVehicleNumber >> myHaveNewWaiting;
470 57 : }
471 :
472 : void
473 10180 : MSTransportableControl::clearState() {
474 39987 : for (std::map<std::string, MSTransportable*>::iterator i = myTransportables.begin(); i != myTransportables.end(); ++i) {
475 29807 : delete (*i).second;
476 : }
477 : myTransportables.clear();
478 : myWaiting4Vehicle.clear();
479 : myWaiting4Departure.clear();
480 : myWaitingUntil.clear();
481 10180 : myLoadedNumber = 0;
482 10180 : myDiscardedNumber = 0;
483 10180 : myRunningNumber = 0;
484 10180 : myJammedNumber = 0;
485 10180 : myWaitingForDepartureNumber = 0;
486 10180 : myWaitingForVehicleNumber = 0;
487 10180 : myWaitingUntilNumber = 0;
488 10180 : myEndedNumber = 0;
489 10180 : myArrivedNumber = 0;
490 10180 : myHaveNewWaiting = false;
491 10180 : if (myMovementModel != myNonInteractingModel) {
492 6126 : myMovementModel->clearState();
493 : }
494 10180 : myNonInteractingModel->clearState();
495 10180 : }
496 :
497 : /****************************************************************************/
|