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 5606 : MSTransportableControl::MSTransportableControl(const bool isPerson):
49 5606 : myLoadedNumber(0),
50 5606 : myDiscardedNumber(0),
51 5606 : myRunningNumber(0),
52 5606 : myJammedNumber(0),
53 5606 : myWaitingForDepartureNumber(0),
54 5606 : myWaitingForVehicleNumber(0),
55 5606 : myWaitingUntilNumber(0),
56 5606 : myAccessNumber(0),
57 5606 : myEndedNumber(0),
58 5606 : myArrivedNumber(0),
59 5606 : myTeleportsAbortWait(0),
60 5606 : myTeleportsWrongDest(0),
61 5606 : myHaveNewWaiting(false) {
62 5606 : const OptionsCont& oc = OptionsCont::getOptions();
63 5606 : MSNet* const net = MSNet::getInstance();
64 5606 : myMovementModel = myNonInteractingModel = new MSPModel_NonInteracting(oc, net);
65 5606 : if (isPerson) {
66 10050 : const std::string& model = oc.getString("pedestrian.model");
67 5025 : if (model == "striping") {
68 3246 : 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 1779 : } else if (model != "nonInteracting") {
74 14 : delete myNonInteractingModel;
75 56 : throw ProcessError(TLF("Unknown pedestrian model '%'", model));
76 : }
77 : }
78 11184 : if (oc.isSet("vehroute-output")) {
79 1321 : myRouteInfos.routeOut = &OutputDevice::getDeviceByOption("vehroute-output");
80 : }
81 11184 : if (oc.isSet("personroute-output")) {
82 24 : OutputDevice::createDeviceByOption("personroute-output", "routes", "routes_file.xsd");
83 24 : myRouteInfos.routeOut = &OutputDevice::getDeviceByOption("personroute-output");
84 : }
85 11184 : if (oc.isSet("personinfo-output")) {
86 54 : OutputDevice::createDeviceByOption("personinfo-output", "tripinfos", "tripinfo_file.xsd");
87 : }
88 5592 : myAbortWaitingTimeout = string2time(oc.getString("time-to-teleport.ride"));
89 5606 : }
90 :
91 :
92 9651 : MSTransportableControl::~MSTransportableControl() {
93 5573 : clearState();
94 5573 : if (myMovementModel != myNonInteractingModel) {
95 3238 : delete myMovementModel;
96 : }
97 5573 : delete myNonInteractingModel;
98 9651 : }
99 :
100 :
101 : bool
102 457026 : MSTransportableControl::add(MSTransportable* transportable) {
103 457026 : const SUMOVehicleParameter& param = transportable->getParameter();
104 457026 : if (myTransportables.find(param.id) == myTransportables.end()) {
105 457010 : myTransportables[param.id] = transportable;
106 457010 : const SUMOTime step = param.depart % DELTA_T == 0 ? param.depart : (param.depart / DELTA_T + 1) * DELTA_T;
107 457010 : myWaiting4Departure[step].push_back(transportable);
108 457010 : myLoadedNumber++;
109 457010 : myWaitingForDepartureNumber++;
110 : return true;
111 : }
112 : return false;
113 : }
114 :
115 :
116 : void
117 69 : MSTransportableControl::fixLoadCount(const MSTransportable* transportable) {
118 69 : myLoadedNumber--;
119 69 : if (transportable->hasDeparted()) {
120 60 : const SUMOVehicleParameter& param = transportable->getParameter();
121 60 : const SUMOTime step = param.depart % DELTA_T == 0 ? param.depart : (param.depart / DELTA_T + 1) * DELTA_T;
122 60 : TransportableVector& waiting = myWaiting4Departure[step];
123 60 : auto it = std::find(waiting.begin(), waiting.end(), transportable);
124 60 : if (it != waiting.end()) {
125 : waiting.erase(it);
126 60 : if (waiting.size() == 0) {
127 : myWaiting4Departure.erase(step);
128 : }
129 : }
130 : }
131 69 : }
132 :
133 :
134 : MSTransportable*
135 566439 : MSTransportableControl::get(const std::string& id) const {
136 : std::map<std::string, MSTransportable*>::const_iterator i = myTransportables.find(id);
137 566439 : if (i == myTransportables.end()) {
138 : return nullptr;
139 : }
140 565818 : return (*i).second;
141 : }
142 :
143 :
144 : void
145 437596 : MSTransportableControl::erase(MSTransportable* transportable) {
146 437596 : const OptionsCont& oc = OptionsCont::getOptions();
147 875192 : if (oc.isSet("personinfo-output")) {
148 360 : transportable->tripInfoOutput(OutputDevice::getDeviceByOption("personinfo-output"));
149 874832 : } else if (oc.isSet("tripinfo-output")) {
150 63820 : transportable->tripInfoOutput(OutputDevice::getDeviceByOption("tripinfo-output"));
151 811012 : } else if (oc.getBool("duration-log.statistics")) {
152 : // collecting statistics is a sideffect
153 15642 : OutputDevice_String dev;
154 15642 : transportable->tripInfoOutput(dev);
155 15642 : }
156 872498 : if (oc.isSet("vehroute-output") || oc.isSet("personroute-output")) {
157 2930 : if (transportable->hasArrived() || oc.getBool("vehroute-output.write-unfinished")) {
158 5356 : if (oc.getBool("vehroute-output.sorted")) {
159 122 : const SUMOTime departure = oc.getBool("vehroute-output.intended-depart") ? transportable->getParameter().depart : transportable->getDeparture();
160 122 : OutputDevice_String od(1);
161 122 : transportable->routeOutput(od, oc.getBool("vehroute-output.route-length"));
162 122 : MSDevice_Vehroutes::writeSortedOutput(&myRouteInfos,
163 122 : departure, transportable->getID(), od.getString());
164 122 : } else {
165 5112 : transportable->routeOutput(*myRouteInfos.routeOut, oc.getBool("vehroute-output.route-length"));
166 : }
167 : }
168 : }
169 : const std::map<std::string, MSTransportable*>::iterator i = myTransportables.find(transportable->getID());
170 437596 : if (i != myTransportables.end()) {
171 437596 : myRunningNumber--;
172 437596 : myEndedNumber++;
173 1013878 : MSNet::getInstance()->informTransportableStateListener(transportable,
174 437596 : transportable->isPerson() ? MSNet::TransportableState::PERSON_ARRIVED : MSNet::TransportableState::CONTAINER_ARRIVED);
175 437596 : delete i->second;
176 : myTransportables.erase(i);
177 : }
178 437596 : }
179 :
180 :
181 : void
182 9476 : MSTransportableControl::setWaitEnd(const SUMOTime time, MSTransportable* transportable) {
183 9476 : const SUMOTime step = time % DELTA_T == 0 ? time : (time / DELTA_T + 1) * DELTA_T;
184 : // avoid double registration
185 9476 : const TransportableVector& transportables = myWaitingUntil[step];
186 9476 : if (std::find(transportables.begin(), transportables.end(), transportable) == transportables.end()) {
187 9476 : myWaitingUntil[step].push_back(transportable);
188 9476 : myWaitingUntilNumber++;
189 : }
190 9476 : }
191 :
192 :
193 : void
194 2455449 : MSTransportableControl::checkWaiting(MSNet* net, const SUMOTime time) {
195 2455449 : myHaveNewWaiting = false;
196 5179508 : while (myWaiting4Departure.find(time) != myWaiting4Departure.end()) {
197 268639 : TransportableVector& transportables = myWaiting4Departure[time];
198 : // we cannot use an iterator here because there might be additions to the vector while proceeding
199 708788 : for (auto it = transportables.begin(); it != transportables.end();) {
200 440178 : MSTransportable* t = *it;
201 : it = transportables.erase(it);
202 440178 : myWaitingForDepartureNumber--;
203 440178 : const bool isPerson = t->isPerson();
204 440178 : if (t->proceed(net, time)) {
205 440149 : myRunningNumber++;
206 578863 : MSNet::getInstance()->informTransportableStateListener(t,
207 : isPerson ? MSNet::TransportableState::PERSON_DEPARTED : MSNet::TransportableState::CONTAINER_DEPARTED);
208 440149 : const OptionsCont& oc = OptionsCont::getOptions();
209 880298 : if (oc.getBool("vehroute-output.sorted")) {
210 132 : const SUMOTime departure = oc.getBool("vehroute-output.intended-depart") ? t->getParameter().depart : time;
211 264 : if (oc.isSet("personroute-output")) {
212 24 : myRouteInfos.departureCounts[departure]++;
213 : } else {
214 108 : MSDevice_Vehroutes::registerTransportableDepart(departure);
215 : }
216 : }
217 : } else {
218 0 : erase(t);
219 : }
220 : }
221 : myWaiting4Departure.erase(time);
222 : }
223 2463679 : while (myWaitingUntil.find(time) != myWaitingUntil.end()) {
224 : // make a copy because 0-duration stops might modify the vector
225 8266 : const TransportableVector transportables = myWaitingUntil[time];
226 : myWaitingUntil.erase(time);
227 17452 : for (MSTransportable* t : transportables) {
228 9193 : myWaitingUntilNumber--;
229 9193 : if (!t->proceed(net, time)) {
230 7708 : erase(t);
231 : }
232 : }
233 : }
234 2455413 : }
235 :
236 :
237 : void
238 53 : MSTransportableControl::forceDeparture() {
239 53 : myRunningNumber++;
240 53 : }
241 :
242 :
243 : void
244 39969 : MSTransportableControl::addWaiting(const MSEdge* const edge, MSTransportable* transportable) {
245 39969 : myWaiting4Vehicle[edge].push_back(transportable);
246 39969 : myWaitingForVehicleNumber++;
247 39969 : myHaveNewWaiting = true;
248 39969 : if (myAbortWaitingTimeout >= 0) {
249 16 : transportable->setAbortWaiting(myAbortWaitingTimeout);
250 : }
251 39969 : }
252 :
253 :
254 : bool
255 83 : MSTransportableControl::hasAnyWaiting(const MSEdge* edge, SUMOVehicle* vehicle) const {
256 : const auto wait = myWaiting4Vehicle.find(edge);
257 83 : if (wait != myWaiting4Vehicle.end()) {
258 44 : for (const MSTransportable* t : wait->second) {
259 : if (t->isWaitingFor(vehicle)
260 39 : && vehicle->allowsBoarding(t)
261 78 : && vehicle->isStoppedInRange(t->getEdgePos(), MSGlobals::gStopTolerance, true)) {
262 : return true;
263 : }
264 : }
265 : }
266 : return false;
267 : }
268 :
269 :
270 : bool
271 1229736 : MSTransportableControl::loadAnyWaiting(const MSEdge* edge, SUMOVehicle* vehicle, SUMOTime& timeToLoadNext, SUMOTime& stopDuration) {
272 : bool ret = false;
273 : const auto wait = myWaiting4Vehicle.find(edge);
274 1229736 : if (wait != myWaiting4Vehicle.end()) {
275 35778 : const SUMOTime currentTime = SIMSTEP;
276 35778 : TransportableVector& transportables = wait->second;
277 345191 : for (TransportableVector::iterator i = transportables.begin(); i != transportables.end();) {
278 309413 : MSTransportable* const t = *i;
279 : if (t->isWaitingFor(vehicle)
280 254298 : && vehicle->allowsBoarding(t)
281 127216 : && timeToLoadNext - DELTA_T <= currentTime
282 323644 : && vehicle->isStoppedInRange(t->getEdgePos(), MSGlobals::gStopTolerance)) {
283 10218 : edge->removeTransportable(t);
284 10218 : vehicle->addTransportable(t);
285 10218 : if (myAbortWaitingTimeout >= 0) {
286 0 : t->setAbortWaiting(-1);
287 : }
288 10218 : if (timeToLoadNext >= 0) { // meso does not have loading times
289 8576 : const SUMOTime loadingDuration = vehicle->getVehicleType().getLoadingDuration(t->isPerson());
290 : //update the time point at which the next transportable can be loaded on the vehicle
291 8576 : if (timeToLoadNext > currentTime - DELTA_T) {
292 5900 : timeToLoadNext += loadingDuration;
293 : } else {
294 2676 : timeToLoadNext = currentTime + loadingDuration;
295 : }
296 : }
297 :
298 10218 : static_cast<MSStageDriving*>(t->getCurrentStage())->setVehicle(vehicle);
299 10218 : if (t->getCurrentStage()->getOriginStop() != nullptr) {
300 6072 : t->getCurrentStage()->getOriginStop()->removeTransportable(*i);
301 : }
302 : i = transportables.erase(i);
303 10218 : myWaitingForVehicleNumber--;
304 : ret = true;
305 : } else {
306 : ++i;
307 : }
308 : }
309 35778 : if (transportables.empty()) {
310 : myWaiting4Vehicle.erase(wait);
311 : }
312 35778 : if (ret && timeToLoadNext >= 0) {
313 : //if the time a transportable needs to get loaded on the vehicle extends the duration of the stop of the vehicle extend
314 : //the duration by setting it to the loading duration of the transportable
315 5411 : stopDuration = MAX2(stopDuration, timeToLoadNext - currentTime);
316 : }
317 : }
318 1229736 : return ret;
319 : }
320 :
321 :
322 : bool
323 4013814 : MSTransportableControl::hasTransportables() const {
324 4013814 : return !myTransportables.empty();
325 : }
326 :
327 :
328 : bool
329 1444988 : MSTransportableControl::hasNonWaiting() const {
330 1444988 : return !myWaiting4Departure.empty() || getMovingNumber() > 0 || myWaitingUntilNumber > 0 || myHaveNewWaiting;
331 : }
332 :
333 :
334 : int
335 47616 : MSTransportableControl::getActiveCount() {
336 47616 : return (int)myWaiting4Departure.size() + myRunningNumber - myWaitingForVehicleNumber;
337 : }
338 :
339 :
340 : int
341 876083 : MSTransportableControl::getMovingNumber() const {
342 876083 : return myMovementModel->getActiveNumber() + myAccessNumber;
343 : }
344 :
345 :
346 : int
347 4752 : MSTransportableControl::getRidingNumber() const {
348 4752 : return myRunningNumber - myWaitingUntilNumber - myWaitingForVehicleNumber - getMovingNumber();
349 : }
350 :
351 : int
352 4752 : MSTransportableControl::getDepartedNumber() const {
353 4752 : return myLoadedNumber - myWaitingForDepartureNumber - myDiscardedNumber;
354 : }
355 :
356 : void
357 4246 : MSTransportableControl::abortAnyWaitingForVehicle() {
358 4575 : for (const auto& it : myWaiting4Vehicle) {
359 329 : const MSEdge* edge = it.first;
360 29662 : for (MSTransportable* const p : it.second) {
361 29333 : edge->removeTransportable(p);
362 29333 : MSStageDriving* stage = dynamic_cast<MSStageDriving*>(p->getCurrentStage());
363 29333 : const std::string waitDescription = stage == nullptr ? "waiting" : stage->getWaitingDescription();
364 87999 : WRITE_WARNING(p->getObjectType() + " '" + p->getID() + "' aborted " + waitDescription + ".");
365 29333 : if (myAbortWaitingTimeout >= 0) {
366 0 : p->setAbortWaiting(-1);
367 : }
368 29333 : erase(p);
369 : }
370 : }
371 : myWaiting4Vehicle.clear();
372 4246 : myWaitingForVehicleNumber = 0;
373 4246 : }
374 :
375 : void
376 147 : MSTransportableControl::abortWaitingForVehicle(MSTransportable* t) {
377 147 : const MSEdge* edge = t->getEdge();
378 : auto it = myWaiting4Vehicle.find(edge);
379 147 : if (it != myWaiting4Vehicle.end()) {
380 147 : TransportableVector& waiting = it->second;
381 147 : auto it2 = std::find(waiting.begin(), waiting.end(), t);
382 147 : if (it2 != waiting.end()) {
383 147 : if (myAbortWaitingTimeout >= 0) {
384 16 : (*it2)->setAbortWaiting(-1);
385 : }
386 : waiting.erase(it2);
387 : }
388 : }
389 147 : }
390 :
391 : void
392 53 : MSTransportableControl::abortWaiting(MSTransportable* t) {
393 106 : for (std::map<SUMOTime, TransportableVector>::iterator it = myWaiting4Departure.begin(); it != myWaiting4Departure.end(); ++it) {
394 53 : TransportableVector& ts = it->second;
395 53 : TransportableVector::iterator it2 = std::find(ts.begin(), ts.end(), t);
396 53 : if (it2 != ts.end()) {
397 : ts.erase(it2);
398 : }
399 : }
400 53 : for (std::map<SUMOTime, TransportableVector>::iterator it = myWaitingUntil.begin(); it != myWaitingUntil.end(); ++it) {
401 0 : TransportableVector& ts = it->second;
402 0 : TransportableVector::iterator it2 = std::find(ts.begin(), ts.end(), t);
403 0 : if (it2 != ts.end()) {
404 : ts.erase(it2);
405 : }
406 : }
407 53 : }
408 :
409 :
410 : MSTransportable*
411 292923 : MSTransportableControl::buildPerson(const SUMOVehicleParameter* pars, MSVehicleType* vtype, MSTransportable::MSTransportablePlan* plan,
412 : SumoRNG* rng) const {
413 292923 : const double speedFactor = vtype->computeChosenSpeedDeviation(rng);
414 292923 : return new MSPerson(pars, vtype, plan, speedFactor);
415 : }
416 :
417 :
418 : MSTransportable*
419 138357 : MSTransportableControl::buildContainer(const SUMOVehicleParameter* pars, MSVehicleType* vtype, MSTransportable::MSTransportablePlan* plan) const {
420 138357 : return new MSTransportable(pars, vtype, plan, false);
421 : }
422 :
423 :
424 : void
425 42 : MSTransportableControl::saveState(OutputDevice& out) {
426 42 : std::ostringstream oss;
427 252 : oss << myRunningNumber << " " << myLoadedNumber << " " << myEndedNumber << " " << myWaitingForDepartureNumber << " " << myArrivedNumber << " " << myDiscardedNumber;
428 168 : oss << " " << myJammedNumber << " " << myWaitingForVehicleNumber << " " << myWaitingUntilNumber << " " << myHaveNewWaiting;
429 42 : out.writeAttr(SUMO_ATTR_STATE, oss.str());
430 105 : for (const auto& it : myTransportables) {
431 63 : it.second->saveState(out);
432 : }
433 42 : }
434 :
435 :
436 : void
437 48 : MSTransportableControl::loadState(const std::string& state) {
438 48 : std::istringstream iss(state);
439 48 : iss >> myRunningNumber >> myLoadedNumber >> myEndedNumber >> myWaitingForDepartureNumber >> myArrivedNumber >> myDiscardedNumber;
440 48 : iss >> myJammedNumber >> myWaitingForVehicleNumber >> myWaitingUntilNumber >> myHaveNewWaiting;
441 48 : }
442 :
443 : void
444 5603 : MSTransportableControl::clearState() {
445 24967 : for (std::map<std::string, MSTransportable*>::iterator i = myTransportables.begin(); i != myTransportables.end(); ++i) {
446 19364 : delete (*i).second;
447 : }
448 : myTransportables.clear();
449 : myWaiting4Vehicle.clear();
450 : myWaiting4Departure.clear();
451 : myWaitingUntil.clear();
452 5603 : myLoadedNumber = 0;
453 5603 : myDiscardedNumber = 0;
454 5603 : myRunningNumber = 0;
455 5603 : myJammedNumber = 0;
456 5603 : myWaitingForDepartureNumber = 0;
457 5603 : myWaitingForVehicleNumber = 0;
458 5603 : myWaitingUntilNumber = 0;
459 5603 : myEndedNumber = 0;
460 5603 : myArrivedNumber = 0;
461 5603 : myHaveNewWaiting = false;
462 5603 : if (myMovementModel != myNonInteractingModel) {
463 3268 : myMovementModel->clearState();
464 : }
465 5603 : myNonInteractingModel->clearState();
466 5603 : }
467 :
468 : /****************************************************************************/
|