LCOV - code coverage report
Current view: top level - src/microsim/devices - MSDevice_Transportable.cpp (source / functions) Hit Total Coverage
Test: lcov.info Lines: 149 155 96.1 %
Date: 2024-04-29 15:38:36 Functions: 15 16 93.8 %

          Line data    Source code
       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             : /****************************************************************************/
      14             : /// @file    MSDevice_Transportable.cpp
      15             : /// @author  Daniel Krajzewicz
      16             : /// @author  Jakob Erdmann
      17             : /// @author  Michael Behrisch
      18             : /// @author  Laura Bieker
      19             : /// @author  Melanie Weber
      20             : /// @author  Andreas Kendziorra
      21             : /// @date    Fri, 30.01.2009
      22             : ///
      23             : // A device which is used to keep track of persons and containers riding with a vehicle
      24             : /****************************************************************************/
      25             : #include <config.h>
      26             : 
      27             : #include <utils/xml/SUMOSAXAttributes.h>
      28             : #include <microsim/output/MSStopOut.h>
      29             : #include <microsim/MSNet.h>
      30             : #include <microsim/MSEdge.h>
      31             : #include <microsim/MSStop.h>
      32             : #include <microsim/MSStoppingPlace.h>
      33             : #include <microsim/transportables/MSPerson.h>
      34             : #include <microsim/transportables/MSTransportableControl.h>
      35             : #include <microsim/transportables/MSStageDriving.h>
      36             : #include "MSDevice_Transportable.h"
      37             : #include "MSDevice_Taxi.h"
      38             : 
      39             : 
      40             : // ===========================================================================
      41             : // method definitions
      42             : // ===========================================================================
      43             : // ---------------------------------------------------------------------------
      44             : // static initialisation methods
      45             : // ---------------------------------------------------------------------------
      46             : MSDevice_Transportable*
      47        4777 : MSDevice_Transportable::buildVehicleDevices(SUMOVehicle& v, std::vector<MSVehicleDevice*>& into, const bool isContainer) {
      48        4777 :     MSDevice_Transportable* device = new MSDevice_Transportable(v, isContainer ? "container_" + v.getID() : "person_" + v.getID(), isContainer);
      49        4777 :     into.push_back(device);
      50        4777 :     return device;
      51             : }
      52             : 
      53             : 
      54             : // ---------------------------------------------------------------------------
      55             : // MSDevice_Transportable-methods
      56             : // ---------------------------------------------------------------------------
      57        4777 : MSDevice_Transportable::MSDevice_Transportable(SUMOVehicle& holder, const std::string& id, const bool isContainer) :
      58             :     MSVehicleDevice(holder, id),
      59        4777 :     myAmContainer(isContainer),
      60             :     myTransportables(),
      61        4777 :     myStopped(holder.isStopped())
      62        4777 : { }
      63             : 
      64             : 
      65        9554 : MSDevice_Transportable::~MSDevice_Transportable() {
      66             :     // flush any unfortunate riders still remaining
      67        4787 :     for (auto it = myTransportables.begin(); it != myTransportables.end();) {
      68          10 :         MSTransportable* transportable = *it;
      69          30 :         WRITE_WARNING((myAmContainer ? "Removing container '" : "Removing person '") + transportable->getID() +
      70             :                       "' at removal of vehicle '" + myHolder.getID() + "'");
      71          10 :         MSStageDriving* const stage = dynamic_cast<MSStageDriving*>(transportable->getCurrentStage());
      72          10 :         if (stage != nullptr) {
      73          10 :             stage->setVehicle(nullptr);
      74             :         }
      75          10 :         if (myAmContainer) {
      76           0 :             MSNet::getInstance()->getContainerControl().erase(transportable);
      77             :         } else {
      78          10 :             MSNet::getInstance()->getPersonControl().erase(transportable);
      79             :         }
      80          10 :         it = myTransportables.erase(it);
      81             :     }
      82        9554 : }
      83             : 
      84             : void
      85       11983 : MSDevice_Transportable::notifyMoveInternal(const SUMOTrafficObject& veh,
      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       11983 :     notifyMove(const_cast<SUMOTrafficObject&>(veh), -1, travelledDistanceFrontOnLane, veh.getEdge()->getVehicleMaxSpeed(&veh));
      94       11983 : }
      95             : 
      96             : bool
      97          44 : MSDevice_Transportable::anyLeavingAtStop(const MSStop& stop) const {
      98          54 :     for (const MSTransportable* t : myTransportables) {
      99          44 :         MSStageDriving* const stage = dynamic_cast<MSStageDriving*>(t->getCurrentStage());
     100          44 :         if (stage->canLeaveVehicle(t, myHolder, stop)) {
     101             :             return true;
     102             :         }
     103             :     }
     104             :     return false;
     105             : }
     106             : 
     107             : 
     108             : void
     109          12 : MSDevice_Transportable::transferAtSplitOrJoin(MSBaseVehicle* otherVeh) {
     110          12 :     const MSStop& stop = myHolder.getNextStop();
     111          30 :     for (auto it = myTransportables.begin(); it != myTransportables.end();) {
     112          18 :         MSTransportable* t = *it;
     113          18 :         if (t->getNumRemainingStages() > 1) {
     114          12 :             MSStageDriving* const stage = dynamic_cast<MSStageDriving*>(t->getCurrentStage());
     115          12 :             if (stage->canLeaveVehicle(t, myHolder, stop)) {
     116          12 :                 MSStageDriving* const stage2 = dynamic_cast<MSStageDriving*>(t->getNextStage(1));
     117          12 :                 if (stage2 && stage2->isWaitingFor(otherVeh)) {
     118          12 :                     it = myTransportables.erase(it);
     119             :                     // proceeding registers t as waiting on edge
     120          12 :                     t->proceed(MSNet::getInstance(), SIMSTEP); 
     121          12 :                     MSTransportableControl& tc = (t->isPerson() ?
     122           3 :                             MSNet::getInstance()->getPersonControl() :
     123           9 :                             MSNet::getInstance()->getContainerControl());
     124          12 :                     tc.abortWaitingForVehicle(t);
     125          12 :                     t->getEdge()->removeTransportable(t);
     126          12 :                     otherVeh->addTransportable(t);
     127          12 :                     stage2->setVehicle(otherVeh);
     128          12 :                     continue;
     129          12 :                 }
     130             :             }
     131             :         }
     132             :         it++;
     133             :     }
     134          12 : }
     135             : 
     136             : 
     137             : bool
     138       71536 : MSDevice_Transportable::willTransferAtJoin(const MSTransportable* t, const MSBaseVehicle* joinVeh) {
     139       71536 :     if (joinVeh && t->getNumRemainingStages() > 1) {
     140           6 :         MSStageDriving* const stage2 = dynamic_cast<MSStageDriving*>(t->getNextStage(1));
     141           6 :         return stage2->isWaitingFor(joinVeh);
     142             :     }
     143             :     return false;
     144             : }
     145             : 
     146             : 
     147             : bool
     148     1340194 : MSDevice_Transportable::notifyMove(SUMOTrafficObject& /*tObject*/, double /*oldPos*/, double newPos, double newSpeed) {
     149     1340194 :     SUMOVehicle& veh = myHolder;
     150     1340194 :     const SUMOTime currentTime = MSNet::getInstance()->getCurrentTimeStep();
     151     1340194 :     if (myStopped) {
     152      854352 :         if (!veh.isStopped()) {
     153        6206 :             const SUMOTime freeFlowTimeCorrection = MSGlobals::gUseMesoSim ? TIME2STEPS(newPos / newSpeed) : 0;
     154       20507 :             for (MSTransportable* const transportable : myTransportables) {
     155       14301 :                 transportable->setDeparted(currentTime - freeFlowTimeCorrection);
     156             :             }
     157        6206 :             myStopped = false;
     158             :         }
     159             :     } else {
     160      485842 :         if (veh.isStopped()) {
     161       66115 :             myStopped = true;
     162       66115 :             MSStop& stop = veh.getNextStop();
     163       66115 :             const MSVehicle* joinVeh = dynamic_cast<MSVehicle*>(MSNet::getInstance()->getVehicleControl().getVehicle(stop.pars.join));
     164       66115 :             const SUMOTime boardingDuration = veh.getVehicleType().getLoadingDuration(!myAmContainer);
     165       88370 :             for (std::vector<MSTransportable*>::iterator i = myTransportables.begin(); i != myTransportables.end();) {
     166       83526 :                 MSTransportable* transportable = *i;
     167       83526 :                 MSStageDriving* const stage = dynamic_cast<MSStageDriving*>(transportable->getCurrentStage());
     168       83526 :                 if (stage->canLeaveVehicle(transportable, myHolder, stop) && !willTransferAtJoin(transportable, joinVeh)) {
     169       71530 :                     SUMOTime& timeForNext = myAmContainer ? stop.timeToLoadNextContainer : stop.timeToBoardNextPerson;
     170       71530 :                     MSDevice_Taxi* taxiDevice = static_cast<MSDevice_Taxi*>(myHolder.getDevice(typeid(MSDevice_Taxi)));
     171       57535 :                     if (taxiDevice != nullptr && timeForNext == 0 && !MSGlobals::gUseMesoSim) {
     172             :                         // taxi passengers must leave at the end of the stop duration
     173         913 :                         timeForNext = stop.pars.started + stop.pars.duration;
     174             :                     }
     175       71530 :                     if (timeForNext - DELTA_T > currentTime) {
     176             :                         // try deboarding again in the next step
     177       61271 :                         myStopped = false;
     178       61271 :                         break;
     179             :                     }
     180       10259 :                     if (stage->getDestinationStop() != nullptr) {
     181        4815 :                         stage->getDestinationStop()->addTransportable(transportable);
     182             :                     }
     183             : 
     184             :                     SUMOTime arrivalTime = currentTime;
     185       10259 :                     if (MSGlobals::gUseMesoSim) {
     186             :                         // no boarding / unboarding time in meso
     187        1348 :                         arrivalTime += 1;
     188             :                     } else {
     189        8911 :                         if (timeForNext > currentTime - DELTA_T) {
     190        7259 :                             timeForNext += boardingDuration;
     191             :                         } else {
     192        1652 :                             timeForNext = currentTime + boardingDuration;
     193             :                         }
     194             :                     }
     195             :                     //ensure that vehicle stops long enough for deboarding
     196       10259 :                     stop.duration = MAX2(stop.duration, timeForNext - currentTime);
     197             : 
     198       10259 :                     i = myTransportables.erase(i); // erase first in case proceed throws an exception
     199       10259 :                     if (taxiDevice != nullptr) {
     200        2094 :                         taxiDevice->customerArrived(transportable);
     201             :                     }
     202       10259 :                     if (!transportable->proceed(MSNet::getInstance(), arrivalTime)) {
     203        4805 :                         if (myAmContainer) {
     204         223 :                             MSNet::getInstance()->getContainerControl().erase(transportable);
     205             :                         } else {
     206        4582 :                             MSNet::getInstance()->getPersonControl().erase(transportable);
     207             :                         }
     208             :                     }
     209       10259 :                     if (MSStopOut::active()) {
     210             :                         SUMOVehicle* vehicle = dynamic_cast<SUMOVehicle*>(&veh);
     211        2339 :                         if (myAmContainer) {
     212         118 :                             MSStopOut::getInstance()->unloadedContainers(vehicle, 1);
     213             :                         } else {
     214        2221 :                             MSStopOut::getInstance()->unloadedPersons(vehicle, 1);
     215             :                         }
     216             :                     }
     217       10259 :                     continue;
     218       10259 :                 }
     219             :                 ++i;
     220             :             }
     221             :         }
     222             :     }
     223     1340194 :     return true;
     224             : }
     225             : 
     226             : 
     227             : bool
     228       57677 : MSDevice_Transportable::notifyEnter(SUMOTrafficObject& veh, MSMoveReminder::Notification reason, const MSLane* /* enteredLane */) {
     229       57677 :     if (reason == MSMoveReminder::NOTIFICATION_DEPARTED) {
     230        2759 :         const SUMOTime currentTime = MSNet::getInstance()->getCurrentTimeStep();
     231        6274 :         for (MSTransportable* const transportable : myTransportables) {
     232        3515 :             transportable->setDeparted(currentTime);
     233             :         }
     234             :     }
     235       57677 :     if (MSGlobals::gUseMesoSim) {
     236             :         // to trigger vehicle leaving
     237       12346 :         notifyMove(veh, -1., -1., -1.);
     238             :     }
     239       57677 :     return true;
     240             : }
     241             : 
     242             : 
     243             : bool
     244       58700 : MSDevice_Transportable::notifyLeave(SUMOTrafficObject& veh, double /*lastPos*/,
     245             :                                     MSMoveReminder::Notification reason, const MSLane* /* enteredLane */) {
     246       58700 :     if (reason >= MSMoveReminder::NOTIFICATION_ARRIVED) {
     247        7366 :         for (std::vector<MSTransportable*>::iterator i = myTransportables.begin(); i != myTransportables.end();) {
     248        3324 :             MSTransportableControl& tc = myAmContainer ? MSNet::getInstance()->getContainerControl() : MSNet::getInstance()->getPersonControl();
     249        3324 :             MSTransportable* transportable = *i;
     250        3324 :             if (transportable->getDestination() != veh.getEdge()) {
     251         112 :                 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));
     254             :                 tc.registerTeleportWrongDest();
     255             :             }
     256        3324 :             if (!transportable->proceed(MSNet::getInstance(), MSNet::getInstance()->getCurrentTimeStep(), true)) {
     257        3100 :                 tc.erase(transportable);
     258             :             }
     259        3324 :             i = myTransportables.erase(i);
     260             :         }
     261             :     }
     262       58700 :     return true;
     263             : }
     264             : 
     265             : 
     266             : void
     267       13758 : MSDevice_Transportable::addTransportable(MSTransportable* transportable) {
     268       13758 :     myTransportables.push_back(transportable);
     269       13758 :     if (MSStopOut::active()) {
     270        3343 :         if (myAmContainer) {
     271         187 :             MSStopOut::getInstance()->loadedContainers(&myHolder, 1);
     272             :         } else {
     273        3156 :             MSStopOut::getInstance()->loadedPersons(&myHolder, 1);
     274             :         }
     275             :     }
     276       13758 :     MSDevice_Taxi* taxiDevice = static_cast<MSDevice_Taxi*>(myHolder.getDevice(typeid(MSDevice_Taxi)));
     277             :     if (taxiDevice != nullptr) {
     278        2107 :         taxiDevice->customerEntered(transportable);
     279             :     }
     280       13758 : }
     281             : 
     282             : 
     283             : void
     284         153 : MSDevice_Transportable::removeTransportable(MSTransportable* transportable) {
     285         153 :     auto it = std::find(myTransportables.begin(), myTransportables.end(), transportable);
     286         153 :     if (it != myTransportables.end()) {
     287         153 :         myTransportables.erase(it);
     288         153 :         if (MSStopOut::active() && myHolder.isStopped()) {
     289          55 :             if (myAmContainer) {
     290          20 :                 MSStopOut::getInstance()->unloadedContainers(&myHolder, 1);
     291             :             } else {
     292          35 :                 MSStopOut::getInstance()->unloadedPersons(&myHolder, 1);
     293             :             }
     294             :         }
     295         153 :         MSDevice_Taxi* taxiDevice = static_cast<MSDevice_Taxi*>(myHolder.getDevice(typeid(MSDevice_Taxi)));
     296             :         if (taxiDevice != nullptr) {
     297          13 :             taxiDevice->customerArrived(transportable);
     298             :         }
     299             :     }
     300         153 : }
     301             : 
     302             : 
     303             : void
     304          14 : MSDevice_Transportable::saveState(OutputDevice& out) const {
     305          14 :     out.openTag(SUMO_TAG_DEVICE);
     306             :     out.writeAttr(SUMO_ATTR_ID, getID());
     307             :     std::vector<std::string> internals;
     308          14 :     internals.push_back(toString(myStopped));
     309          14 :     out.writeAttr(SUMO_ATTR_STATE, toString(internals));
     310          14 :     out.closeTag();
     311          14 : }
     312             : 
     313             : 
     314             : void
     315           0 : MSDevice_Transportable::loadState(const SUMOSAXAttributes& attrs) {
     316           0 :     std::istringstream bis(attrs.getString(SUMO_ATTR_STATE));
     317           0 :     bis >> myStopped;
     318           0 : }
     319             : 
     320             : 
     321             : std::string
     322           6 : MSDevice_Transportable::getParameter(const std::string& key) const {
     323           6 :     if (key == "IDList") {
     324             :         std::vector<std::string> ids;
     325          12 :         for (const MSTransportable* t : myTransportables) {
     326           6 :             ids.push_back(t->getID());
     327             :         }
     328          12 :         return toString(ids);
     329           6 :     }
     330           0 :     throw InvalidArgument("Parameter '" + key + "' is not supported for device of type '" + deviceName() + "'");
     331             : }
     332             : 
     333             : 
     334             : /****************************************************************************/

Generated by: LCOV version 1.14