Line data Source code
1 : /****************************************************************************/
2 : // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
3 : // Copyright (C) 2001-2024 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 7699 : MSTransportableControl::MSTransportableControl(const bool isPerson):
49 7699 : myLoadedNumber(0),
50 7699 : myDiscardedNumber(0),
51 7699 : myRunningNumber(0),
52 7699 : myJammedNumber(0),
53 7699 : myWaitingForDepartureNumber(0),
54 7699 : myWaitingForVehicleNumber(0),
55 7699 : myWaitingUntilNumber(0),
56 7699 : myAccessNumber(0),
57 7699 : myEndedNumber(0),
58 7699 : myArrivedNumber(0),
59 7699 : myTeleportsAbortWait(0),
60 7699 : myTeleportsWrongDest(0),
61 7699 : myHaveNewWaiting(false) {
62 7699 : const OptionsCont& oc = OptionsCont::getOptions();
63 7699 : MSNet* const net = MSNet::getInstance();
64 7699 : myMovementModel = myNonInteractingModel = new MSPModel_NonInteracting(oc, net);
65 7699 : if (isPerson) {
66 6955 : const std::string& model = oc.getString("pedestrian.model");
67 6955 : if (model == "striping") {
68 5113 : 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 1842 : } else if (model != "nonInteracting") {
74 21 : delete myNonInteractingModel;
75 63 : throw ProcessError(TLF("Unknown pedestrian model '%'", model));
76 : }
77 : }
78 15356 : if (oc.isSet("vehroute-output")) {
79 1320 : myRouteInfos.routeOut = &OutputDevice::getDeviceByOption("vehroute-output");
80 : }
81 15356 : 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 15356 : if (oc.isSet("personinfo-output")) {
86 36 : OutputDevice::createDeviceByOption("personinfo-output", "tripinfos", "tripinfo_file.xsd");
87 : }
88 7678 : myAbortWaitingTimeout = string2time(oc.getString("time-to-teleport.ride"));
89 7678 : myMaxTransportableNumber = isPerson ? oc.getInt("max-num-persons") : -1;
90 7699 : }
91 :
92 :
93 13751 : MSTransportableControl::~MSTransportableControl() {
94 7658 : clearState();
95 7658 : if (myMovementModel != myNonInteractingModel) {
96 5104 : delete myMovementModel;
97 : }
98 7658 : delete myNonInteractingModel;
99 13751 : }
100 :
101 :
102 : bool
103 501792 : MSTransportableControl::add(MSTransportable* transportable) {
104 501792 : const SUMOVehicleParameter& param = transportable->getParameter();
105 501792 : if (myTransportables.find(param.id) == myTransportables.end()) {
106 501776 : myTransportables[param.id] = transportable;
107 501776 : const SUMOTime step = param.depart % DELTA_T == 0 ? param.depart : (param.depart / DELTA_T + 1) * DELTA_T;
108 501776 : myWaiting4Departure[step].push_back(transportable);
109 501776 : myLoadedNumber++;
110 501776 : 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 503789 : MSTransportableControl::get(const std::string& id) const {
137 : std::map<std::string, MSTransportable*>::const_iterator i = myTransportables.find(id);
138 503789 : if (i == myTransportables.end()) {
139 : return nullptr;
140 : }
141 497995 : return (*i).second;
142 : }
143 :
144 :
145 : void
146 364895 : MSTransportableControl::erase(MSTransportable* transportable) {
147 364895 : const OptionsCont& oc = OptionsCont::getOptions();
148 729790 : if (oc.isSet("personinfo-output")) {
149 360 : transportable->tripInfoOutput(OutputDevice::getDeviceByOption("personinfo-output"));
150 729430 : } else if (oc.isSet("tripinfo-output")) {
151 67500 : transportable->tripInfoOutput(OutputDevice::getDeviceByOption("tripinfo-output"));
152 661930 : } else if (oc.getBool("duration-log.statistics")) {
153 : // collecting statistics is a sideffect
154 21591 : OutputDevice_String dev;
155 21591 : transportable->tripInfoOutput(dev);
156 21591 : }
157 727068 : if (oc.isSet("vehroute-output") || oc.isSet("personroute-output")) {
158 2870 : if (transportable->hasArrived() || oc.getBool("vehroute-output.write-unfinished")) {
159 5364 : if (oc.getBool("vehroute-output.sorted")) {
160 122 : const SUMOTime departure = oc.getBool("vehroute-output.intended-depart") ? transportable->getParameter().depart : transportable->getDeparture();
161 122 : OutputDevice_String od(1);
162 122 : transportable->routeOutput(od, oc.getBool("vehroute-output.route-length"));
163 122 : MSDevice_Vehroutes::writeSortedOutput(&myRouteInfos,
164 122 : departure, transportable->getID(), od.getString());
165 122 : } else {
166 5120 : transportable->routeOutput(*myRouteInfos.routeOut, oc.getBool("vehroute-output.route-length"));
167 : }
168 : }
169 : }
170 : const std::map<std::string, MSTransportable*>::iterator i = myTransportables.find(transportable->getID());
171 364895 : if (i != myTransportables.end()) {
172 364895 : myRunningNumber--;
173 364895 : myEndedNumber++;
174 867691 : MSNet::getInstance()->informTransportableStateListener(transportable,
175 364895 : transportable->isPerson() ? MSNet::TransportableState::PERSON_ARRIVED : MSNet::TransportableState::CONTAINER_ARRIVED);
176 364895 : delete i->second;
177 : myTransportables.erase(i);
178 : }
179 364895 : }
180 :
181 :
182 : void
183 65591 : MSTransportableControl::setWaitEnd(const SUMOTime time, MSTransportable* transportable) {
184 65591 : const SUMOTime step = time % DELTA_T == 0 ? time : (time / DELTA_T + 1) * DELTA_T;
185 : // avoid double registration
186 65591 : const TransportableVector& transportables = myWaitingUntil[step];
187 65591 : if (std::find(transportables.begin(), transportables.end(), transportable) == transportables.end()) {
188 65591 : myWaitingUntil[step].push_back(transportable);
189 65591 : myWaitingUntilNumber++;
190 : }
191 65591 : }
192 :
193 :
194 : void
195 5848460 : MSTransportableControl::checkWaiting(MSNet* net, const SUMOTime time) {
196 5848460 : myHaveNewWaiting = false;
197 11989144 : while (myWaiting4Departure.find(time) != myWaiting4Departure.end()) {
198 292260 : TransportableVector& transportables = myWaiting4Departure[time];
199 : // we cannot use an iterator here because there might be additions to the vector while proceeding
200 743250 : for (auto it = transportables.begin(); it != transportables.end();) {
201 451130 : MSTransportable* t = *it;
202 451130 : if (myMaxTransportableNumber > 0 && myRunningNumber >= myMaxTransportableNumber) {
203 104 : TransportableVector& nextStep = myWaiting4Departure[time + DELTA_T];
204 104 : nextStep.insert(nextStep.begin(), transportables.begin(), transportables.end());
205 : transportables.clear();
206 : break;
207 : }
208 : it = transportables.erase(it);
209 451026 : myWaitingForDepartureNumber--;
210 451026 : const bool isPerson = t->isPerson();
211 451026 : t->setDeparted(time);
212 451026 : if (t->proceed(net, time)) {
213 450990 : myRunningNumber++;
214 642992 : MSNet::getInstance()->informTransportableStateListener(t,
215 : isPerson ? MSNet::TransportableState::PERSON_DEPARTED : MSNet::TransportableState::CONTAINER_DEPARTED);
216 450990 : const OptionsCont& oc = OptionsCont::getOptions();
217 901980 : if (oc.getBool("vehroute-output.sorted")) {
218 132 : const SUMOTime departure = oc.getBool("vehroute-output.intended-depart") ? t->getParameter().depart : time;
219 264 : if (oc.isSet("personroute-output")) {
220 24 : myRouteInfos.departureCounts[departure]++;
221 : } else {
222 108 : MSDevice_Vehroutes::registerTransportableDepart(departure);
223 : }
224 : }
225 : } else {
226 0 : erase(t);
227 : }
228 : }
229 : myWaiting4Departure.erase(time);
230 : }
231 5912462 : while (myWaitingUntil.find(time) != myWaitingUntil.end()) {
232 : // make a copy because 0-duration stops might modify the vector
233 64045 : const TransportableVector transportables = myWaitingUntil[time];
234 : myWaitingUntil.erase(time);
235 129108 : for (MSTransportable* t : transportables) {
236 65070 : myWaitingUntilNumber--;
237 65070 : if (!t->proceed(net, time)) {
238 18267 : erase(t);
239 : }
240 : }
241 64045 : }
242 5848417 : }
243 :
244 :
245 : void
246 42 : MSTransportableControl::forceDeparture() {
247 42 : myRunningNumber++;
248 42 : }
249 :
250 :
251 : void
252 73837 : MSTransportableControl::addWaiting(const MSEdge* const edge, MSTransportable* transportable) {
253 73837 : myWaiting4Vehicle[edge].push_back(transportable);
254 73837 : myWaitingForVehicleNumber++;
255 73837 : myHaveNewWaiting = true;
256 73837 : if (myAbortWaitingTimeout >= 0) {
257 16 : transportable->setAbortWaiting(myAbortWaitingTimeout);
258 : }
259 73837 : }
260 :
261 :
262 : bool
263 83 : MSTransportableControl::hasAnyWaiting(const MSEdge* edge, SUMOVehicle* vehicle) const {
264 : const auto wait = myWaiting4Vehicle.find(edge);
265 83 : if (wait != myWaiting4Vehicle.end()) {
266 44 : for (const MSTransportable* t : wait->second) {
267 : if (t->isWaitingFor(vehicle)
268 39 : && vehicle->allowsBoarding(t)
269 78 : && vehicle->isStoppedInRange(t->getEdgePos(), MSGlobals::gStopTolerance, true)) {
270 : return true;
271 : }
272 : }
273 : }
274 : return false;
275 : }
276 :
277 :
278 : bool
279 921626 : MSTransportableControl::loadAnyWaiting(const MSEdge* edge, SUMOVehicle* vehicle, SUMOTime& timeToLoadNext, SUMOTime& stopDuration, MSTransportable* const force) {
280 : bool ret = false;
281 : const auto wait = myWaiting4Vehicle.find(edge);
282 921626 : if (wait != myWaiting4Vehicle.end()) {
283 49663 : const SUMOTime currentTime = SIMSTEP;
284 49663 : TransportableVector& transportables = wait->second;
285 414166 : for (TransportableVector::iterator i = transportables.begin(); i != transportables.end();) {
286 364503 : MSTransportable* const t = *i;
287 674688 : if (t->isWaitingFor(vehicle) && (t == force ||
288 310185 : (vehicle->allowsBoarding(t)
289 122052 : && timeToLoadNext - DELTA_T <= currentTime
290 12159 : && vehicle->isStoppedInRange(t->getEdgePos(), MSGlobals::gStopTolerance)))) {
291 9409 : edge->removeTransportable(t);
292 9409 : vehicle->addTransportable(t);
293 9409 : if (myAbortWaitingTimeout >= 0) {
294 0 : t->setAbortWaiting(-1);
295 : }
296 9409 : if (timeToLoadNext >= 0) { // meso does not have loading times
297 14966 : const SUMOTime loadingDuration = (SUMOTime)((double)vehicle->getVehicleType().getLoadingDuration(t->isPerson()) * t->getVehicleType().getBoardingFactor());
298 : //update the time point at which the next transportable can be loaded on the vehicle
299 7483 : if (timeToLoadNext > currentTime - DELTA_T) {
300 4998 : timeToLoadNext += loadingDuration;
301 : } else {
302 2485 : timeToLoadNext = currentTime + loadingDuration;
303 : }
304 : }
305 :
306 9409 : static_cast<MSStageDriving*>(t->getCurrentStage())->setVehicle(vehicle);
307 9409 : if (t->getCurrentStage()->getOriginStop() != nullptr) {
308 4774 : t->getCurrentStage()->getOriginStop()->removeTransportable(*i);
309 : }
310 : i = transportables.erase(i);
311 9409 : myWaitingForVehicleNumber--;
312 : ret = true;
313 : } else {
314 : ++i;
315 : }
316 : }
317 49663 : if (transportables.empty()) {
318 : myWaiting4Vehicle.erase(wait);
319 : }
320 49663 : if (ret && timeToLoadNext >= 0) {
321 : //if the time a transportable needs to get loaded on the vehicle extends the duration of the stop of the vehicle extend
322 : //the duration by setting it to the loading duration of the transportable
323 4886 : stopDuration = MAX2(stopDuration, timeToLoadNext - currentTime);
324 : }
325 : }
326 921626 : return ret;
327 : }
328 :
329 :
330 : bool
331 12968662 : MSTransportableControl::hasTransportables() const {
332 12968662 : return !myTransportables.empty();
333 : }
334 :
335 :
336 : bool
337 1178290 : MSTransportableControl::hasNonWaiting() const {
338 1178290 : return !myWaiting4Departure.empty() || getMovingNumber() > 0 || myWaitingUntilNumber > 0 || myHaveNewWaiting;
339 : }
340 :
341 :
342 : int
343 35671 : MSTransportableControl::getActiveCount() {
344 35671 : return (int)myWaiting4Departure.size() + myRunningNumber - myWaitingForVehicleNumber;
345 : }
346 :
347 :
348 : int
349 888513 : MSTransportableControl::getMovingNumber() const {
350 888513 : return myMovementModel->getActiveNumber() + myAccessNumber;
351 : }
352 :
353 :
354 : int
355 4752 : MSTransportableControl::getRidingNumber() const {
356 4752 : return myRunningNumber - myWaitingUntilNumber - myWaitingForVehicleNumber - getMovingNumber();
357 : }
358 :
359 : int
360 4752 : MSTransportableControl::getDepartedNumber() const {
361 4752 : return myLoadedNumber - myWaitingForDepartureNumber - myDiscardedNumber;
362 : }
363 :
364 : void
365 3940 : MSTransportableControl::abortAnyWaitingForVehicle() {
366 4236 : for (const auto& it : myWaiting4Vehicle) {
367 296 : const MSEdge* edge = it.first;
368 901 : for (MSTransportable* const p : it.second) {
369 605 : edge->removeTransportable(p);
370 605 : MSStageDriving* stage = dynamic_cast<MSStageDriving*>(p->getCurrentStage());
371 605 : const std::string waitDescription = stage == nullptr ? "waiting" : stage->getWaitingDescription();
372 1210 : WRITE_WARNING(p->getObjectType() + " '" + p->getID() + "' aborted " + waitDescription + ".");
373 605 : if (myAbortWaitingTimeout >= 0) {
374 0 : p->setAbortWaiting(-1);
375 : }
376 605 : erase(p);
377 : }
378 : }
379 : myWaiting4Vehicle.clear();
380 3940 : myWaitingForVehicleNumber = 0;
381 3940 : }
382 :
383 : void
384 90 : MSTransportableControl::abortWaitingForVehicle(MSTransportable* t) {
385 90 : const MSEdge* edge = t->getEdge();
386 : auto it = myWaiting4Vehicle.find(edge);
387 90 : if (it != myWaiting4Vehicle.end()) {
388 90 : TransportableVector& waiting = it->second;
389 90 : auto it2 = std::find(waiting.begin(), waiting.end(), t);
390 90 : if (it2 != waiting.end()) {
391 90 : if (myAbortWaitingTimeout >= 0) {
392 16 : (*it2)->setAbortWaiting(-1);
393 : }
394 : waiting.erase(it2);
395 : }
396 : }
397 90 : }
398 :
399 : void
400 42 : MSTransportableControl::abortWaiting(MSTransportable* t) {
401 84 : for (std::map<SUMOTime, TransportableVector>::iterator it = myWaiting4Departure.begin(); it != myWaiting4Departure.end(); ++it) {
402 42 : TransportableVector& ts = it->second;
403 42 : TransportableVector::iterator it2 = std::find(ts.begin(), ts.end(), t);
404 42 : if (it2 != ts.end()) {
405 : ts.erase(it2);
406 : }
407 : }
408 42 : for (std::map<SUMOTime, TransportableVector>::iterator it = myWaitingUntil.begin(); it != myWaitingUntil.end(); ++it) {
409 0 : TransportableVector& ts = it->second;
410 0 : TransportableVector::iterator it2 = std::find(ts.begin(), ts.end(), t);
411 0 : if (it2 != ts.end()) {
412 : ts.erase(it2);
413 : }
414 : }
415 42 : }
416 :
417 :
418 : MSTransportable*
419 278298 : MSTransportableControl::buildPerson(const SUMOVehicleParameter* pars, MSVehicleType* vtype, MSTransportable::MSTransportablePlan* plan,
420 : SumoRNG* rng) const {
421 278298 : const double speedFactor = vtype->computeChosenSpeedDeviation(rng);
422 278298 : return new MSPerson(pars, vtype, plan, speedFactor);
423 : }
424 :
425 :
426 : MSTransportable*
427 195467 : MSTransportableControl::buildContainer(const SUMOVehicleParameter* pars, MSVehicleType* vtype, MSTransportable::MSTransportablePlan* plan) const {
428 195467 : return new MSTransportable(pars, vtype, plan, false);
429 : }
430 :
431 :
432 : void
433 29 : MSTransportableControl::saveState(OutputDevice& out) {
434 29 : std::ostringstream oss;
435 174 : oss << myRunningNumber << " " << myLoadedNumber << " " << myEndedNumber << " " << myWaitingForDepartureNumber << " " << myArrivedNumber << " " << myDiscardedNumber;
436 116 : oss << " " << myJammedNumber << " " << myWaitingForVehicleNumber << " " << myWaitingUntilNumber << " " << myHaveNewWaiting;
437 29 : out.writeAttr(SUMO_ATTR_STATE, oss.str());
438 72 : for (const auto& it : myTransportables) {
439 43 : it.second->saveState(out);
440 : }
441 29 : }
442 :
443 :
444 : void
445 34 : MSTransportableControl::loadState(const std::string& state) {
446 34 : std::istringstream iss(state);
447 34 : iss >> myRunningNumber >> myLoadedNumber >> myEndedNumber >> myWaitingForDepartureNumber >> myArrivedNumber >> myDiscardedNumber;
448 34 : iss >> myJammedNumber >> myWaitingForVehicleNumber >> myWaitingUntilNumber >> myHaveNewWaiting;
449 34 : }
450 :
451 : void
452 7683 : MSTransportableControl::clearState() {
453 144513 : for (std::map<std::string, MSTransportable*>::iterator i = myTransportables.begin(); i != myTransportables.end(); ++i) {
454 136830 : delete (*i).second;
455 : }
456 : myTransportables.clear();
457 : myWaiting4Vehicle.clear();
458 : myWaiting4Departure.clear();
459 : myWaitingUntil.clear();
460 7683 : myLoadedNumber = 0;
461 7683 : myDiscardedNumber = 0;
462 7683 : myRunningNumber = 0;
463 7683 : myJammedNumber = 0;
464 7683 : myWaitingForDepartureNumber = 0;
465 7683 : myWaitingForVehicleNumber = 0;
466 7683 : myWaitingUntilNumber = 0;
467 7683 : myEndedNumber = 0;
468 7683 : myArrivedNumber = 0;
469 7683 : myHaveNewWaiting = false;
470 7683 : if (myMovementModel != myNonInteractingModel) {
471 5129 : myMovementModel->clearState();
472 : }
473 7683 : myNonInteractingModel->clearState();
474 7683 : }
475 :
476 : /****************************************************************************/
|