Eclipse SUMO - Simulation of Urban MObility
Loading...
Searching...
No Matches
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-2026 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>
37#include "MSDevice_Taxi.h"
38
39
40// ===========================================================================
41// method definitions
42// ===========================================================================
43// ---------------------------------------------------------------------------
44// static initialisation methods
45// ---------------------------------------------------------------------------
47MSDevice_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// ---------------------------------------------------------------------------
57MSDevice_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 myOriginalType(&holder.getVehicleType()),
63 myLoadedType(nullptr) {
64 const std::string key = "device." + deviceName() + ".loadedType";
65 const std::string loadedTypeID = holder.getStringParam(key);
66 if (loadedTypeID != "") {
68 if (myLoadedType == nullptr) {
69 throw InvalidArgument(TLF("Vehicle type '%' in parameter '%' of vehicle '%' is not known.", loadedTypeID, key, holder.getID()));
70 }
71 }
72}
73
74
76 // flush any unfortunate riders still remaining
77 for (auto it = myTransportables.begin(); it != myTransportables.end();) {
78 MSTransportable* transportable = *it;
79 WRITE_WARNING((myAmContainer ? "Removing container '" : "Removing person '") + transportable->getID() +
80 "' at removal of vehicle '" + myHolder.getID() + "'");
81 MSStageDriving* const stage = dynamic_cast<MSStageDriving*>(transportable->getCurrentStage());
82 if (stage != nullptr) {
83 stage->setVehicle(nullptr);
84 }
85 if (myAmContainer) {
87 } else {
88 MSNet::getInstance()->getPersonControl().erase(transportable);
89 }
90 it = myTransportables.erase(it);
91 }
92}
93
94void
96 const double /* frontOnLane */,
97 const double /* timeOnLane */,
98 const double /* meanSpeedFrontOnLane */,
99 const double /* meanSpeedVehicleOnLane */,
100 const double travelledDistanceFrontOnLane,
101 const double /* travelledDistanceVehicleOnLane */,
102 const double /* meanLengthOnLane */) {
103 notifyMove(const_cast<SUMOTrafficObject&>(veh), -1, travelledDistanceFrontOnLane, veh.getEdge()->getVehicleMaxSpeed(&veh));
104}
105
106bool
108 for (const MSTransportable* t : myTransportables) {
109 MSStageDriving* const stage = dynamic_cast<MSStageDriving*>(t->getCurrentStage());
110 if (stage->canLeaveVehicle(t, myHolder, stop)) {
111 return true;
112 }
113 }
114 return false;
115}
116
117
118void
120 const MSStop& stop = myHolder.getNextStop();
121 for (auto it = myTransportables.begin(); it != myTransportables.end();) {
122 MSTransportable* t = *it;
123 if (t->getNumRemainingStages() > 1) {
124 MSStageDriving* const stage = dynamic_cast<MSStageDriving*>(t->getCurrentStage());
125 if (stage->canLeaveVehicle(t, myHolder, stop)) {
126 MSStageDriving* const stage2 = dynamic_cast<MSStageDriving*>(t->getNextStage(1));
127 if (stage2 && stage2->isWaitingFor(otherVeh)) {
128 auto locker = myHolder.getScopeLock();
129 it = myTransportables.erase(it);
130 // proceeding registers t as waiting on edge
132 MSTransportableControl& tc = (t->isPerson() ?
137 otherVeh->addTransportable(t);
138 stage2->setVehicle(otherVeh);
139 continue;
140 }
141 }
142 }
143 it++;
144 }
145}
146
147
148bool
150 if (joinVeh && t->getNumRemainingStages() > 1) {
151 MSStageDriving* const stage2 = dynamic_cast<MSStageDriving*>(t->getNextStage(1));
152 return stage2->isWaitingFor(joinVeh);
153 }
154 return false;
155}
156
157
158bool
159MSDevice_Transportable::notifyMove(SUMOTrafficObject& /*tObject*/, double /*oldPos*/, double newPos, double newSpeed) {
160 SUMOVehicle& veh = myHolder;
161 const SUMOTime currentTime = MSNet::getInstance()->getCurrentTimeStep();
162 if (myStopped) {
163 if (!veh.isStopped()) {
164 const SUMOTime freeFlowTimeCorrection = MSGlobals::gUseMesoSim ? TIME2STEPS(newPos / newSpeed) : 0;
165 for (MSTransportable* const transportable : myTransportables) {
166 transportable->setDeparted(currentTime - freeFlowTimeCorrection);
167 }
168 myStopped = false;
169 }
170 } else {
171 if (veh.isStopped()) {
172 myStopped = true;
173 MSStop& stop = veh.getNextStopMutable();
174 const MSVehicle* joinVeh = dynamic_cast<MSVehicle*>(MSNet::getInstance()->getVehicleControl().getVehicle(stop.pars.join));
175 const SUMOTime boardingDuration = veh.getVehicleType().getLoadingDuration(!myAmContainer);
176 int numUnloaded = 0;
177 for (std::vector<MSTransportable*>::iterator i = myTransportables.begin(); i != myTransportables.end();) {
178 MSTransportable* transportable = *i;
179 MSStageDriving* const stage = dynamic_cast<MSStageDriving*>(transportable->getCurrentStage());
180 if (stage->canLeaveVehicle(transportable, myHolder, stop) && !willTransferAtJoin(transportable, joinVeh)) {
182 MSDevice_Taxi* taxiDevice = static_cast<MSDevice_Taxi*>(myHolder.getDevice(typeid(MSDevice_Taxi)));
183 if (taxiDevice != nullptr && timeForNext == 0 && !MSGlobals::gUseMesoSim) {
184 // taxi passengers must leave at the end of the stop duration
185 timeForNext = stop.pars.started + stop.pars.duration;
186 }
187 if (timeForNext - DELTA_T > currentTime) {
188 // try deboarding again in the next step
189 myStopped = false;
190 break;
191 }
192 if (stage->getDestinationStop() != nullptr) {
193 stage->getDestinationStop()->addTransportable(transportable);
194 }
195
196 SUMOTime arrivalTime = currentTime;
198 // no boarding / unboarding time in meso
199 arrivalTime += 1;
200 } else {
201 const SUMOTime boardingTime = (SUMOTime)((double)boardingDuration * transportable->getVehicleType().getBoardingFactor());
202 if (timeForNext > currentTime - DELTA_T) {
203 timeForNext += boardingTime;
204 } else {
205 timeForNext = currentTime + boardingTime;
206 }
207 }
208 //ensure that vehicle stops long enough for deboarding
209 stop.duration = MAX2(stop.duration, timeForNext - currentTime);
210
211 veh.removeTransportableMass(transportable);
212 auto locker = myHolder.getScopeLock();
213 i = myTransportables.erase(i); // erase first in case proceed throws an exception
214 numUnloaded++;
215 if (taxiDevice != nullptr) {
216 taxiDevice->customerArrived(transportable);
217 }
218 if (!transportable->proceed(MSNet::getInstance(), arrivalTime)) {
219 if (myAmContainer) {
220 MSNet::getInstance()->getContainerControl().erase(transportable);
221 } else {
222 MSNet::getInstance()->getPersonControl().erase(transportable);
223 }
224 }
225 if (MSStopOut::active()) {
226 SUMOVehicle* vehicle = dynamic_cast<SUMOVehicle*>(&veh);
227 if (myAmContainer) {
229 } else {
231 }
232 }
233 continue;
234 }
235 ++i;
236 }
237 if (numUnloaded != 0) {
239 }
240 }
241 }
242 return true;
243}
244
245
246bool
249 const SUMOTime currentTime = MSNet::getInstance()->getCurrentTimeStep();
250 for (MSTransportable* const transportable : myTransportables) {
251 transportable->setDeparted(currentTime);
252 }
253 }
255 // to trigger vehicle leaving
256 notifyMove(veh, -1., -1., -1.);
257 }
258 return true;
259}
260
261
262bool
264 MSMoveReminder::Notification reason, const MSLane* /* enteredLane */) {
266 auto locker = myHolder.getScopeLock();
267 for (std::vector<MSTransportable*>::iterator i = myTransportables.begin(); i != myTransportables.end();) {
269 MSTransportable* transportable = *i;
270 if (transportable->getDestination() != veh.getEdge()) {
271 WRITE_WARNINGF("Teleporting % '%' from vehicle destination edge '%' to intended destination edge '%' time=%",
272 myAmContainer ? "container" : "person", transportable->getID(), veh.getEdge()->getID(),
273 transportable->getDestination()->getID(), time2string(SIMSTEP));
275 }
276 if (!transportable->proceed(MSNet::getInstance(), MSNet::getInstance()->getCurrentTimeStep(), true)) {
277 tc.erase(transportable);
278 }
279 i = myTransportables.erase(i);
280 }
281 }
282 return true;
283}
284
285
286void
288 auto locker = myHolder.getScopeLock();
289 if (myTransportables.empty()) {
291 }
292 myTransportables.push_back(transportable);
293 if (MSStopOut::active()) {
294 if (myAmContainer) {
296 } else {
298 }
299 }
300 MSDevice_Taxi* taxiDevice = static_cast<MSDevice_Taxi*>(myHolder.getDevice(typeid(MSDevice_Taxi)));
301 if (taxiDevice != nullptr) {
302 taxiDevice->customerEntered(transportable);
303 }
305}
306
307
308void
310 auto it = std::find(myTransportables.begin(), myTransportables.end(), transportable);
311 if (it != myTransportables.end()) {
312 auto locker = myHolder.getScopeLock();
313 myTransportables.erase(it);
315 if (myAmContainer) {
317 } else {
319 }
320 }
321 MSDevice_Taxi* taxiDevice = static_cast<MSDevice_Taxi*>(myHolder.getDevice(typeid(MSDevice_Taxi)));
322 if (taxiDevice != nullptr) {
323 taxiDevice->customerArrived(transportable);
324 }
326 }
327}
328
329
330void
332 if (myLoadedType != nullptr) {
334 if (perAttached > 0) {
335 MSBaseVehicle& veh = dynamic_cast<MSBaseVehicle&>(myHolder);
337 const double numAttached = ceil(myTransportables.size() / perAttached);
338 if (numAttached > 0.) {
339 MSVehicleType* stype = &veh.getSingularType();
342 stype->setLength(myOriginalType->getLength() + numAttached * myLoadedType->getLength());
343 stype->setMass(myOriginalType->getMass() + numAttached * myLoadedType->getMass());
344 SUMOVTypeParameter& sparam = const_cast<SUMOVTypeParameter&>(stype->getParameter());
348 } else {
350 }
351 if (oldVC != myHolder.getVClass()) {
352 veh.reroute(SIMSTEP, "device." + deviceName() + ".loadedType", veh.getRouterTT());
353 }
354 }
355 }
356}
357
358
359void
363 std::vector<std::string> internals;
364 internals.push_back(toString(myStopped));
365 out.writeAttr(SUMO_ATTR_STATE, toString(internals));
366 out.closeTag();
367}
368
369
370void
372 std::istringstream bis(attrs.getString(SUMO_ATTR_STATE));
373 bis >> myStopped;
374}
375
376
377std::string
378MSDevice_Transportable::getParameter(const std::string& key) const {
379 if (key == "IDList") {
380 std::vector<std::string> ids;
381 for (const MSTransportable* t : myTransportables) {
382 ids.push_back(t->getID());
383 }
384 return toString(ids);
385 }
386 throw InvalidArgument("Parameter '" + key + "' is not supported for device of type '" + deviceName() + "'");
387}
388
389
390/****************************************************************************/
long long int SUMOTime
Definition GUI.h:36
#define WRITE_WARNINGF(...)
Definition MsgHandler.h:287
#define WRITE_WARNING(msg)
Definition MsgHandler.h:286
#define TLF(string,...)
Definition MsgHandler.h:306
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:91
#define SIMSTEP
Definition SUMOTime.h:64
#define TIME2STEPS(x)
Definition SUMOTime.h:60
SUMOVehicleClass
Definition of vehicle classes to differ between different lane usage and authority types.
@ SUMO_TAG_DEVICE
@ SUMO_ATTR_ID
@ SUMO_ATTR_STATE
The state of a link.
T MAX2(T a, T b)
Definition StdDefs.h:86
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
Definition ToString.h:46
The base class for microscopic and mesoscopic vehicles.
virtual void addTransportable(MSTransportable *transportable)
Adds a person or container to this vehicle.
MSVehicleType & getSingularType()
Replaces the current vehicle type with a new one used by this vehicle only.
SUMOAbstractRouter< MSEdge, SUMOVehicle > & getRouterTT() const
bool reroute(SUMOTime t, const std::string &info, SUMOAbstractRouter< MSEdge, SUMOVehicle > &router, const bool onInit=false, const bool withTaz=false, const bool silent=false, const MSEdge *sink=nullptr)
Performs a rerouting using the given router.
A device which collects info on the vehicle trip (mainly on departure and arrival)
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
MSVehicleType * myLoadedType
the type to consult if loading/unloading changes vehicle properties
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.
const MSVehicleType * myOriginalType
the original type to set when nothing is being transported
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
void changeAttached()
modifiy vehicle properties when loading/unloading (optional)
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)
static SumoRNG * getEquipmentRNG()
Definition MSDevice.h:92
double getVehicleMaxSpeed(const SUMOTrafficObject *const veh) const
Returns the maximum speed the vehicle may use on this edge.
Definition MSEdge.cpp:1198
virtual void removeTransportable(MSTransportable *t) const
Definition MSEdge.cpp:1225
static bool gUseMesoSim
Definition MSGlobals.h:106
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:187
virtual MSTransportableControl & getContainerControl()
Returns the container control.
Definition MSNet.cpp:1267
SUMOTime getCurrentTimeStep() const
Returns the current simulation step.
Definition MSNet.h:334
MSVehicleControl & getVehicleControl()
Returns the vehicle control.
Definition MSNet.h:392
virtual MSTransportableControl & getPersonControl()
Returns the person control.
Definition MSNet.cpp:1258
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:88
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)
static bool active()
Definition MSStopOut.h:54
void unloadedPersons(const SUMOVehicle *veh, int n)
static MSStopOut * getInstance()
Definition MSStopOut.h:60
void unloadedContainers(const SUMOVehicle *veh, int n)
void loadedPersons(const SUMOVehicle *veh, int n)
Definition MSStopOut.cpp:96
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
const MSEdge * getDestination() const
Returns the current destination.
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)
MSStage * getCurrentStage() const
Return the current stage.
virtual bool proceed(MSNet *net, SUMOTime time, const bool vehicleArrived=false)
bool isPerson() const override
Whether it is a person.
const MSVehicleType & getVehicleType() const override
Returns the object's "vehicle" type.
const MSEdge * getEdge() const override
Returns the current edge.
SUMOVehicle * getVehicle(const std::string &id) const
Returns the vehicle with the given id.
MSVehicleType * getVType(const std::string &id=DEFAULT_VTYPE_ID, SumoRNG *rng=nullptr, bool readOnly=false)
Returns the named vehicle type or a sample from the named distribution.
Abstract in-vehicle device.
SUMOVehicle & myHolder
The vehicle that stores the device.
Representation of a vehicle in the micro simulation.
Definition MSVehicle.h:77
The car-following model and parameter.
SUMOVehicleClass getVehicleClass() const
Get this vehicle type's vehicle class.
void setGUIShape(SUMOVehicleShape shape)
Set a new value for this type's gui shape.
int getPersonCapacity() const
Get this vehicle type's person capacity.
SUMOTime getLoadingDuration(const bool isPerson) const
Get this vehicle type's loading duration.
void setLength(const double &length)
Set a new value for this type's length.
void setVClass(SUMOVehicleClass vclass)
Set a new value for this type's vehicle class.
double getLength() const
Get vehicle's length [m].
SUMOVehicleShape getGuiShape() const
Get this vehicle type's shape.
void setMass(double mass)
Set a new value for this type's mass.
double getMass() const
Get this vehicle type's mass.
double getBoardingFactor() const
Get this person type's factor for loading/boarding duration.
const SUMOVTypeParameter & getParameter() const
int getContainerCapacity() const
Get this vehicle type's container capacity.
const std::string & getID() const
Returns the id.
Definition Named.h:74
Static storage of an output device and its base (abstract) implementation.
OutputDevice & writeAttr(const SumoXMLAttr attr, const T &val)
writes a named attribute
OutputDevice & openTag(const std::string &xmlElement)
Opens an XML tag.
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 const MSVehicleType & getVehicleType() const =0
Returns the object's "vehicle" type.
std::string getStringParam(const std::string &paramName, const bool required=false, const std::string &deflt="") const
Retrieve a string parameter for the traffic object.
virtual void replaceVehicleType(const MSVehicleType *type)=0
Replaces the current vehicle type by the one given.
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 SUMOVehicleClass getVClass() const =0
Returns the object's access class.
virtual const MSEdge * getEdge() const =0
Returns the edge the object is currently at.
Structure representing possible vehicle parameter.
double locomotiveLength
the length of the locomotive
double carriageLength
the length of train carriages
double carriageGap
the length of the gap between carriages
Representation of a vehicle.
Definition SUMOVehicle.h:63
virtual bool isStopped() const =0
Returns whether the vehicle is at a stop and waiting for a person or container to continue.
virtual void removeTransportableMass(MSTransportable *t)=0
removes a person or containers mass
virtual std::unique_ptr< MFXOptionalLock > getScopeLock()=0
virtual const MSStop & getNextStop() const =0
virtual MSStop & getNextStopMutable()=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.