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.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 /****************************************************************************/
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 bool
98  for (const MSTransportable* t : myTransportables) {
99  MSStageDriving* const stage = dynamic_cast<MSStageDriving*>(t->getCurrentStage());
100  if (stage->canLeaveVehicle(t, myHolder, stop)) {
101  return true;
102  }
103  }
104  return false;
105 }
106 
107 
108 void
110  const MSStop& stop = myHolder.getNextStop();
111  for (auto it = myTransportables.begin(); it != myTransportables.end();) {
112  MSTransportable* t = *it;
113  if (t->getNumRemainingStages() > 1) {
114  MSStageDriving* const stage = dynamic_cast<MSStageDriving*>(t->getCurrentStage());
115  if (stage->canLeaveVehicle(t, myHolder, stop)) {
116  MSStageDriving* const stage2 = dynamic_cast<MSStageDriving*>(t->getNextStage(1));
117  if (stage2 && stage2->isWaitingFor(otherVeh)) {
118  it = myTransportables.erase(it);
119  // proceeding registers t as waiting on edge
121  MSTransportableControl& tc = (t->isPerson() ?
125  t->getEdge()->removeTransportable(t);
126  otherVeh->addTransportable(t);
127  stage2->setVehicle(otherVeh);
128  continue;
129  }
130  }
131  }
132  it++;
133  }
134 }
135 
136 
137 bool
139  if (joinVeh && t->getNumRemainingStages() > 1) {
140  MSStageDriving* const stage2 = dynamic_cast<MSStageDriving*>(t->getNextStage(1));
141  return stage2->isWaitingFor(joinVeh);
142  }
143  return false;
144 }
145 
146 
147 bool
148 MSDevice_Transportable::notifyMove(SUMOTrafficObject& /*tObject*/, double /*oldPos*/, double newPos, double newSpeed) {
149  SUMOVehicle& veh = myHolder;
150  const SUMOTime currentTime = MSNet::getInstance()->getCurrentTimeStep();
151  if (myStopped) {
152  if (!veh.isStopped()) {
153  const SUMOTime freeFlowTimeCorrection = MSGlobals::gUseMesoSim ? TIME2STEPS(newPos / newSpeed) : 0;
154  for (MSTransportable* const transportable : myTransportables) {
155  transportable->setDeparted(currentTime - freeFlowTimeCorrection);
156  }
157  myStopped = false;
158  }
159  } else {
160  if (veh.isStopped()) {
161  myStopped = true;
162  MSStop& stop = veh.getNextStop();
163  const MSVehicle* joinVeh = dynamic_cast<MSVehicle*>(MSNet::getInstance()->getVehicleControl().getVehicle(stop.pars.join));
164  const SUMOTime boardingDuration = veh.getVehicleType().getLoadingDuration(!myAmContainer);
165  for (std::vector<MSTransportable*>::iterator i = myTransportables.begin(); i != myTransportables.end();) {
166  MSTransportable* transportable = *i;
167  MSStageDriving* const stage = dynamic_cast<MSStageDriving*>(transportable->getCurrentStage());
168  if (stage->canLeaveVehicle(transportable, myHolder, stop) && !willTransferAtJoin(transportable, joinVeh)) {
170  MSDevice_Taxi* taxiDevice = static_cast<MSDevice_Taxi*>(myHolder.getDevice(typeid(MSDevice_Taxi)));
171  if (taxiDevice != nullptr && timeForNext == 0 && !MSGlobals::gUseMesoSim) {
172  // taxi passengers must leave at the end of the stop duration
173  timeForNext = stop.pars.started + stop.pars.duration;
174  }
175  if (timeForNext - DELTA_T > currentTime) {
176  // try deboarding again in the next step
177  myStopped = false;
178  break;
179  }
180  if (stage->getDestinationStop() != nullptr) {
181  stage->getDestinationStop()->addTransportable(transportable);
182  }
183 
184  SUMOTime arrivalTime = currentTime;
186  // no boarding / unboarding time in meso
187  arrivalTime += 1;
188  } else {
189  if (timeForNext > currentTime - DELTA_T) {
190  timeForNext += boardingDuration;
191  } else {
192  timeForNext = currentTime + boardingDuration;
193  }
194  }
195  //ensure that vehicle stops long enough for deboarding
196  stop.duration = MAX2(stop.duration, timeForNext - currentTime);
197 
198  i = myTransportables.erase(i); // erase first in case proceed throws an exception
199  if (taxiDevice != nullptr) {
200  taxiDevice->customerArrived(transportable);
201  }
202  if (!transportable->proceed(MSNet::getInstance(), arrivalTime)) {
203  if (myAmContainer) {
204  MSNet::getInstance()->getContainerControl().erase(transportable);
205  } else {
206  MSNet::getInstance()->getPersonControl().erase(transportable);
207  }
208  }
209  if (MSStopOut::active()) {
210  SUMOVehicle* vehicle = dynamic_cast<SUMOVehicle*>(&veh);
211  if (myAmContainer) {
213  } else {
215  }
216  }
217  continue;
218  }
219  ++i;
220  }
221  }
222  }
223  return true;
224 }
225 
226 
227 bool
230  const SUMOTime currentTime = MSNet::getInstance()->getCurrentTimeStep();
231  for (MSTransportable* const transportable : myTransportables) {
232  transportable->setDeparted(currentTime);
233  }
234  }
236  // to trigger vehicle leaving
237  notifyMove(veh, -1., -1., -1.);
238  }
239  return true;
240 }
241 
242 
243 bool
245  MSMoveReminder::Notification reason, const MSLane* /* enteredLane */) {
246  if (reason >= MSMoveReminder::NOTIFICATION_ARRIVED) {
247  for (std::vector<MSTransportable*>::iterator i = myTransportables.begin(); i != myTransportables.end();) {
249  MSTransportable* transportable = *i;
250  if (transportable->getDestination() != veh.getEdge()) {
251  WRITE_WARNING((myAmContainer ? "Teleporting container '" : "Teleporting person '") + transportable->getID() +
252  "' from vehicle destination edge '" + veh.getEdge()->getID() +
253  "' to intended destination edge '" + transportable->getDestination()->getID() + "' time=" + time2string(SIMSTEP));
255  }
256  if (!transportable->proceed(MSNet::getInstance(), MSNet::getInstance()->getCurrentTimeStep(), true)) {
257  tc.erase(transportable);
258  }
259  i = myTransportables.erase(i);
260  }
261  }
262  return true;
263 }
264 
265 
266 void
268  myTransportables.push_back(transportable);
269  if (MSStopOut::active()) {
270  if (myAmContainer) {
272  } else {
274  }
275  }
276  MSDevice_Taxi* taxiDevice = static_cast<MSDevice_Taxi*>(myHolder.getDevice(typeid(MSDevice_Taxi)));
277  if (taxiDevice != nullptr) {
278  taxiDevice->customerEntered(transportable);
279  }
280 }
281 
282 
283 void
285  auto it = std::find(myTransportables.begin(), myTransportables.end(), transportable);
286  if (it != myTransportables.end()) {
287  myTransportables.erase(it);
288  if (MSStopOut::active() && myHolder.isStopped()) {
289  if (myAmContainer) {
291  } else {
293  }
294  }
295  MSDevice_Taxi* taxiDevice = static_cast<MSDevice_Taxi*>(myHolder.getDevice(typeid(MSDevice_Taxi)));
296  if (taxiDevice != nullptr) {
297  taxiDevice->customerArrived(transportable);
298  }
299  }
300 }
301 
302 
303 void
306  out.writeAttr(SUMO_ATTR_ID, getID());
307  std::vector<std::string> internals;
308  internals.push_back(toString(myStopped));
309  out.writeAttr(SUMO_ATTR_STATE, toString(internals));
310  out.closeTag();
311 }
312 
313 
314 void
316  std::istringstream bis(attrs.getString(SUMO_ATTR_STATE));
317  bis >> myStopped;
318 }
319 
320 
321 std::string
322 MSDevice_Transportable::getParameter(const std::string& key) const {
323  if (key == "IDList") {
324  std::vector<std::string> ids;
325  for (const MSTransportable* t : myTransportables) {
326  ids.push_back(t->getID());
327  }
328  return toString(ids);
329  }
330  throw InvalidArgument("Parameter '" + key + "' is not supported for device of type '" + deviceName() + "'");
331 }
332 
333 
334 /****************************************************************************/
long long int SUMOTime
Definition: GUI.h:35
#define WRITE_WARNING(msg)
Definition: MsgHandler.h:295
SUMOTime DELTA_T
Definition: SUMOTime.cpp:38
std::string time2string(SUMOTime t, bool humanReadable)
convert SUMOTime to string (independently of global format setting)
Definition: SUMOTime.cpp:69
#define SIMSTEP
Definition: SUMOTime.h:61
#define TIME2STEPS(x)
Definition: SUMOTime.h:57
@ SUMO_TAG_DEVICE
@ SUMO_ATTR_ID
@ SUMO_ATTR_STATE
The state of a link.
T MAX2(T a, T b)
Definition: StdDefs.h:82
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
Definition: ToString.h:46
The base class for microscopic and mesoscopic vehicles.
Definition: MSBaseVehicle.h:55
virtual void addTransportable(MSTransportable *transportable)
Adds a person or container to this vehicle.
A device which collects info on the vehicle trip (mainly on departure and arrival)
Definition: MSDevice_Taxi.h:49
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.
static bool willTransferAtJoin(const MSTransportable *t, const MSBaseVehicle *joinVeh)
check if boardingDuration should be applied
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.
bool anyLeavingAtStop(const MSStop &stop) const
static MSDevice_Transportable * buildVehicleDevices(SUMOVehicle &v, std::vector< MSVehicleDevice * > &into, const bool isContainer)
Build devices for the given vehicle, if needed.
void transferAtSplitOrJoin(MSBaseVehicle *otherVeh)
transfers transportables that want to continue in the other train part (without boarding/loading dela...
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:1106
virtual void removeTransportable(MSTransportable *t) const
Definition: MSEdge.cpp:1133
static bool gUseMesoSim
Definition: MSGlobals.h:103
Representation of a lane in the micro simulation.
Definition: MSLane.h:84
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:182
virtual MSTransportableControl & getContainerControl()
Returns the container control.
Definition: MSNet.cpp:1182
MSVehicleControl & getVehicleControl()
Returns the vehicle control.
Definition: MSNet.h:378
SUMOTime getCurrentTimeStep() const
Returns the current simulation step.
Definition: MSNet.h:320
virtual MSTransportableControl & getPersonControl()
Returns the person control.
Definition: MSNet.cpp:1173
bool canLeaveVehicle(const MSTransportable *t, const SUMOVehicle &veh, const MSStop &stop)
checks whether the person may exit at the current vehicle position
bool isWaitingFor(const SUMOVehicle *vehicle) const
Whether the person waits for the given vehicle.
void setVehicle(SUMOVehicle *v)
MSStoppingPlace * getDestinationStop() const
returns the destination stop (if any)
Definition: MSStage.h:84
Definition: MSStop.h:44
SUMOTime timeToLoadNextContainer
The time at which the vehicle is able to load another container.
Definition: MSStop.h:83
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
const SUMOVehicleParameter::Stop pars
The stop parameter.
Definition: MSStop.h:65
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
void abortWaitingForVehicle(MSTransportable *t)
let the given transportable abort waiting for a vehicle (when removing stage via TraCI)
void registerTeleportWrongDest()
register a teleport to the final destination
virtual void erase(MSTransportable *transportable)
removes a single transportable
MSStage * getNextStage(int offset) const
Return the next (or previous) stage denoted by the offset.
int getNumRemainingStages() const
Return the number of remaining stages (including the current)
virtual bool proceed(MSNet *net, SUMOTime time, const bool vehicleArrived=false)
bool isPerson() const
Whether it is a person.
const MSEdge * getEdge() const
Returns the current edge.
MSStage * getCurrentStage() const
Return the current stage.
const MSEdge * getDestination() const
Returns the current destination.
SUMOVehicle * getVehicle(const std::string &id) const
Returns the vehicle with the given id.
Abstract in-vehicle device.
SUMOVehicle & myHolder
The vehicle that stores the device.
Representation of a vehicle in the micro simulation.
Definition: MSVehicle.h:77
SUMOTime getLoadingDuration(const bool isPerson) const
Get this vehicle type's loading 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:254
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, bool *isPresent=nullptr) const =0
Returns the string-value of the named (by its enum-value) attribute.
Representation of a vehicle, person, or container.
virtual MSDevice * getDevice(const std::type_info &type) const =0
Returns a device of the given type if it exists or nullptr if not.
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 MSStop & getNextStop()=0
SUMOTime started
the time at which this stop was reached
std::string join
the id of the vehicle (train portion) to which this vehicle shall be joined
SUMOTime duration
The stopping duration.