LCOV - code coverage report
Current view: top level - src/microsim/transportables - MSTransportableControl.cpp (source / functions) Hit Total Coverage
Test: lcov.info Lines: 233 239 97.5 %
Date: 2024-05-07 15:28:01 Functions: 27 27 100.0 %

          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    MSTransportableControl.cpp
      15             : /// @author  Daniel Krajzewicz
      16             : /// @author  Jakob Erdmann
      17             : /// @author  Sascha Krieg
      18             : /// @author  Michael Behrisch
      19             : /// @date    Mon, 9 Jul 2001
      20             : ///
      21             : // Stores all persons in the net and handles their waiting for cars.
      22             : /****************************************************************************/
      23             : #include <config.h>
      24             : 
      25             : #include <vector>
      26             : #include <algorithm>
      27             : #include <utils/iodevices/OutputDevice.h>
      28             : #include <utils/iodevices/OutputDevice_String.h>
      29             : #include <utils/options/OptionsCont.h>
      30             : #include <microsim/transportables/MSPerson.h>
      31             : #include <microsim/transportables/MSStageDriving.h>
      32             : #include <microsim/transportables/MSPModel_NonInteracting.h>
      33             : #ifdef JPS_VERSION
      34             : #include <microsim/transportables/MSPModel_JuPedSim.h>
      35             : #endif
      36             : #include <microsim/transportables/MSPModel_Striping.h>
      37             : #include <microsim/transportables/MSTransportableControl.h>
      38             : #include <microsim/devices/MSDevice_Vehroutes.h>
      39             : #include <microsim/MSNet.h>
      40             : #include <microsim/MSEdge.h>
      41             : #include <microsim/MSVehicle.h>
      42             : #include <microsim/MSStoppingPlace.h>
      43             : 
      44             : 
      45             : // ===========================================================================
      46             : // method definitions
      47             : // ===========================================================================
      48        5606 : MSTransportableControl::MSTransportableControl(const bool isPerson):
      49        5606 :     myLoadedNumber(0),
      50        5606 :     myDiscardedNumber(0),
      51        5606 :     myRunningNumber(0),
      52        5606 :     myJammedNumber(0),
      53        5606 :     myWaitingForDepartureNumber(0),
      54        5606 :     myWaitingForVehicleNumber(0),
      55        5606 :     myWaitingUntilNumber(0),
      56        5606 :     myAccessNumber(0),
      57        5606 :     myEndedNumber(0),
      58        5606 :     myArrivedNumber(0),
      59        5606 :     myTeleportsAbortWait(0),
      60        5606 :     myTeleportsWrongDest(0),
      61        5606 :     myHaveNewWaiting(false) {
      62        5606 :     const OptionsCont& oc = OptionsCont::getOptions();
      63        5606 :     MSNet* const net = MSNet::getInstance();
      64        5606 :     myMovementModel = myNonInteractingModel = new MSPModel_NonInteracting(oc, net);
      65        5606 :     if (isPerson) {
      66       10050 :         const std::string& model = oc.getString("pedestrian.model");
      67        5025 :         if (model == "striping") {
      68        3246 :             myMovementModel = new MSPModel_Striping(oc, net);
      69             : #ifdef JPS_VERSION
      70             :         } else if (model == "jupedsim") {
      71             :             myMovementModel = new MSPModel_JuPedSim(oc, net);
      72             : #endif
      73        1779 :         } else if (model != "nonInteracting") {
      74          14 :             delete myNonInteractingModel;
      75          56 :             throw ProcessError(TLF("Unknown pedestrian model '%'", model));
      76             :         }
      77             :     }
      78       11184 :     if (oc.isSet("vehroute-output")) {
      79        1321 :         myRouteInfos.routeOut = &OutputDevice::getDeviceByOption("vehroute-output");
      80             :     }
      81       11184 :     if (oc.isSet("personroute-output")) {
      82          24 :         OutputDevice::createDeviceByOption("personroute-output", "routes", "routes_file.xsd");
      83          24 :         myRouteInfos.routeOut = &OutputDevice::getDeviceByOption("personroute-output");
      84             :     }
      85       11184 :     if (oc.isSet("personinfo-output")) {
      86          54 :         OutputDevice::createDeviceByOption("personinfo-output", "tripinfos", "tripinfo_file.xsd");
      87             :     }
      88        5592 :     myAbortWaitingTimeout = string2time(oc.getString("time-to-teleport.ride"));
      89        5606 : }
      90             : 
      91             : 
      92        9651 : MSTransportableControl::~MSTransportableControl() {
      93        5573 :     clearState();
      94        5573 :     if (myMovementModel != myNonInteractingModel) {
      95        3238 :         delete myMovementModel;
      96             :     }
      97        5573 :     delete myNonInteractingModel;
      98        9651 : }
      99             : 
     100             : 
     101             : bool
     102      457026 : MSTransportableControl::add(MSTransportable* transportable) {
     103      457026 :     const SUMOVehicleParameter& param = transportable->getParameter();
     104      457026 :     if (myTransportables.find(param.id) == myTransportables.end()) {
     105      457010 :         myTransportables[param.id] = transportable;
     106      457010 :         const SUMOTime step = param.depart % DELTA_T == 0 ? param.depart : (param.depart / DELTA_T + 1) * DELTA_T;
     107      457010 :         myWaiting4Departure[step].push_back(transportable);
     108      457010 :         myLoadedNumber++;
     109      457010 :         myWaitingForDepartureNumber++;
     110             :         return true;
     111             :     }
     112             :     return false;
     113             : }
     114             : 
     115             : 
     116             : void
     117          69 : MSTransportableControl::fixLoadCount(const MSTransportable* transportable) {
     118          69 :     myLoadedNumber--;
     119          69 :     if (transportable->hasDeparted()) {
     120          60 :         const SUMOVehicleParameter& param = transportable->getParameter();
     121          60 :         const SUMOTime step = param.depart % DELTA_T == 0 ? param.depart : (param.depart / DELTA_T + 1) * DELTA_T;
     122          60 :         TransportableVector& waiting = myWaiting4Departure[step];
     123          60 :         auto it = std::find(waiting.begin(), waiting.end(), transportable);
     124          60 :         if (it != waiting.end()) {
     125             :             waiting.erase(it);
     126          60 :             if (waiting.size() == 0) {
     127             :                 myWaiting4Departure.erase(step);
     128             :             }
     129             :         }
     130             :     }
     131          69 : }
     132             : 
     133             : 
     134             : MSTransportable*
     135      566439 : MSTransportableControl::get(const std::string& id) const {
     136             :     std::map<std::string, MSTransportable*>::const_iterator i = myTransportables.find(id);
     137      566439 :     if (i == myTransportables.end()) {
     138             :         return nullptr;
     139             :     }
     140      565818 :     return (*i).second;
     141             : }
     142             : 
     143             : 
     144             : void
     145      437596 : MSTransportableControl::erase(MSTransportable* transportable) {
     146      437596 :     const OptionsCont& oc = OptionsCont::getOptions();
     147      875192 :     if (oc.isSet("personinfo-output")) {
     148         360 :         transportable->tripInfoOutput(OutputDevice::getDeviceByOption("personinfo-output"));
     149      874832 :     } else if (oc.isSet("tripinfo-output")) {
     150       63820 :         transportable->tripInfoOutput(OutputDevice::getDeviceByOption("tripinfo-output"));
     151      811012 :     } else if (oc.getBool("duration-log.statistics")) {
     152             :         // collecting statistics is a sideffect
     153       15642 :         OutputDevice_String dev;
     154       15642 :         transportable->tripInfoOutput(dev);
     155       15642 :     }
     156      872498 :     if (oc.isSet("vehroute-output") || oc.isSet("personroute-output")) {
     157        2930 :         if (transportable->hasArrived() || oc.getBool("vehroute-output.write-unfinished")) {
     158        5356 :             if (oc.getBool("vehroute-output.sorted")) {
     159         122 :                 const SUMOTime departure = oc.getBool("vehroute-output.intended-depart") ? transportable->getParameter().depart : transportable->getDeparture();
     160         122 :                 OutputDevice_String od(1);
     161         122 :                 transportable->routeOutput(od, oc.getBool("vehroute-output.route-length"));
     162         122 :                 MSDevice_Vehroutes::writeSortedOutput(&myRouteInfos,
     163         122 :                                                       departure, transportable->getID(), od.getString());
     164         122 :             } else {
     165        5112 :                 transportable->routeOutput(*myRouteInfos.routeOut, oc.getBool("vehroute-output.route-length"));
     166             :             }
     167             :         }
     168             :     }
     169             :     const std::map<std::string, MSTransportable*>::iterator i = myTransportables.find(transportable->getID());
     170      437596 :     if (i != myTransportables.end()) {
     171      437596 :         myRunningNumber--;
     172      437596 :         myEndedNumber++;
     173     1013878 :         MSNet::getInstance()->informTransportableStateListener(transportable,
     174      437596 :                 transportable->isPerson() ? MSNet::TransportableState::PERSON_ARRIVED : MSNet::TransportableState::CONTAINER_ARRIVED);
     175      437596 :         delete i->second;
     176             :         myTransportables.erase(i);
     177             :     }
     178      437596 : }
     179             : 
     180             : 
     181             : void
     182        9476 : MSTransportableControl::setWaitEnd(const SUMOTime time, MSTransportable* transportable) {
     183        9476 :     const SUMOTime step = time % DELTA_T == 0 ? time : (time / DELTA_T + 1) * DELTA_T;
     184             :     // avoid double registration
     185        9476 :     const TransportableVector& transportables = myWaitingUntil[step];
     186        9476 :     if (std::find(transportables.begin(), transportables.end(), transportable) == transportables.end()) {
     187        9476 :         myWaitingUntil[step].push_back(transportable);
     188        9476 :         myWaitingUntilNumber++;
     189             :     }
     190        9476 : }
     191             : 
     192             : 
     193             : void
     194     2455449 : MSTransportableControl::checkWaiting(MSNet* net, const SUMOTime time) {
     195     2455449 :     myHaveNewWaiting = false;
     196     5179508 :     while (myWaiting4Departure.find(time) != myWaiting4Departure.end()) {
     197      268639 :         TransportableVector& transportables = myWaiting4Departure[time];
     198             :         // we cannot use an iterator here because there might be additions to the vector while proceeding
     199      708788 :         for (auto it = transportables.begin(); it != transportables.end();) {
     200      440178 :             MSTransportable* t = *it;
     201             :             it = transportables.erase(it);
     202      440178 :             myWaitingForDepartureNumber--;
     203      440178 :             const bool isPerson = t->isPerson();
     204      440178 :             if (t->proceed(net, time)) {
     205      440149 :                 myRunningNumber++;
     206      578863 :                 MSNet::getInstance()->informTransportableStateListener(t,
     207             :                         isPerson ? MSNet::TransportableState::PERSON_DEPARTED : MSNet::TransportableState::CONTAINER_DEPARTED);
     208      440149 :                 const OptionsCont& oc = OptionsCont::getOptions();
     209      880298 :                 if (oc.getBool("vehroute-output.sorted")) {
     210         132 :                     const SUMOTime departure = oc.getBool("vehroute-output.intended-depart") ? t->getParameter().depart : time;
     211         264 :                     if (oc.isSet("personroute-output")) {
     212          24 :                         myRouteInfos.departureCounts[departure]++;
     213             :                     } else {
     214         108 :                         MSDevice_Vehroutes::registerTransportableDepart(departure);
     215             :                     }
     216             :                 }
     217             :             } else {
     218           0 :                 erase(t);
     219             :             }
     220             :         }
     221             :         myWaiting4Departure.erase(time);
     222             :     }
     223     2463679 :     while (myWaitingUntil.find(time) != myWaitingUntil.end()) {
     224             :         // make a copy because 0-duration stops might modify the vector
     225        8266 :         const TransportableVector transportables = myWaitingUntil[time];
     226             :         myWaitingUntil.erase(time);
     227       17452 :         for (MSTransportable* t : transportables) {
     228        9193 :             myWaitingUntilNumber--;
     229        9193 :             if (!t->proceed(net, time)) {
     230        7708 :                 erase(t);
     231             :             }
     232             :         }
     233             :     }
     234     2455413 : }
     235             : 
     236             : 
     237             : void
     238          53 : MSTransportableControl::forceDeparture() {
     239          53 :     myRunningNumber++;
     240          53 : }
     241             : 
     242             : 
     243             : void
     244       39969 : MSTransportableControl::addWaiting(const MSEdge* const edge, MSTransportable* transportable) {
     245       39969 :     myWaiting4Vehicle[edge].push_back(transportable);
     246       39969 :     myWaitingForVehicleNumber++;
     247       39969 :     myHaveNewWaiting = true;
     248       39969 :     if (myAbortWaitingTimeout >= 0) {
     249          16 :         transportable->setAbortWaiting(myAbortWaitingTimeout);
     250             :     }
     251       39969 : }
     252             : 
     253             : 
     254             : bool
     255          83 : MSTransportableControl::hasAnyWaiting(const MSEdge* edge, SUMOVehicle* vehicle) const {
     256             :     const auto wait = myWaiting4Vehicle.find(edge);
     257          83 :     if (wait != myWaiting4Vehicle.end()) {
     258          44 :         for (const MSTransportable* t : wait->second) {
     259             :             if (t->isWaitingFor(vehicle)
     260          39 :                     && vehicle->allowsBoarding(t)
     261          78 :                     && vehicle->isStoppedInRange(t->getEdgePos(), MSGlobals::gStopTolerance, true)) {
     262             :                 return true;
     263             :             }
     264             :         }
     265             :     }
     266             :     return false;
     267             : }
     268             : 
     269             : 
     270             : bool
     271     1229736 : MSTransportableControl::loadAnyWaiting(const MSEdge* edge, SUMOVehicle* vehicle, SUMOTime& timeToLoadNext, SUMOTime& stopDuration) {
     272             :     bool ret = false;
     273             :     const auto wait = myWaiting4Vehicle.find(edge);
     274     1229736 :     if (wait != myWaiting4Vehicle.end()) {
     275       35778 :         const SUMOTime currentTime = SIMSTEP;
     276       35778 :         TransportableVector& transportables = wait->second;
     277      345191 :         for (TransportableVector::iterator i = transportables.begin(); i != transportables.end();) {
     278      309413 :             MSTransportable* const t = *i;
     279             :             if (t->isWaitingFor(vehicle)
     280      254298 :                     && vehicle->allowsBoarding(t)
     281      127216 :                     && timeToLoadNext - DELTA_T <= currentTime
     282      323644 :                     && vehicle->isStoppedInRange(t->getEdgePos(), MSGlobals::gStopTolerance)) {
     283       10218 :                 edge->removeTransportable(t);
     284       10218 :                 vehicle->addTransportable(t);
     285       10218 :                 if (myAbortWaitingTimeout >= 0) {
     286           0 :                     t->setAbortWaiting(-1);
     287             :                 }
     288       10218 :                 if (timeToLoadNext >= 0) { // meso does not have loading times
     289        8576 :                     const SUMOTime loadingDuration = vehicle->getVehicleType().getLoadingDuration(t->isPerson());
     290             :                     //update the time point at which the next transportable can be loaded on the vehicle
     291        8576 :                     if (timeToLoadNext > currentTime - DELTA_T) {
     292        5900 :                         timeToLoadNext += loadingDuration;
     293             :                     } else {
     294        2676 :                         timeToLoadNext = currentTime + loadingDuration;
     295             :                     }
     296             :                 }
     297             : 
     298       10218 :                 static_cast<MSStageDriving*>(t->getCurrentStage())->setVehicle(vehicle);
     299       10218 :                 if (t->getCurrentStage()->getOriginStop() != nullptr) {
     300        6072 :                     t->getCurrentStage()->getOriginStop()->removeTransportable(*i);
     301             :                 }
     302             :                 i = transportables.erase(i);
     303       10218 :                 myWaitingForVehicleNumber--;
     304             :                 ret = true;
     305             :             } else {
     306             :                 ++i;
     307             :             }
     308             :         }
     309       35778 :         if (transportables.empty()) {
     310             :             myWaiting4Vehicle.erase(wait);
     311             :         }
     312       35778 :         if (ret && timeToLoadNext >= 0) {
     313             :             //if the time a transportable needs to get loaded on the vehicle extends the duration of the stop of the vehicle extend
     314             :             //the duration by setting it to the loading duration of the transportable
     315        5411 :             stopDuration = MAX2(stopDuration, timeToLoadNext - currentTime);
     316             :         }
     317             :     }
     318     1229736 :     return ret;
     319             : }
     320             : 
     321             : 
     322             : bool
     323     4013814 : MSTransportableControl::hasTransportables() const {
     324     4013814 :     return !myTransportables.empty();
     325             : }
     326             : 
     327             : 
     328             : bool
     329     1444988 : MSTransportableControl::hasNonWaiting() const {
     330     1444988 :     return !myWaiting4Departure.empty() || getMovingNumber() > 0 || myWaitingUntilNumber > 0 || myHaveNewWaiting;
     331             : }
     332             : 
     333             : 
     334             : int
     335       47616 : MSTransportableControl::getActiveCount() {
     336       47616 :     return (int)myWaiting4Departure.size() + myRunningNumber - myWaitingForVehicleNumber;
     337             : }
     338             : 
     339             : 
     340             : int
     341      876083 : MSTransportableControl::getMovingNumber() const {
     342      876083 :     return myMovementModel->getActiveNumber() + myAccessNumber;
     343             : }
     344             : 
     345             : 
     346             : int
     347        4752 : MSTransportableControl::getRidingNumber() const {
     348        4752 :     return myRunningNumber - myWaitingUntilNumber - myWaitingForVehicleNumber - getMovingNumber();
     349             : }
     350             : 
     351             : int
     352        4752 : MSTransportableControl::getDepartedNumber() const {
     353        4752 :     return myLoadedNumber - myWaitingForDepartureNumber - myDiscardedNumber;
     354             : }
     355             : 
     356             : void
     357        4246 : MSTransportableControl::abortAnyWaitingForVehicle() {
     358        4575 :     for (const auto& it : myWaiting4Vehicle) {
     359         329 :         const MSEdge* edge = it.first;
     360       29662 :         for (MSTransportable* const p : it.second) {
     361       29333 :             edge->removeTransportable(p);
     362       29333 :             MSStageDriving* stage = dynamic_cast<MSStageDriving*>(p->getCurrentStage());
     363       29333 :             const std::string waitDescription = stage == nullptr ? "waiting" : stage->getWaitingDescription();
     364       87999 :             WRITE_WARNING(p->getObjectType() + " '" + p->getID() + "' aborted " + waitDescription + ".");
     365       29333 :             if (myAbortWaitingTimeout >= 0) {
     366           0 :                 p->setAbortWaiting(-1);
     367             :             }
     368       29333 :             erase(p);
     369             :         }
     370             :     }
     371             :     myWaiting4Vehicle.clear();
     372        4246 :     myWaitingForVehicleNumber = 0;
     373        4246 : }
     374             : 
     375             : void
     376         147 : MSTransportableControl::abortWaitingForVehicle(MSTransportable* t) {
     377         147 :     const MSEdge* edge = t->getEdge();
     378             :     auto it = myWaiting4Vehicle.find(edge);
     379         147 :     if (it != myWaiting4Vehicle.end()) {
     380         147 :         TransportableVector& waiting = it->second;
     381         147 :         auto it2 = std::find(waiting.begin(), waiting.end(), t);
     382         147 :         if (it2 != waiting.end()) {
     383         147 :             if (myAbortWaitingTimeout >= 0) {
     384          16 :                 (*it2)->setAbortWaiting(-1);
     385             :             }
     386             :             waiting.erase(it2);
     387             :         }
     388             :     }
     389         147 : }
     390             : 
     391             : void
     392          53 : MSTransportableControl::abortWaiting(MSTransportable* t) {
     393         106 :     for (std::map<SUMOTime, TransportableVector>::iterator it = myWaiting4Departure.begin(); it != myWaiting4Departure.end(); ++it) {
     394          53 :         TransportableVector& ts = it->second;
     395          53 :         TransportableVector::iterator it2 = std::find(ts.begin(), ts.end(), t);
     396          53 :         if (it2 != ts.end()) {
     397             :             ts.erase(it2);
     398             :         }
     399             :     }
     400          53 :     for (std::map<SUMOTime, TransportableVector>::iterator it = myWaitingUntil.begin(); it != myWaitingUntil.end(); ++it) {
     401           0 :         TransportableVector& ts = it->second;
     402           0 :         TransportableVector::iterator it2 = std::find(ts.begin(), ts.end(), t);
     403           0 :         if (it2 != ts.end()) {
     404             :             ts.erase(it2);
     405             :         }
     406             :     }
     407          53 : }
     408             : 
     409             : 
     410             : MSTransportable*
     411      292923 : MSTransportableControl::buildPerson(const SUMOVehicleParameter* pars, MSVehicleType* vtype, MSTransportable::MSTransportablePlan* plan,
     412             :                                     SumoRNG* rng) const {
     413      292923 :     const double speedFactor = vtype->computeChosenSpeedDeviation(rng);
     414      292923 :     return new MSPerson(pars, vtype, plan, speedFactor);
     415             : }
     416             : 
     417             : 
     418             : MSTransportable*
     419      138357 : MSTransportableControl::buildContainer(const SUMOVehicleParameter* pars, MSVehicleType* vtype, MSTransportable::MSTransportablePlan* plan) const {
     420      138357 :     return new MSTransportable(pars, vtype, plan, false);
     421             : }
     422             : 
     423             : 
     424             : void
     425          42 : MSTransportableControl::saveState(OutputDevice& out) {
     426          42 :     std::ostringstream oss;
     427         252 :     oss << myRunningNumber << " " << myLoadedNumber << " " << myEndedNumber << " " << myWaitingForDepartureNumber << " " << myArrivedNumber << " " << myDiscardedNumber;
     428         168 :     oss << " " << myJammedNumber << " " << myWaitingForVehicleNumber << " " << myWaitingUntilNumber << " " << myHaveNewWaiting;
     429          42 :     out.writeAttr(SUMO_ATTR_STATE, oss.str());
     430         105 :     for (const auto& it : myTransportables) {
     431          63 :         it.second->saveState(out);
     432             :     }
     433          42 : }
     434             : 
     435             : 
     436             : void
     437          48 : MSTransportableControl::loadState(const std::string& state) {
     438          48 :     std::istringstream iss(state);
     439          48 :     iss >> myRunningNumber >> myLoadedNumber >> myEndedNumber >> myWaitingForDepartureNumber >> myArrivedNumber >> myDiscardedNumber;
     440          48 :     iss >> myJammedNumber >> myWaitingForVehicleNumber >> myWaitingUntilNumber >> myHaveNewWaiting;
     441          48 : }
     442             : 
     443             : void
     444        5603 : MSTransportableControl::clearState() {
     445       24967 :     for (std::map<std::string, MSTransportable*>::iterator i = myTransportables.begin(); i != myTransportables.end(); ++i) {
     446       19364 :         delete (*i).second;
     447             :     }
     448             :     myTransportables.clear();
     449             :     myWaiting4Vehicle.clear();
     450             :     myWaiting4Departure.clear();
     451             :     myWaitingUntil.clear();
     452        5603 :     myLoadedNumber = 0;
     453        5603 :     myDiscardedNumber = 0;
     454        5603 :     myRunningNumber = 0;
     455        5603 :     myJammedNumber = 0;
     456        5603 :     myWaitingForDepartureNumber = 0;
     457        5603 :     myWaitingForVehicleNumber = 0;
     458        5603 :     myWaitingUntilNumber = 0;
     459        5603 :     myEndedNumber = 0;
     460        5603 :     myArrivedNumber = 0;
     461        5603 :     myHaveNewWaiting = false;
     462        5603 :     if (myMovementModel != myNonInteractingModel) {
     463        3268 :         myMovementModel->clearState();
     464             :     }
     465        5603 :     myNonInteractingModel->clearState();
     466        5603 : }
     467             : 
     468             : /****************************************************************************/

Generated by: LCOV version 1.14