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