1 /****************************************************************************/
2 // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.org/sumo
3 // Copyright (C) 2001-2019 German Aerospace Center (DLR) and others.
4 // This program and the accompanying materials
5 // are made available under the terms of the Eclipse Public License v2.0
6 // which accompanies this distribution, and is available at
7 // http://www.eclipse.org/legal/epl-v20.html
8 // SPDX-License-Identifier: EPL-2.0
9 /****************************************************************************/
10 /// @file    MSTransportableControl.cpp
11 /// @author  Daniel Krajzewicz
12 /// @author  Jakob Erdmann
13 /// @author  Sascha Krieg
14 /// @author  Michael Behrisch
15 /// @date    Mon, 9 Jul 2001
16 /// @version $Id$
17 ///
18 // Stores all persons in the net and handles their waiting for cars.
19 /****************************************************************************/
20 
21 
22 // ===========================================================================
23 // included modules
24 // ===========================================================================
25 #include <config.h>
26 
27 #include <vector>
28 #include <algorithm>
29 #include "MSNet.h"
30 #include "MSEdge.h"
31 #include <microsim/pedestrians/MSPerson.h>
32 #include "MSContainer.h"
33 #include "MSVehicle.h"
34 #include "MSTransportableControl.h"
35 #include <utils/iodevices/OutputDevice.h>
36 #include <utils/iodevices/OutputDevice_String.h>
37 #include <utils/options/OptionsCont.h>
38 
39 
40 // ===========================================================================
41 // method definitions
42 // ===========================================================================
MSTransportableControl()43 MSTransportableControl::MSTransportableControl():
44     myLoadedNumber(0),
45     myRunningNumber(0),
46     myJammedNumber(0),
47     myWaitingForVehicleNumber(0),
48     myHaveNewWaiting(false) {
49 }
50 
51 
~MSTransportableControl()52 MSTransportableControl::~MSTransportableControl() {
53     for (std::map<std::string, MSTransportable*>::iterator i = myTransportables.begin(); i != myTransportables.end(); ++i) {
54         delete (*i).second;
55     }
56     myTransportables.clear();
57     myWaiting4Vehicle.clear();
58 }
59 
60 
61 bool
add(MSTransportable * transportable)62 MSTransportableControl::add(MSTransportable* transportable) {
63     const SUMOVehicleParameter& param = transportable->getParameter();
64     if (myTransportables.find(param.id) == myTransportables.end()) {
65         myTransportables[param.id] = transportable;
66         const SUMOTime step = param.depart % DELTA_T == 0 ? param.depart : (param.depart / DELTA_T + 1) * DELTA_T;
67         myWaiting4Departure[step].push_back(transportable);
68         myLoadedNumber++;
69         return true;
70     }
71     return false;
72 }
73 
74 
75 MSTransportable*
get(const std::string & id) const76 MSTransportableControl::get(const std::string& id) const {
77     std::map<std::string, MSTransportable*>::const_iterator i = myTransportables.find(id);
78     if (i == myTransportables.end()) {
79         return nullptr;
80     }
81     return (*i).second;
82 }
83 
84 
85 void
erase(MSTransportable * transportable)86 MSTransportableControl::erase(MSTransportable* transportable) {
87     if (OptionsCont::getOptions().isSet("tripinfo-output")) {
88         transportable->tripInfoOutput(OutputDevice::getDeviceByOption("tripinfo-output"));
89     } else if (OptionsCont::getOptions().getBool("duration-log.statistics")) {
90         // collecting statistics is a sideffect
91         OutputDevice_String dev;
92         transportable->tripInfoOutput(dev);
93     }
94     if (OptionsCont::getOptions().isSet("vehroute-output")) {
95         transportable->routeOutput(OutputDevice::getDeviceByOption("vehroute-output"), OptionsCont::getOptions().getBool("vehroute-output.route-length"));
96     }
97     const std::map<std::string, MSTransportable*>::iterator i = myTransportables.find(transportable->getID());
98     if (i != myTransportables.end()) {
99         myRunningNumber--;
100         delete i->second;
101         myTransportables.erase(i);
102     }
103 }
104 
105 
106 void
setWaitEnd(const SUMOTime time,MSTransportable * transportable)107 MSTransportableControl::setWaitEnd(const SUMOTime time, MSTransportable* transportable) {
108     const SUMOTime step = time % DELTA_T == 0 ? time : (time / DELTA_T + 1) * DELTA_T;
109     // avoid double registration
110     const TransportableVector& transportables = myWaiting4Departure[step];
111     if (std::find(transportables.begin(), transportables.end(), transportable) == transportables.end()) {
112         myWaitingUntil[step].push_back(transportable);
113     }
114 }
115 
116 
117 void
checkWaiting(MSNet * net,const SUMOTime time)118 MSTransportableControl::checkWaiting(MSNet* net, const SUMOTime time) {
119     myHaveNewWaiting = false;
120     while (myWaiting4Departure.find(time) != myWaiting4Departure.end()) {
121         const TransportableVector& transportables = myWaiting4Departure[time];
122         // we cannot use an iterator here because there might be additions to the vector while proceeding
123         for (int i = 0; i < (int)transportables.size(); ++i) {
124             if (transportables[i]->proceed(net, time)) {
125                 myRunningNumber++;
126             } else {
127                 erase(transportables[i]);
128             }
129         }
130         myWaiting4Departure.erase(time);
131     }
132     while (myWaitingUntil.find(time) != myWaitingUntil.end()) {
133         const TransportableVector& transportables = myWaitingUntil[time];
134         // we cannot use an iterator here because there might be additions to the vector while proceeding
135         for (int i = 0; i < (int)transportables.size(); ++i) {
136             if (!transportables[i]->proceed(net, time)) {
137                 erase(transportables[i]);
138             }
139         }
140         myWaitingUntil.erase(time);
141     }
142 }
143 
144 
145 void
addWaiting(const MSEdge * const edge,MSTransportable * transportable)146 MSTransportableControl::addWaiting(const MSEdge* const edge, MSTransportable* transportable) {
147     myWaiting4Vehicle[edge].push_back(transportable);
148     myWaitingForVehicleNumber++;
149     myHaveNewWaiting = true;
150 }
151 
152 
153 bool
boardAnyWaiting(MSEdge * edge,SUMOVehicle * vehicle,const SUMOVehicleParameter::Stop & stop,SUMOTime & timeToBoardNextPerson,SUMOTime & stopDuration)154 MSTransportableControl::boardAnyWaiting(MSEdge* edge, SUMOVehicle* vehicle, const SUMOVehicleParameter::Stop& stop, SUMOTime& timeToBoardNextPerson, SUMOTime& stopDuration) {
155     bool ret = false;
156     if (myWaiting4Vehicle.find(edge) != myWaiting4Vehicle.end()) {
157         TransportableVector& wait = myWaiting4Vehicle[edge];
158         SUMOTime currentTime =  MSNet::getInstance()->getCurrentTimeStep();
159         for (TransportableVector::iterator i = wait.begin(); i != wait.end();) {
160             if ((*i)->isWaitingFor(vehicle)
161                     && vehicle->getVehicleType().getPersonCapacity() > vehicle->getPersonNumber()
162                     && timeToBoardNextPerson <= currentTime
163                     && stop.startPos <= (*i)->getEdgePos()
164                     && (*i)->getEdgePos() <= stop.endPos) {
165                 edge->removePerson(*i);
166                 vehicle->addPerson(*i);
167                 //if the time a person needs to enter the vehicle extends the duration of the stop of the vehicle extend
168                 //the duration by setting it to the boarding duration of the person
169                 const SUMOTime boardingDuration = vehicle->getVehicleType().getBoardingDuration();
170                 if (boardingDuration >= stopDuration) {
171                     stopDuration = boardingDuration;
172                 }
173                 //update the time point at which the next person can board the vehicle
174                 if (timeToBoardNextPerson > currentTime - DELTA_T) {
175                     timeToBoardNextPerson += boardingDuration;
176                 } else {
177                     timeToBoardNextPerson = currentTime + boardingDuration;
178                 }
179 
180                 static_cast<MSTransportable::Stage_Driving*>((*i)->getCurrentStage())->setVehicle(vehicle);
181                 i = wait.erase(i);
182                 myWaitingForVehicleNumber--;
183                 ret = true;
184             } else {
185                 ++i;
186             }
187         }
188         if (wait.size() == 0) {
189             myWaiting4Vehicle.erase(myWaiting4Vehicle.find(edge));
190         }
191     }
192     return ret;
193 }
194 
195 
196 bool
loadAnyWaiting(MSEdge * edge,SUMOVehicle * vehicle,const SUMOVehicleParameter::Stop & stop,SUMOTime & timeToLoadNextContainer,SUMOTime & stopDuration)197 MSTransportableControl::loadAnyWaiting(MSEdge* edge, SUMOVehicle* vehicle, const SUMOVehicleParameter::Stop& stop, SUMOTime& timeToLoadNextContainer, SUMOTime& stopDuration) {
198     bool ret = false;
199     if (myWaiting4Vehicle.find(edge) != myWaiting4Vehicle.end()) {
200         TransportableVector& waitContainers = myWaiting4Vehicle[edge];
201         for (TransportableVector::iterator i = waitContainers.begin(); i != waitContainers.end();) {
202             SUMOTime currentTime = MSNet::getInstance()->getCurrentTimeStep();
203             if ((*i)->isWaitingFor(vehicle)
204                     && vehicle->getVehicleType().getContainerCapacity() > vehicle->getContainerNumber()
205                     && timeToLoadNextContainer <= currentTime
206                     && stop.startPos <= (*i)->getEdgePos()
207                     && (*i)->getEdgePos() <= stop.endPos) {
208                 edge->removeContainer(*i);
209                 vehicle->addContainer(*i);
210                 //if the time a container needs to get loaded on the vehicle extends the duration of the stop of the vehicle extend
211                 //the duration by setting it to the loading duration of the container
212                 const SUMOTime loadingDuration = vehicle->getVehicleType().getLoadingDuration();
213                 if (loadingDuration >= stopDuration) {
214                     stopDuration = loadingDuration;
215                 }
216                 //update the time point at which the next container can be loaded on the vehicle
217                 timeToLoadNextContainer = currentTime + loadingDuration;
218 
219                 static_cast<MSContainer::MSContainerStage_Driving*>((*i)->getCurrentStage())->setVehicle(vehicle);
220                 i = waitContainers.erase(i);
221                 myWaitingForVehicleNumber--;
222                 ret = true;
223             } else {
224                 ++i;
225             }
226         }
227         if (waitContainers.size() == 0) {
228             myWaiting4Vehicle.erase(myWaiting4Vehicle.find(edge));
229         }
230     }
231     return ret;
232 }
233 
234 
235 bool
hasTransportables() const236 MSTransportableControl::hasTransportables() const {
237     return !myTransportables.empty();
238 }
239 
240 
241 bool
hasNonWaiting() const242 MSTransportableControl::hasNonWaiting() const {
243     return !myWaiting4Departure.empty() || myWaitingForVehicleNumber < myRunningNumber || myHaveNewWaiting;
244 }
245 
246 
247 int
getActiveCount()248 MSTransportableControl::getActiveCount() {
249     return (int)myWaiting4Departure.size() + myRunningNumber - myWaitingForVehicleNumber;
250 }
251 
252 
253 void
abortWaitingForVehicle()254 MSTransportableControl::abortWaitingForVehicle() {
255     for (std::map<const MSEdge*, TransportableVector>::const_iterator i = myWaiting4Vehicle.begin(); i != myWaiting4Vehicle.end(); ++i) {
256         const MSEdge* edge = (*i).first;
257         const TransportableVector& pv = (*i).second;
258         for (TransportableVector::const_iterator j = pv.begin(); j != pv.end(); ++j) {
259             MSTransportable* p = (*j);
260             p->setDeparted(MSNet::getInstance()->getCurrentTimeStep());
261             std::string transportableType;
262             if (dynamic_cast<MSPerson*>(p) != nullptr) {
263                 edge->removePerson(p);
264                 transportableType = "Person";
265             } else {
266                 transportableType = "Container";
267                 edge->removeContainer(p);
268             }
269             MSTransportable::Stage_Driving* stage = dynamic_cast<MSTransportable::Stage_Driving*>(p->getCurrentStage());
270             const std::string waitDescription = stage == nullptr ? "waiting" : stage->getWaitingDescription();
271             WRITE_WARNING(transportableType + " '" + p->getID() + "' aborted " + waitDescription + ".");
272             erase(p);
273         }
274     }
275 }
276 
277 
278 void
abortWaiting(MSTransportable * t)279 MSTransportableControl::abortWaiting(MSTransportable* t) {
280     for (std::map<SUMOTime, TransportableVector>::iterator it = myWaiting4Departure.begin(); it != myWaiting4Departure.end(); ++it) {
281         TransportableVector& ts = it->second;
282         TransportableVector::iterator it2 = std::find(ts.begin(), ts.end(), t);
283         if (it2 != ts.end()) {
284             ts.erase(it2);
285         }
286     }
287     for (std::map<SUMOTime, TransportableVector>::iterator it = myWaiting4Departure.begin(); it != myWaiting4Departure.end(); ++it) {
288         TransportableVector& ts = it->second;
289         TransportableVector::iterator it2 = std::find(ts.begin(), ts.end(), t);
290         if (it2 != ts.end()) {
291             ts.erase(it2);
292         }
293     }
294 }
295 
296 
297 MSTransportable*
buildPerson(const SUMOVehicleParameter * pars,MSVehicleType * vtype,MSTransportable::MSTransportablePlan * plan,std::mt19937 * rng) const298 MSTransportableControl::buildPerson(const SUMOVehicleParameter* pars, MSVehicleType* vtype, MSTransportable::MSTransportablePlan* plan,
299                                     std::mt19937* rng) const {
300     const double speedFactor = vtype->computeChosenSpeedDeviation(rng);
301     return new MSPerson(pars, vtype, plan, speedFactor);
302 }
303 
304 
305 MSTransportable*
buildContainer(const SUMOVehicleParameter * pars,MSVehicleType * vtype,MSTransportable::MSTransportablePlan * plan) const306 MSTransportableControl::buildContainer(const SUMOVehicleParameter* pars, MSVehicleType* vtype, MSTransportable::MSTransportablePlan* plan) const {
307     return new MSContainer(pars, vtype, plan);
308 }
309 
310 
311 /****************************************************************************/
312