LCOV - code coverage report
Current view: top level - src/microsim/devices - MSDevice_Transportable.cpp (source / functions) Coverage Total Hit
Test: lcov.info Lines: 96.2 % 156 150
Test Date: 2024-11-22 15:46:21 Functions: 93.8 % 16 15

            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         4575 : MSDevice_Transportable::buildVehicleDevices(SUMOVehicle& v, std::vector<MSVehicleDevice*>& into, const bool isContainer) {
      48         4575 :     MSDevice_Transportable* device = new MSDevice_Transportable(v, isContainer ? "container_" + v.getID() : "person_" + v.getID(), isContainer);
      49         4575 :     into.push_back(device);
      50         4575 :     return device;
      51              : }
      52              : 
      53              : 
      54              : // ---------------------------------------------------------------------------
      55              : // MSDevice_Transportable-methods
      56              : // ---------------------------------------------------------------------------
      57         4575 : MSDevice_Transportable::MSDevice_Transportable(SUMOVehicle& holder, const std::string& id, const bool isContainer) :
      58              :     MSVehicleDevice(holder, id),
      59         4575 :     myAmContainer(isContainer),
      60              :     myTransportables(),
      61         4575 :     myStopped(holder.isStopped())
      62         4575 : { }
      63              : 
      64              : 
      65         9150 : MSDevice_Transportable::~MSDevice_Transportable() {
      66              :     // flush any unfortunate riders still remaining
      67         4585 :     for (auto it = myTransportables.begin(); it != myTransportables.end();) {
      68           10 :         MSTransportable* transportable = *it;
      69           40 :         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         9150 : }
      83              : 
      84              : void
      85        13662 : 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        13662 :     notifyMove(const_cast<SUMOTrafficObject&>(veh), -1, travelledDistanceFrontOnLane, veh.getEdge()->getVehicleMaxSpeed(&veh));
      94        13662 : }
      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        68854 : MSDevice_Transportable::willTransferAtJoin(const MSTransportable* t, const MSBaseVehicle* joinVeh) {
     139        68854 :     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      1001196 : MSDevice_Transportable::notifyMove(SUMOTrafficObject& /*tObject*/, double /*oldPos*/, double newPos, double newSpeed) {
     149      1001196 :     SUMOVehicle& veh = myHolder;
     150      1001196 :     const SUMOTime currentTime = MSNet::getInstance()->getCurrentTimeStep();
     151      1001196 :     if (myStopped) {
     152       548899 :         if (!veh.isStopped()) {
     153         5586 :             const SUMOTime freeFlowTimeCorrection = MSGlobals::gUseMesoSim ? TIME2STEPS(newPos / newSpeed) : 0;
     154        17301 :             for (MSTransportable* const transportable : myTransportables) {
     155        11715 :                 transportable->setDeparted(currentTime - freeFlowTimeCorrection);
     156              :             }
     157         5586 :             myStopped = false;
     158              :         }
     159              :     } else {
     160       452297 :         if (veh.isStopped()) {
     161        64369 :             myStopped = true;
     162        64369 :             MSStop& stop = veh.getNextStop();
     163        64369 :             const MSVehicle* joinVeh = dynamic_cast<MSVehicle*>(MSNet::getInstance()->getVehicleControl().getVehicle(stop.pars.join));
     164        64369 :             const SUMOTime boardingDuration = veh.getVehicleType().getLoadingDuration(!myAmContainer);
     165        80273 :             for (std::vector<MSTransportable*>::iterator i = myTransportables.begin(); i != myTransportables.end();) {
     166        75989 :                 MSTransportable* transportable = *i;
     167        75989 :                 MSStageDriving* const stage = dynamic_cast<MSStageDriving*>(transportable->getCurrentStage());
     168        75989 :                 if (stage->canLeaveVehicle(transportable, myHolder, stop) && !willTransferAtJoin(transportable, joinVeh)) {
     169        68848 :                     SUMOTime& timeForNext = myAmContainer ? stop.timeToLoadNextContainer : stop.timeToBoardNextPerson;
     170        68848 :                     MSDevice_Taxi* taxiDevice = static_cast<MSDevice_Taxi*>(myHolder.getDevice(typeid(MSDevice_Taxi)));
     171        56522 :                     if (taxiDevice != nullptr && timeForNext == 0 && !MSGlobals::gUseMesoSim) {
     172              :                         // taxi passengers must leave at the end of the stop duration
     173          905 :                         timeForNext = stop.pars.started + stop.pars.duration;
     174              :                     }
     175        68848 :                     if (timeForNext - DELTA_T > currentTime) {
     176              :                         // try deboarding again in the next step
     177        60085 :                         myStopped = false;
     178        60085 :                         break;
     179              :                     }
     180         8763 :                     if (stage->getDestinationStop() != nullptr) {
     181         4630 :                         stage->getDestinationStop()->addTransportable(transportable);
     182              :                     }
     183              : 
     184              :                     SUMOTime arrivalTime = currentTime;
     185         8763 :                     if (MSGlobals::gUseMesoSim) {
     186              :                         // no boarding / unboarding time in meso
     187         1594 :                         arrivalTime += 1;
     188              :                     } else {
     189         7169 :                         const SUMOTime boardingTime = (SUMOTime)((double)boardingDuration * transportable->getVehicleType().getBoardingFactor());
     190         7169 :                         if (timeForNext > currentTime - DELTA_T) {
     191         5937 :                             timeForNext += boardingTime;
     192              :                         } else {
     193         1232 :                             timeForNext = currentTime + boardingTime;
     194              :                         }
     195              :                     }
     196              :                     //ensure that vehicle stops long enough for deboarding
     197         8763 :                     stop.duration = MAX2(stop.duration, timeForNext - currentTime);
     198              : 
     199         8763 :                     i = myTransportables.erase(i); // erase first in case proceed throws an exception
     200         8763 :                     if (taxiDevice != nullptr) {
     201         1870 :                         taxiDevice->customerArrived(transportable);
     202              :                     }
     203         8763 :                     if (!transportable->proceed(MSNet::getInstance(), arrivalTime)) {
     204         4385 :                         if (myAmContainer) {
     205          241 :                             MSNet::getInstance()->getContainerControl().erase(transportable);
     206              :                         } else {
     207         4144 :                             MSNet::getInstance()->getPersonControl().erase(transportable);
     208              :                         }
     209              :                     }
     210         8763 :                     if (MSStopOut::active()) {
     211              :                         SUMOVehicle* vehicle = dynamic_cast<SUMOVehicle*>(&veh);
     212         1672 :                         if (myAmContainer) {
     213          118 :                             MSStopOut::getInstance()->unloadedContainers(vehicle, 1);
     214              :                         } else {
     215         1554 :                             MSStopOut::getInstance()->unloadedPersons(vehicle, 1);
     216              :                         }
     217              :                     }
     218         8763 :                     continue;
     219         8763 :                 }
     220              :                 ++i;
     221              :             }
     222              :         }
     223              :     }
     224      1001196 :     return true;
     225              : }
     226              : 
     227              : 
     228              : bool
     229        49790 : MSDevice_Transportable::notifyEnter(SUMOTrafficObject& veh, MSMoveReminder::Notification reason, const MSLane* /* enteredLane */) {
     230        49790 :     if (reason == MSMoveReminder::NOTIFICATION_DEPARTED) {
     231         2460 :         const SUMOTime currentTime = MSNet::getInstance()->getCurrentTimeStep();
     232         5352 :         for (MSTransportable* const transportable : myTransportables) {
     233         2892 :             transportable->setDeparted(currentTime);
     234              :         }
     235              :     }
     236        49790 :     if (MSGlobals::gUseMesoSim) {
     237              :         // to trigger vehicle leaving
     238        14085 :         notifyMove(veh, -1., -1., -1.);
     239              :     }
     240        49790 :     return true;
     241              : }
     242              : 
     243              : 
     244              : bool
     245        50781 : MSDevice_Transportable::notifyLeave(SUMOTrafficObject& veh, double /*lastPos*/,
     246              :                                     MSMoveReminder::Notification reason, const MSLane* /* enteredLane */) {
     247        50781 :     if (reason >= MSMoveReminder::NOTIFICATION_ARRIVED) {
     248         7775 :         for (std::vector<MSTransportable*>::iterator i = myTransportables.begin(); i != myTransportables.end();) {
     249         3929 :             MSTransportableControl& tc = myAmContainer ? MSNet::getInstance()->getContainerControl() : MSNet::getInstance()->getPersonControl();
     250         3929 :             MSTransportable* transportable = *i;
     251         3929 :             if (transportable->getDestination() != veh.getEdge()) {
     252          142 :                 WRITE_WARNING((myAmContainer ? "Teleporting container '" : "Teleporting person '") + transportable->getID() +
     253              :                               "' from vehicle destination edge '" + veh.getEdge()->getID() +
     254              :                               "' to intended destination edge '" + transportable->getDestination()->getID() + "' time=" + time2string(SIMSTEP));
     255              :                 tc.registerTeleportWrongDest();
     256              :             }
     257         3929 :             if (!transportable->proceed(MSNet::getInstance(), MSNet::getInstance()->getCurrentTimeStep(), true)) {
     258         3712 :                 tc.erase(transportable);
     259              :             }
     260         3929 :             i = myTransportables.erase(i);
     261              :         }
     262              :     }
     263        50781 :     return true;
     264              : }
     265              : 
     266              : 
     267              : void
     268        12892 : MSDevice_Transportable::addTransportable(MSTransportable* transportable) {
     269        12892 :     myTransportables.push_back(transportable);
     270        12892 :     if (MSStopOut::active()) {
     271         2674 :         if (myAmContainer) {
     272          187 :             MSStopOut::getInstance()->loadedContainers(&myHolder, 1);
     273              :         } else {
     274         2487 :             MSStopOut::getInstance()->loadedPersons(&myHolder, 1);
     275              :         }
     276              :     }
     277        12892 :     MSDevice_Taxi* taxiDevice = static_cast<MSDevice_Taxi*>(myHolder.getDevice(typeid(MSDevice_Taxi)));
     278              :     if (taxiDevice != nullptr) {
     279         1881 :         taxiDevice->customerEntered(transportable);
     280              :     }
     281        12892 : }
     282              : 
     283              : 
     284              : void
     285          178 : MSDevice_Transportable::removeTransportable(MSTransportable* transportable) {
     286          178 :     auto it = std::find(myTransportables.begin(), myTransportables.end(), transportable);
     287          178 :     if (it != myTransportables.end()) {
     288          178 :         myTransportables.erase(it);
     289          178 :         if (MSStopOut::active() && myHolder.isStopped()) {
     290           55 :             if (myAmContainer) {
     291           20 :                 MSStopOut::getInstance()->unloadedContainers(&myHolder, 1);
     292              :             } else {
     293           35 :                 MSStopOut::getInstance()->unloadedPersons(&myHolder, 1);
     294              :             }
     295              :         }
     296          178 :         MSDevice_Taxi* taxiDevice = static_cast<MSDevice_Taxi*>(myHolder.getDevice(typeid(MSDevice_Taxi)));
     297              :         if (taxiDevice != nullptr) {
     298           11 :             taxiDevice->customerArrived(transportable);
     299              :         }
     300              :     }
     301          178 : }
     302              : 
     303              : 
     304              : void
     305            9 : MSDevice_Transportable::saveState(OutputDevice& out) const {
     306            9 :     out.openTag(SUMO_TAG_DEVICE);
     307              :     out.writeAttr(SUMO_ATTR_ID, getID());
     308              :     std::vector<std::string> internals;
     309            9 :     internals.push_back(toString(myStopped));
     310            9 :     out.writeAttr(SUMO_ATTR_STATE, toString(internals));
     311            9 :     out.closeTag();
     312            9 : }
     313              : 
     314              : 
     315              : void
     316            0 : MSDevice_Transportable::loadState(const SUMOSAXAttributes& attrs) {
     317            0 :     std::istringstream bis(attrs.getString(SUMO_ATTR_STATE));
     318            0 :     bis >> myStopped;
     319            0 : }
     320              : 
     321              : 
     322              : std::string
     323            5 : MSDevice_Transportable::getParameter(const std::string& key) const {
     324            5 :     if (key == "IDList") {
     325              :         std::vector<std::string> ids;
     326           10 :         for (const MSTransportable* t : myTransportables) {
     327            5 :             ids.push_back(t->getID());
     328              :         }
     329           10 :         return toString(ids);
     330            5 :     }
     331            0 :     throw InvalidArgument("Parameter '" + key + "' is not supported for device of type '" + deviceName() + "'");
     332              : }
     333              : 
     334              : 
     335              : /****************************************************************************/
        

Generated by: LCOV version 2.0-1