Eclipse SUMO - Simulation of Urban MObility
MSDevice_Transportable.cpp
Go to the documentation of this file.
1 /****************************************************************************/
2 // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.org/sumo
3 // Copyright (C) 2001-2022 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 /****************************************************************************/
23 // A device which is used to keep track of persons and containers riding with a vehicle
24 /****************************************************************************/
25 #include <config.h>
26 
29 #include <microsim/MSNet.h>
30 #include <microsim/MSEdge.h>
31 #include <microsim/MSStop.h>
36 #include "MSDevice_Transportable.h"
37 #include "MSDevice_Taxi.h"
38 
39 
40 // ===========================================================================
41 // method definitions
42 // ===========================================================================
43 // ---------------------------------------------------------------------------
44 // static initialisation methods
45 // ---------------------------------------------------------------------------
47 MSDevice_Transportable::buildVehicleDevices(SUMOVehicle& v, std::vector<MSVehicleDevice*>& into, const bool isContainer) {
48  MSDevice_Transportable* device = new MSDevice_Transportable(v, isContainer ? "container_" + v.getID() : "person_" + v.getID(), isContainer);
49  into.push_back(device);
50  return device;
51 }
52 
53 
54 // ---------------------------------------------------------------------------
55 // MSDevice_Transportable-methods
56 // ---------------------------------------------------------------------------
57 MSDevice_Transportable::MSDevice_Transportable(SUMOVehicle& holder, const std::string& id, const bool isContainer) :
58  MSVehicleDevice(holder, id),
59  myAmContainer(isContainer),
60  myTransportables(),
61  myStopped(holder.isStopped())
62 { }
63 
64 
66  // flush any unfortunate riders still remaining
67  for (auto it = myTransportables.begin(); it != myTransportables.end();) {
68  MSTransportable* transportable = *it;
69  WRITE_WARNING((myAmContainer ? "Removing container '" : "Removing person '") + transportable->getID() +
70  "' at removal of vehicle '" + myHolder.getID() + "'");
71  MSStageDriving* const stage = dynamic_cast<MSStageDriving*>(transportable->getCurrentStage());
72  if (stage != nullptr) {
73  stage->setVehicle(nullptr);
74  }
75  if (myAmContainer) {
76  MSNet::getInstance()->getContainerControl().erase(transportable);
77  } else {
78  MSNet::getInstance()->getPersonControl().erase(transportable);
79  }
80  it = myTransportables.erase(it);
81  }
82 }
83 
84 void
86  const double /* frontOnLane */,
87  const double /* timeOnLane */,
88  const double /* meanSpeedFrontOnLane */,
89  const double /* meanSpeedVehicleOnLane */,
90  const double travelledDistanceFrontOnLane,
91  const double /* travelledDistanceVehicleOnLane */,
92  const double /* meanLengthOnLane */) {
93  notifyMove(const_cast<SUMOTrafficObject&>(veh), -1, travelledDistanceFrontOnLane, veh.getEdge()->getVehicleMaxSpeed(&veh));
94 }
95 
96 
97 bool
98 MSDevice_Transportable::notifyMove(SUMOTrafficObject& /*tObject*/, double /*oldPos*/, double newPos, double newSpeed) {
99  SUMOVehicle& veh = myHolder;
100  const SUMOTime currentTime = MSNet::getInstance()->getCurrentTimeStep();
101  if (myStopped) {
102  if (!veh.isStopped()) {
103  const SUMOTime freeFlowTimeCorrection = MSGlobals::gUseMesoSim ? TIME2STEPS(newPos / newSpeed) : 0;
104  for (MSTransportable* const transportable : myTransportables) {
105  transportable->setDeparted(currentTime - freeFlowTimeCorrection);
106  }
107  myStopped = false;
108  }
109  } else {
110  if (veh.isStopped()) {
111  myStopped = true;
112  MSStop& stop = veh.getNextStop();
113  const SUMOTime boardingDuration = myAmContainer ? veh.getVehicleType().getLoadingDuration() : veh.getVehicleType().getBoardingDuration();
114  for (std::vector<MSTransportable*>::iterator i = myTransportables.begin(); i != myTransportables.end();) {
115  MSTransportable* transportable = *i;
116  MSStageDriving* const stage = dynamic_cast<MSStageDriving*>(transportable->getCurrentStage());
117  if (stage->canLeaveVehicle(transportable, myHolder)) {
118  if (stop.timeToBoardNextPerson - DELTA_T > currentTime) {
119  // try deboarding again in the next step
120  myStopped = false;
121  break;
122  }
123  if (stage->getDestinationStop() != nullptr) {
124  stage->getDestinationStop()->addTransportable(transportable);
125  }
126 
127  SUMOTime arrivalTime = currentTime;
129  arrivalTime += 1;
130  } else {
131  // no boarding / unboarding time in meso
132  if (stop.timeToBoardNextPerson > currentTime - DELTA_T) {
133  stop.timeToBoardNextPerson += boardingDuration;
134  } else {
135  stop.timeToBoardNextPerson = currentTime + boardingDuration;
136  }
137  }
138  //ensure that vehicle stops long enough for deboarding
139  stop.duration = MAX2(stop.duration, stop.timeToBoardNextPerson - currentTime);
140 
141  i = myTransportables.erase(i); // erase first in case proceed throws an exception
142  MSDevice_Taxi* taxiDevice = static_cast<MSDevice_Taxi*>(myHolder.getDevice(typeid(MSDevice_Taxi)));
143  if (taxiDevice != nullptr) {
144  taxiDevice->customerArrived(transportable);
145  }
146  if (!transportable->proceed(MSNet::getInstance(), arrivalTime)) {
147  if (myAmContainer) {
148  MSNet::getInstance()->getContainerControl().erase(transportable);
149  } else {
150  MSNet::getInstance()->getPersonControl().erase(transportable);
151  }
152  }
153  if (MSStopOut::active()) {
154  SUMOVehicle* vehicle = dynamic_cast<SUMOVehicle*>(&veh);
155  if (myAmContainer) {
157  } else {
159  }
160  }
161  continue;
162  }
163  ++i;
164  }
165  }
166  }
167  return true;
168 }
169 
170 
171 bool
174  const SUMOTime currentTime = MSNet::getInstance()->getCurrentTimeStep();
175  for (MSTransportable* const transportable : myTransportables) {
176  transportable->setDeparted(currentTime);
177  }
178  }
180  // to trigger vehicle leaving
181  notifyMove(veh, -1., -1., -1.);
182  }
183  return true;
184 }
185 
186 
187 bool
189  MSMoveReminder::Notification reason, const MSLane* /* enteredLane */) {
190  if (reason >= MSMoveReminder::NOTIFICATION_ARRIVED) {
191  for (std::vector<MSTransportable*>::iterator i = myTransportables.begin(); i != myTransportables.end();) {
192  MSTransportable* transportable = *i;
193  if (transportable->getDestination() != veh.getEdge()) {
194  WRITE_WARNING((myAmContainer ? "Teleporting container '" : "Teleporting person '") + transportable->getID() +
195  "' from vehicle destination edge '" + veh.getEdge()->getID() +
196  "' to intended destination edge '" + transportable->getDestination()->getID() + "' time=" + time2string(SIMSTEP));
197  }
198  if (!transportable->proceed(MSNet::getInstance(), MSNet::getInstance()->getCurrentTimeStep(), true)) {
199  if (myAmContainer) {
200  MSNet::getInstance()->getContainerControl().erase(transportable);
201  } else {
202  MSNet::getInstance()->getPersonControl().erase(transportable);
203  }
204  }
205  i = myTransportables.erase(i);
206  }
207  }
208  return true;
209 }
210 
211 
212 void
214  myTransportables.push_back(transportable);
215  if (MSStopOut::active()) {
216  if (myAmContainer) {
218  } else {
220  }
221  }
222  MSDevice_Taxi* taxiDevice = static_cast<MSDevice_Taxi*>(myHolder.getDevice(typeid(MSDevice_Taxi)));
223  if (taxiDevice != nullptr) {
224  taxiDevice->customerEntered(transportable);
225  }
226 }
227 
228 
229 void
231  auto it = std::find(myTransportables.begin(), myTransportables.end(), transportable);
232  if (it != myTransportables.end()) {
233  myTransportables.erase(it);
234  if (MSStopOut::active() && myHolder.isStopped()) {
235  if (myAmContainer) {
237  } else {
239  }
240  }
241  MSDevice_Taxi* taxiDevice = static_cast<MSDevice_Taxi*>(myHolder.getDevice(typeid(MSDevice_Taxi)));
242  if (taxiDevice != nullptr) {
243  taxiDevice->customerArrived(transportable);
244  }
245  }
246 }
247 
248 
249 void
252  out.writeAttr(SUMO_ATTR_ID, getID());
253  std::vector<std::string> internals;
254  internals.push_back(toString(myStopped));
255  out.writeAttr(SUMO_ATTR_STATE, toString(internals));
256  out.closeTag();
257 }
258 
259 
260 void
262  std::istringstream bis(attrs.getString(SUMO_ATTR_STATE));
263  bis >> myStopped;
264 }
265 
266 
267 std::string
268 MSDevice_Transportable::getParameter(const std::string& key) const {
269  if (key == "IDList") {
270  std::vector<std::string> ids;
271  for (const MSTransportable* t : myTransportables) {
272  ids.push_back(t->getID());
273  }
274  return toString(ids);
275  }
276  throw InvalidArgument("Parameter '" + key + "' is not supported for device of type '" + deviceName() + "'");
277 }
278 
279 
280 /****************************************************************************/
#define WRITE_WARNING(msg)
Definition: MsgHandler.h:280
SUMOTime DELTA_T
Definition: SUMOTime.cpp:37
std::string time2string(SUMOTime t)
convert SUMOTime to string
Definition: SUMOTime.cpp:68
#define SIMSTEP
Definition: SUMOTime.h:59
#define TIME2STEPS(x)
Definition: SUMOTime.h:55
long long int SUMOTime
Definition: SUMOTime.h:32
@ SUMO_TAG_DEVICE
@ SUMO_ATTR_ID
@ SUMO_ATTR_STATE
The state of a link.
T MAX2(T a, T b)
Definition: StdDefs.h:80
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
Definition: ToString.h:46
A device which collects info on the vehicle trip (mainly on departure and arrival)
Definition: MSDevice_Taxi.h:48
void customerArrived(const MSTransportable *person)
called by MSDevice_Transportable upon unloading a person
void customerEntered(const MSTransportable *t)
called by MSDevice_Transportable upon loading a person
void saveState(OutputDevice &out) const
Saves the state of the device.
bool notifyMove(SUMOTrafficObject &veh, double oldPos, double newPos, double newSpeed)
Checks whether the vehicle is at a stop and transportable action is needed.
std::string getParameter(const std::string &key) const
try to retrieve the given parameter from this device. Throw exception for unsupported key
bool notifyLeave(SUMOTrafficObject &veh, double lastPos, MSMoveReminder::Notification reason, const MSLane *enteredLane=0)
Passengers leaving on arrival.
static MSDevice_Transportable * buildVehicleDevices(SUMOVehicle &v, std::vector< MSVehicleDevice * > &into, const bool isContainer)
Build devices for the given vehicle, if needed.
bool notifyEnter(SUMOTrafficObject &veh, MSMoveReminder::Notification reason, const MSLane *enteredLane=0)
Adds passengers on vehicle insertion.
MSDevice_Transportable(SUMOVehicle &holder, const std::string &id, const bool isContainer)
Constructor.
std::vector< MSTransportable * > myTransportables
The passengers of the vehicle.
void notifyMoveInternal(const SUMOTrafficObject &veh, const double frontOnLane, const double timeOnLane, const double meanSpeedFrontOnLane, const double meanSpeedVehicleOnLane, const double travelledDistanceFrontOnLane, const double travelledDistanceVehicleOnLane, const double meanLengthOnLane)
Internal notification about the vehicle moves, see MSMoveReminder::notifyMoveInternal()
void addTransportable(MSTransportable *transportable)
Add a passenger.
const bool myAmContainer
Whether it is a container device.
const std::string deviceName() const
return the name for this type of device
void loadState(const SUMOSAXAttributes &attrs)
Loads the state of the device from the given description.
void removeTransportable(MSTransportable *transportable)
Remove a passenger (TraCI)
double getVehicleMaxSpeed(const SUMOTrafficObject *const veh) const
Returns the maximum speed the vehicle may use on this edge.
Definition: MSEdge.cpp:1002
static bool gUseMesoSim
Definition: MSGlobals.h:94
Representation of a lane in the micro simulation.
Definition: MSLane.h:82
Notification
Definition of a vehicle state.
@ NOTIFICATION_ARRIVED
The vehicle arrived at its destination (is deleted)
@ NOTIFICATION_DEPARTED
The vehicle has departed (was inserted into the network)
static MSNet * getInstance()
Returns the pointer to the unique instance of MSNet (singleton).
Definition: MSNet.cpp:174
virtual MSTransportableControl & getContainerControl()
Returns the container control.
Definition: MSNet.cpp:1068
SUMOTime getCurrentTimeStep() const
Returns the current simulation step.
Definition: MSNet.h:318
virtual MSTransportableControl & getPersonControl()
Returns the person control.
Definition: MSNet.cpp:1059
void setVehicle(SUMOVehicle *v)
bool canLeaveVehicle(const MSTransportable *t, const SUMOVehicle &veh)
checks whether the person may exit at the current vehicle position
MSStoppingPlace * getDestinationStop() const
returns the destination stop (if any)
Definition: MSStage.h:80
Definition: MSStop.h:44
SUMOTime timeToBoardNextPerson
The time at which the vehicle is able to board another person.
Definition: MSStop.h:81
SUMOTime duration
The stopping duration.
Definition: MSStop.h:67
void loadedContainers(const SUMOVehicle *veh, int n)
Definition: MSStopOut.cpp:89
static MSStopOut * getInstance()
Definition: MSStopOut.h:60
static bool active()
Definition: MSStopOut.h:54
void unloadedPersons(const SUMOVehicle *veh, int n)
Definition: MSStopOut.cpp:84
void unloadedContainers(const SUMOVehicle *veh, int n)
Definition: MSStopOut.cpp:97
void loadedPersons(const SUMOVehicle *veh, int n)
Definition: MSStopOut.cpp:76
bool addTransportable(const MSTransportable *p)
adds a transportable to this stop
virtual void erase(MSTransportable *transportable)
removes a single transportable
virtual bool proceed(MSNet *net, SUMOTime time, const bool vehicleArrived=false)
MSStage * getCurrentStage() const
Return the current stage.
const MSEdge * getDestination() const
Returns the current destination.
Abstract in-vehicle device.
SUMOVehicle & myHolder
The vehicle that stores the device.
SUMOTime getLoadingDuration() const
Get this vehicle type's loading duration.
SUMOTime getBoardingDuration() const
Get this vehicle type's boarding duration.
const std::string & getID() const
Returns the id.
Definition: Named.h:74
Static storage of an output device and its base (abstract) implementation.
Definition: OutputDevice.h:61
OutputDevice & openTag(const std::string &xmlElement)
Opens an XML tag.
OutputDevice & writeAttr(const SumoXMLAttr attr, const T &val)
writes a named attribute
Definition: OutputDevice.h:248
bool closeTag(const std::string &comment="")
Closes the most recently opened tag and optionally adds a comment.
Encapsulated SAX-Attributes.
virtual std::string getString(int id) const =0
Returns the string-value of the named (by its enum-value) attribute.
Representation of a vehicle, person, or container.
virtual bool isStopped() const =0
Returns whether the object is at a stop.
virtual const MSVehicleType & getVehicleType() const =0
Returns the object's "vehicle" type.
virtual const MSEdge * getEdge() const =0
Returns the edge the object is currently at.
Representation of a vehicle.
Definition: SUMOVehicle.h:60
virtual MSVehicleDevice * getDevice(const std::type_info &type) const =0
Returns a device of the given type if it exists or 0.
virtual MSStop & getNextStop()=0