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 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/MSNet.h>
40 : #include <microsim/MSEdge.h>
41 : #include <microsim/MSVehicle.h>
42 : #include <microsim/MSStoppingPlace.h>
43 :
44 :
45 : // ===========================================================================
46 : // method definitions
47 : // ===========================================================================
48 8238 : MSTransportableControl::MSTransportableControl(const bool isPerson):
49 8238 : myLoadedNumber(0),
50 8238 : myDiscardedNumber(0),
51 8238 : myRunningNumber(0),
52 8238 : myJammedNumber(0),
53 8238 : myWaitingForDepartureNumber(0),
54 8238 : myWaitingForVehicleNumber(0),
55 8238 : myWaitingUntilNumber(0),
56 8238 : myAccessNumber(0),
57 8238 : myEndedNumber(0),
58 8238 : myArrivedNumber(0),
59 8238 : myTeleportsAbortWait(0),
60 8238 : myTeleportsWrongDest(0),
61 8238 : myHaveNewWaiting(false) {
62 8238 : const OptionsCont& oc = OptionsCont::getOptions();
63 8238 : MSNet* const net = MSNet::getInstance();
64 8238 : myMovementModel = myNonInteractingModel = new MSPModel_NonInteracting(oc, net);
65 8238 : if (isPerson) {
66 7425 : const std::string& model = oc.getString("pedestrian.model");
67 7425 : if (model == "striping") {
68 5414 : myMovementModel = new MSPModel_Striping(oc, net);
69 : #ifdef JPS_VERSION
70 : } else if (model == "jupedsim") {
71 : myMovementModel = new MSPModel_JuPedSim(oc, net);
72 : #endif
73 2011 : } else if (model != "nonInteracting") {
74 24 : delete myNonInteractingModel;
75 72 : throw ProcessError(TLF("Unknown pedestrian model '%'", model));
76 : }
77 : }
78 16428 : if (oc.isSet("vehroute-output")) {
79 1557 : myRouteInfos.routeOut = &OutputDevice::getDeviceByOption("vehroute-output");
80 : }
81 16428 : if (oc.isSet("personroute-output")) {
82 24 : OutputDevice::createDeviceByOption("personroute-output", "routes", "routes_file.xsd");
83 12 : myRouteInfos.routeOut = &OutputDevice::getDeviceByOption("personroute-output");
84 : }
85 16428 : if (oc.isSet("personinfo-output")) {
86 36 : OutputDevice::createDeviceByOption("personinfo-output", "tripinfos", "tripinfo_file.xsd");
87 : }
88 8214 : myAbortWaitingTimeout = string2time(oc.getString("time-to-teleport.ride"));
89 8214 : myMaxTransportableNumber = isPerson ? oc.getInt("max-num-persons") : -1;
90 8238 : }
91 :
92 :
93 14679 : MSTransportableControl::~MSTransportableControl() {
94 8188 : clearState();
95 8188 : if (myMovementModel != myNonInteractingModel) {
96 5399 : delete myMovementModel;
97 : }
98 8188 : delete myNonInteractingModel;
99 14679 : }
100 :
101 :
102 : bool
103 513493 : MSTransportableControl::add(MSTransportable* transportable) {
104 513493 : const SUMOVehicleParameter& param = transportable->getParameter();
105 513493 : if (myTransportables.find(param.id) == myTransportables.end()) {
106 513477 : myTransportables[param.id] = transportable;
107 513477 : const SUMOTime step = param.depart % DELTA_T == 0 ? param.depart : (param.depart / DELTA_T + 1) * DELTA_T;
108 513477 : myWaiting4Departure[step].push_back(transportable);
109 513477 : myLoadedNumber++;
110 513477 : myWaitingForDepartureNumber++;
111 : return true;
112 : }
113 : return false;
114 : }
115 :
116 :
117 : void
118 48 : MSTransportableControl::fixLoadCount(const MSTransportable* transportable) {
119 48 : myLoadedNumber--;
120 48 : if (transportable->hasDeparted()) {
121 42 : const SUMOVehicleParameter& param = transportable->getParameter();
122 42 : const SUMOTime step = param.depart % DELTA_T == 0 ? param.depart : (param.depart / DELTA_T + 1) * DELTA_T;
123 42 : TransportableVector& waiting = myWaiting4Departure[step];
124 42 : auto it = std::find(waiting.begin(), waiting.end(), transportable);
125 42 : if (it != waiting.end()) {
126 : waiting.erase(it);
127 42 : if (waiting.size() == 0) {
128 : myWaiting4Departure.erase(step);
129 : }
130 : }
131 : }
132 48 : }
133 :
134 :
135 : MSTransportable*
136 521101 : MSTransportableControl::get(const std::string& id) const {
137 : std::map<std::string, MSTransportable*>::const_iterator i = myTransportables.find(id);
138 521101 : if (i == myTransportables.end()) {
139 : return nullptr;
140 : }
141 510633 : return (*i).second;
142 : }
143 :
144 :
145 : void
146 394613 : MSTransportableControl::erase(MSTransportable* transportable) {
147 394613 : const OptionsCont& oc = OptionsCont::getOptions();
148 789226 : if (oc.isSet("personinfo-output")) {
149 360 : transportable->tripInfoOutput(OutputDevice::getDeviceByOption("personinfo-output"));
150 788866 : } else if (oc.isSet("tripinfo-output")) {
151 69960 : transportable->tripInfoOutput(OutputDevice::getDeviceByOption("tripinfo-output"));
152 718906 : } else if (oc.getBool("duration-log.statistics")) {
153 : // collecting statistics is a sideffect
154 21515 : OutputDevice_String dev;
155 21515 : transportable->tripInfoOutput(dev);
156 21515 : }
157 786043 : if (oc.isSet("vehroute-output") || oc.isSet("personroute-output")) {
158 3343 : if (transportable->hasArrived() || oc.getBool("vehroute-output.write-unfinished")) {
159 : // @todo: adapt this if we ever introduce person-device.vehroute
160 6262 : if (transportable->getBoolParam("has.vehroute.person-device", false, true)) {
161 6022 : if (oc.getBool("vehroute-output.sorted")) {
162 122 : const SUMOTime departure = oc.getBool("vehroute-output.intended-depart") ? transportable->getParameter().depart : transportable->getDeparture();
163 122 : OutputDevice_String od(1);
164 122 : transportable->routeOutput(od, oc.getBool("vehroute-output.route-length"));
165 122 : MSDevice_Vehroutes::writeSortedOutput(&myRouteInfos,
166 122 : departure, transportable->getID(), od.getString());
167 122 : } else {
168 5778 : transportable->routeOutput(*myRouteInfos.routeOut, oc.getBool("vehroute-output.route-length"));
169 : }
170 : }
171 : }
172 : }
173 : const std::map<std::string, MSTransportable*>::iterator i = myTransportables.find(transportable->getID());
174 394613 : if (i != myTransportables.end()) {
175 394613 : if (i->second->hasDeparted()) {
176 394357 : myRunningNumber--;
177 : }
178 394613 : myEndedNumber++;
179 927800 : MSNet::getInstance()->informTransportableStateListener(transportable,
180 394613 : transportable->isPerson() ? MSNet::TransportableState::PERSON_ARRIVED : MSNet::TransportableState::CONTAINER_ARRIVED);
181 394613 : delete i->second;
182 : myTransportables.erase(i);
183 : }
184 394613 : }
185 :
186 :
187 : void
188 65805 : MSTransportableControl::setWaitEnd(const SUMOTime time, MSTransportable* transportable) {
189 65805 : const SUMOTime step = time % DELTA_T == 0 ? time : (time / DELTA_T + 1) * DELTA_T;
190 : // avoid double registration
191 65805 : const TransportableVector& transportables = myWaitingUntil[step];
192 65805 : if (std::find(transportables.begin(), transportables.end(), transportable) == transportables.end()) {
193 65805 : myWaitingUntil[step].push_back(transportable);
194 65805 : myWaitingUntilNumber++;
195 : }
196 65805 : }
197 :
198 :
199 : void
200 10619265 : MSTransportableControl::checkWaiting(MSNet* net, const SUMOTime time) {
201 10619265 : myHaveNewWaiting = false;
202 21546218 : while (myWaiting4Departure.find(time) != myWaiting4Departure.end()) {
203 307732 : TransportableVector& transportables = myWaiting4Departure[time];
204 : // we cannot use an iterator here because there might be additions to the vector while proceeding
205 792803 : for (auto it = transportables.begin(); it != transportables.end();) {
206 485219 : MSTransportable* t = *it;
207 485219 : if (myMaxTransportableNumber > 0 && myRunningNumber >= myMaxTransportableNumber) {
208 104 : TransportableVector& nextStep = myWaiting4Departure[time + DELTA_T];
209 104 : nextStep.insert(nextStep.begin(), transportables.begin(), transportables.end());
210 : transportables.clear();
211 : break;
212 485115 : } else if (myMaxTransportableNumber == 0) {
213 160 : erase(t);
214 : it = transportables.erase(it);
215 160 : continue;
216 : }
217 : it = transportables.erase(it);
218 484955 : myWaitingForDepartureNumber--;
219 484955 : const bool isPerson = t->isPerson();
220 484955 : t->setDeparted(time);
221 484955 : if (t->proceed(net, time)) {
222 484911 : myRunningNumber++;
223 680243 : MSNet::getInstance()->informTransportableStateListener(t,
224 : isPerson ? MSNet::TransportableState::PERSON_DEPARTED : MSNet::TransportableState::CONTAINER_DEPARTED);
225 484911 : const OptionsCont& oc = OptionsCont::getOptions();
226 969822 : if (oc.getBool("vehroute-output.sorted")) {
227 132 : const SUMOTime departure = oc.getBool("vehroute-output.intended-depart") ? t->getParameter().depart : time;
228 264 : if (oc.isSet("personroute-output")) {
229 24 : myRouteInfos.departureCounts[departure]++;
230 : } else {
231 108 : MSDevice_Vehroutes::registerTransportableDepart(departure);
232 : }
233 : }
234 : } else {
235 0 : erase(t);
236 : }
237 : }
238 : myWaiting4Departure.erase(time);
239 : }
240 10683377 : while (myWaitingUntil.find(time) != myWaitingUntil.end()) {
241 : // make a copy because 0-duration stops might modify the vector
242 64163 : const TransportableVector transportables = myWaitingUntil[time];
243 : myWaitingUntil.erase(time);
244 129440 : for (MSTransportable* t : transportables) {
245 65284 : myWaitingUntilNumber--;
246 65284 : if (!t->proceed(net, time)) {
247 18289 : erase(t);
248 : }
249 : }
250 64163 : }
251 10619214 : }
252 :
253 :
254 : void
255 41 : MSTransportableControl::forceDeparture() {
256 41 : myRunningNumber++;
257 41 : }
258 :
259 :
260 : void
261 76998 : MSTransportableControl::addWaiting(const MSEdge* const edge, MSTransportable* transportable) {
262 76998 : myWaiting4Vehicle[edge].push_back(transportable);
263 76998 : myWaitingForVehicleNumber++;
264 76998 : myHaveNewWaiting = true;
265 76998 : if (myAbortWaitingTimeout >= 0) {
266 16 : transportable->setAbortWaiting(myAbortWaitingTimeout);
267 : }
268 76998 : }
269 :
270 :
271 : bool
272 83 : MSTransportableControl::hasAnyWaiting(const MSEdge* edge, SUMOVehicle* vehicle) const {
273 : const auto wait = myWaiting4Vehicle.find(edge);
274 83 : if (wait != myWaiting4Vehicle.end()) {
275 44 : for (const MSTransportable* t : wait->second) {
276 : if (t->isWaitingFor(vehicle)
277 39 : && vehicle->allowsBoarding(t)
278 78 : && vehicle->isStoppedInRange(t->getEdgePos(), MSGlobals::gStopTolerance, true)) {
279 : return true;
280 : }
281 : }
282 : }
283 : return false;
284 : }
285 :
286 :
287 : bool
288 5739725 : MSTransportableControl::loadAnyWaiting(const MSEdge* edge, SUMOVehicle* vehicle, SUMOTime& timeToLoadNext, SUMOTime& stopDuration, MSTransportable* const force) {
289 : bool ret = false;
290 : const auto wait = myWaiting4Vehicle.find(edge);
291 5739725 : if (wait != myWaiting4Vehicle.end()) {
292 4329388 : const SUMOTime currentTime = SIMSTEP;
293 4329388 : TransportableVector& transportables = wait->second;
294 4700748 : for (TransportableVector::iterator i = transportables.begin(); i != transportables.end();) {
295 4646284 : MSTransportable* const t = *i;
296 9238942 : if (t->isWaitingFor(vehicle) && (t == force ||
297 4592658 : (vehicle->allowsBoarding(t)
298 4400319 : && timeToLoadNext - DELTA_T <= currentTime
299 4287952 : && vehicle->isStoppedInRange(t->getEdgePos(), MSGlobals::gStopTolerance)))) {
300 4284823 : edge->removeTransportable(t);
301 4284823 : vehicle->addTransportable(t);
302 9899 : if (myAbortWaitingTimeout >= 0) {
303 0 : t->setAbortWaiting(-1);
304 : }
305 9899 : if (timeToLoadNext >= 0) { // meso does not have loading times
306 15742 : const SUMOTime loadingDuration = (SUMOTime)((double)vehicle->getVehicleType().getLoadingDuration(t->isPerson()) * t->getVehicleType().getBoardingFactor());
307 : //update the time point at which the next transportable can be loaded on the vehicle
308 7871 : if (timeToLoadNext > currentTime - DELTA_T) {
309 5136 : timeToLoadNext += loadingDuration;
310 : } else {
311 2735 : timeToLoadNext = currentTime + loadingDuration;
312 : }
313 : }
314 :
315 9899 : static_cast<MSStageDriving*>(t->getCurrentStage())->setVehicle(vehicle);
316 9899 : if (t->getCurrentStage()->getOriginStop() != nullptr) {
317 5017 : t->getCurrentStage()->getOriginStop()->removeTransportable(*i);
318 : }
319 : i = transportables.erase(i);
320 9899 : myWaitingForVehicleNumber--;
321 : ret = true;
322 : } else {
323 : ++i;
324 : }
325 : }
326 54464 : if (transportables.empty()) {
327 : myWaiting4Vehicle.erase(wait);
328 : }
329 54464 : if (ret && timeToLoadNext >= 0) {
330 : //if the time a transportable needs to get loaded on the vehicle extends the duration of the stop of the vehicle extend
331 : //the duration by setting it to the loading duration of the transportable
332 5256 : stopDuration = MAX2(stopDuration, timeToLoadNext - currentTime);
333 : }
334 : }
335 1464801 : return ret;
336 : }
337 :
338 :
339 : bool
340 22294277 : MSTransportableControl::hasTransportables() const {
341 22294277 : return !myTransportables.empty();
342 : }
343 :
344 :
345 : bool
346 1188955 : MSTransportableControl::hasNonWaiting() const {
347 1188955 : return !myWaiting4Departure.empty() || getMovingNumber() > 0 || myWaitingUntilNumber > 0 || myHaveNewWaiting;
348 : }
349 :
350 :
351 : int
352 76853 : MSTransportableControl::getActiveCount() {
353 76853 : return (int)myWaiting4Departure.size() + myRunningNumber - myWaitingForVehicleNumber;
354 : }
355 :
356 :
357 : int
358 897385 : MSTransportableControl::getMovingNumber() const {
359 897385 : return myMovementModel->getActiveNumber() + myAccessNumber;
360 : }
361 :
362 :
363 : int
364 4752 : MSTransportableControl::getRidingNumber() const {
365 4752 : return myRunningNumber - myWaitingUntilNumber - myWaitingForVehicleNumber - getMovingNumber();
366 : }
367 :
368 : int
369 9642 : MSTransportableControl::getDepartedNumber() const {
370 9642 : return myLoadedNumber - myWaitingForDepartureNumber - myDiscardedNumber;
371 : }
372 :
373 : void
374 4278 : MSTransportableControl::abortAnyWaitingForVehicle() {
375 4573 : for (const auto& it : myWaiting4Vehicle) {
376 295 : const MSEdge* edge = it.first;
377 899 : for (MSTransportable* const p : it.second) {
378 604 : edge->removeTransportable(p);
379 604 : MSStageDriving* stage = dynamic_cast<MSStageDriving*>(p->getCurrentStage());
380 604 : const std::string waitDescription = stage == nullptr ? "waiting" : stage->getWaitingDescription();
381 1208 : WRITE_WARNING(p->getObjectType() + " '" + p->getID() + "' aborted " + waitDescription + ".");
382 604 : if (myAbortWaitingTimeout >= 0) {
383 0 : p->setAbortWaiting(-1);
384 : }
385 604 : erase(p);
386 : }
387 : }
388 : myWaiting4Vehicle.clear();
389 4278 : myWaitingForVehicleNumber = 0;
390 4278 : }
391 :
392 : void
393 105 : MSTransportableControl::abortWaitingForVehicle(MSTransportable* t) {
394 105 : const MSEdge* edge = t->getEdge();
395 : auto it = myWaiting4Vehicle.find(edge);
396 105 : if (it != myWaiting4Vehicle.end()) {
397 105 : TransportableVector& waiting = it->second;
398 105 : auto it2 = std::find(waiting.begin(), waiting.end(), t);
399 105 : if (it2 != waiting.end()) {
400 105 : if (myAbortWaitingTimeout >= 0) {
401 16 : (*it2)->setAbortWaiting(-1);
402 : }
403 : waiting.erase(it2);
404 105 : myWaitingForVehicleNumber--;
405 : }
406 : }
407 105 : }
408 :
409 : void
410 41 : MSTransportableControl::abortWaiting(MSTransportable* t) {
411 82 : for (std::map<SUMOTime, TransportableVector>::iterator it = myWaiting4Departure.begin(); it != myWaiting4Departure.end(); ++it) {
412 41 : TransportableVector& ts = it->second;
413 41 : TransportableVector::iterator it2 = std::find(ts.begin(), ts.end(), t);
414 41 : if (it2 != ts.end()) {
415 : ts.erase(it2);
416 : }
417 : }
418 41 : for (std::map<SUMOTime, TransportableVector>::iterator it = myWaitingUntil.begin(); it != myWaitingUntil.end(); ++it) {
419 0 : TransportableVector& ts = it->second;
420 0 : TransportableVector::iterator it2 = std::find(ts.begin(), ts.end(), t);
421 0 : if (it2 != ts.end()) {
422 : ts.erase(it2);
423 : }
424 : }
425 41 : }
426 :
427 :
428 : MSTransportable*
429 284987 : MSTransportableControl::buildPerson(const SUMOVehicleParameter* pars, MSVehicleType* vtype, MSTransportable::MSTransportablePlan* plan,
430 : SumoRNG* rng) const {
431 284987 : const double speedFactor = vtype->computeChosenSpeedDeviation(rng);
432 284987 : return new MSPerson(pars, vtype, plan, speedFactor);
433 : }
434 :
435 :
436 : MSTransportable*
437 198898 : MSTransportableControl::buildContainer(const SUMOVehicleParameter* pars, MSVehicleType* vtype, MSTransportable::MSTransportablePlan* plan) const {
438 198898 : return new MSTransportable(pars, vtype, plan, false);
439 : }
440 :
441 :
442 : void
443 29 : MSTransportableControl::saveState(OutputDevice& out) {
444 29 : std::ostringstream oss;
445 174 : oss << myRunningNumber << " " << myLoadedNumber << " " << myEndedNumber << " " << myWaitingForDepartureNumber << " " << myArrivedNumber << " " << myDiscardedNumber;
446 116 : oss << " " << myJammedNumber << " " << myWaitingForVehicleNumber << " " << myWaitingUntilNumber << " " << myHaveNewWaiting;
447 58 : out.writeAttr(SUMO_ATTR_STATE, oss.str());
448 72 : for (const auto& it : myTransportables) {
449 43 : it.second->saveState(out);
450 : }
451 29 : }
452 :
453 :
454 : void
455 34 : MSTransportableControl::loadState(const std::string& state) {
456 34 : std::istringstream iss(state);
457 34 : iss >> myRunningNumber >> myLoadedNumber >> myEndedNumber >> myWaitingForDepartureNumber >> myArrivedNumber >> myDiscardedNumber;
458 34 : iss >> myJammedNumber >> myWaitingForVehicleNumber >> myWaitingUntilNumber >> myHaveNewWaiting;
459 34 : }
460 :
461 : void
462 8213 : MSTransportableControl::clearState() {
463 127021 : for (std::map<std::string, MSTransportable*>::iterator i = myTransportables.begin(); i != myTransportables.end(); ++i) {
464 118808 : delete (*i).second;
465 : }
466 : myTransportables.clear();
467 : myWaiting4Vehicle.clear();
468 : myWaiting4Departure.clear();
469 : myWaitingUntil.clear();
470 8213 : myLoadedNumber = 0;
471 8213 : myDiscardedNumber = 0;
472 8213 : myRunningNumber = 0;
473 8213 : myJammedNumber = 0;
474 8213 : myWaitingForDepartureNumber = 0;
475 8213 : myWaitingForVehicleNumber = 0;
476 8213 : myWaitingUntilNumber = 0;
477 8213 : myEndedNumber = 0;
478 8213 : myArrivedNumber = 0;
479 8213 : myHaveNewWaiting = false;
480 8213 : if (myMovementModel != myNonInteractingModel) {
481 5424 : myMovementModel->clearState();
482 : }
483 8213 : myNonInteractingModel->clearState();
484 8213 : }
485 :
486 : /****************************************************************************/
|