LCOV - code coverage report
Current view: top level - src/microsim - MSVehicleTransfer.cpp (source / functions) Coverage Total Hit
Test: lcov.info Lines: 98.3 % 120 118
Test Date: 2024-10-24 15:46:30 Functions: 100.0 % 11 11

            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    MSVehicleTransfer.cpp
      15              : /// @author  Daniel Krajzewicz
      16              : /// @author  Jakob Erdmann
      17              : /// @author  Michael Behrisch
      18              : /// @date    Sep 2003
      19              : ///
      20              : // A mover of vehicles that got stucked due to grid locks
      21              : /****************************************************************************/
      22              : #include <config.h>
      23              : 
      24              : #include <iostream>
      25              : #include <utils/common/MsgHandler.h>
      26              : #include <utils/xml/SUMOSAXAttributes.h>
      27              : #include "MSNet.h"
      28              : #include "MSLane.h"
      29              : #include "MSEdge.h"
      30              : #include "MSVehicle.h"
      31              : #include "MSParkingArea.h"
      32              : #include <microsim/lcmodels/MSAbstractLaneChangeModel.h>
      33              : #include "MSVehicleControl.h"
      34              : #include "MSInsertionControl.h"
      35              : #include "MSVehicleTransfer.h"
      36              : 
      37              : 
      38              : // ===========================================================================
      39              : // static member definitions
      40              : // ===========================================================================
      41              : MSVehicleTransfer* MSVehicleTransfer::myInstance = nullptr;
      42              : const double MSVehicleTransfer::TeleportMinSpeed = 1;
      43              : 
      44              : 
      45              : // ===========================================================================
      46              : // member method definitions
      47              : // ===========================================================================
      48              : bool
      49     36196887 : MSVehicleTransfer::VehicleInformation::operator<(const VehicleInformation& v2) const {
      50     36196887 :     return myVeh->getNumericalID() < v2.myVeh->getNumericalID();
      51              : }
      52              : 
      53              : 
      54              : void
      55        21683 : MSVehicleTransfer::add(const SUMOTime t, MSVehicle* veh) {
      56        21683 :     const bool jumping = veh->isJumping();
      57        21683 :     const SUMOTime proceed = jumping ? t + veh->getPastStops().back().jump : -1;
      58        21683 :     if (veh->isParking()) {
      59        12496 :         veh->getLaneChangeModel().endLaneChangeManeuver(MSMoveReminder::NOTIFICATION_PARKING);
      60        12496 :         MSNet::getInstance()->informVehicleStateListener(veh, MSNet::VehicleState::STARTING_PARKING);
      61        12496 :         veh->onRemovalFromNet(MSMoveReminder::NOTIFICATION_PARKING);
      62              :     } else {
      63         9187 :         veh->getLaneChangeModel().endLaneChangeManeuver(MSMoveReminder::NOTIFICATION_TELEPORT);
      64         9187 :         MSNet::getInstance()->informVehicleStateListener(veh, MSNet::VehicleState::STARTING_TELEPORT);
      65         9187 :         if (veh->succEdge(1) == nullptr) {
      66         7125 :             WRITE_WARNINGF(TL("Vehicle '%' teleports beyond arrival edge '%', time=%."), veh->getID(), veh->getEdge()->getID(), time2string(t));
      67         2375 :             veh->onRemovalFromNet(MSMoveReminder::NOTIFICATION_TELEPORT_ARRIVED);
      68         2375 :             MSNet::getInstance()->getVehicleControl().scheduleVehicleRemoval(veh);
      69         2375 :             return;
      70              :         }
      71         6812 :         veh->onRemovalFromNet(MSMoveReminder::NOTIFICATION_TELEPORT);
      72         6812 :         veh->enterLaneAtMove(veh->succEdge(1)->getLanes()[0], true);
      73              :     }
      74        19308 :     myVehicles.push_back(VehicleInformation(t, veh, proceed, veh->isParking(), jumping));
      75              : }
      76              : 
      77              : 
      78              : void
      79      2545279 : MSVehicleTransfer::remove(MSVehicle* veh) {
      80              :     auto& vehInfos = myVehicles.getContainer();
      81      3314739 :     for (auto i = vehInfos.begin(); i != vehInfos.end(); ++i) {
      82       769476 :         if (i->myVeh == veh) {
      83           16 :             if (i->myParking) {
      84           16 :                 veh->getMutableLane()->removeParking(veh);
      85              :             }
      86              :             vehInfos.erase(i);
      87           16 :             break;
      88              :         }
      89              :     }
      90              :     myVehicles.unlock();
      91      2545279 : }
      92              : 
      93              : 
      94              : void
      95     82314054 : MSVehicleTransfer::checkInsertions(SUMOTime time) {
      96              :     // go through vehicles
      97              :     auto& vehInfos = myVehicles.getContainer();
      98     82314054 :     std::sort(vehInfos.begin(), vehInfos.end());
      99     90257009 :     for (auto i = vehInfos.begin(); i != vehInfos.end();) {
     100              :         // vehicle information cannot be const because we need to assign the proceed time
     101              :         VehicleInformation& desc = *i;
     102              : 
     103      7942955 :         if (desc.myParking) {
     104              :             // handle parking vehicles
     105      7535716 :             if (time != desc.myTransferTime) {
     106              :                 // avoid calling processNextStop twice in the transfer step
     107      7523220 :                 const MSLane* lane = desc.myVeh->getLane();
     108              :                 // lane must be locked because pedestrians may be added in during stop processing while existing passengers are being drawn simultaneously
     109      7523220 :                 if (lane != nullptr) {
     110      7523220 :                     lane->getVehiclesSecure();
     111              :                 }
     112      7523220 :                 desc.myVeh->processNextStop(1);
     113      7523220 :                 desc.myVeh->updateParkingState();
     114      7523220 :                 if (lane != nullptr) {
     115      7523220 :                     lane->releaseVehicles();
     116              :                 }
     117              :             }
     118      7535716 :             if (desc.myVeh->keepStopping(true)) {
     119              :                 i++;
     120      7452136 :                 continue;
     121              :             }
     122              :             // parking finished, head back into traffic
     123              :         }
     124       490819 :         const SUMOVehicleClass vclass = desc.myVeh->getVehicleType().getVehicleClass();
     125       490819 :         const MSEdge* e = desc.myVeh->getEdge();
     126       490819 :         const MSEdge* nextEdge = desc.myVeh->succEdge(1);
     127              : 
     128              : 
     129       490819 :         if (desc.myParking) {
     130        83580 :             MSParkingArea* pa = desc.myVeh->getCurrentParkingArea();
     131        83580 :             const double departPos = pa != nullptr ? pa->getInsertionPosition(*desc.myVeh) : desc.myVeh->getPositionOnLane();
     132              :             // handle parking vehicles
     133        83580 :             desc.myVeh->setIdling(true);
     134        83580 :             if (desc.myVeh->getMutableLane()->isInsertionSuccess(desc.myVeh, 0, departPos, desc.myVeh->getLateralPositionOnLane(),
     135              :                     false, MSMoveReminder::NOTIFICATION_PARKING)) {
     136         9163 :                 MSNet::getInstance()->informVehicleStateListener(desc.myVeh, MSNet::VehicleState::ENDING_PARKING);
     137         9163 :                 desc.myVeh->getMutableLane()->removeParking(desc.myVeh);
     138              :                 // at this point we are in the lane, blocking traffic & if required we configure the exit manoeuvre
     139         9163 :                 if (MSGlobals::gModelParkingManoeuver && desc.myVeh->setExitManoeuvre()) {
     140           64 :                     MSNet::getInstance()->informVehicleStateListener(desc.myVeh, MSNet::VehicleState::MANEUVERING);
     141              :                 }
     142         9163 :                 desc.myVeh->setIdling(false);
     143              :                 i = vehInfos.erase(i);
     144              :             } else {
     145              :                 // blocked from entering the road - engine assumed to be idling.
     146        74417 :                 desc.myVeh->workOnIdleReminders();
     147        74417 :                 if (!desc.myVeh->signalSet(MSVehicle::VEH_SIGNAL_BLINKER_LEFT | MSVehicle::VEH_SIGNAL_BLINKER_RIGHT)) {
     148              :                     // signal wish to re-enter the road
     149         1449 :                     desc.myVeh->switchOnSignal(MSGlobals::gLefthand ? MSVehicle::VEH_SIGNAL_BLINKER_RIGHT : MSVehicle::VEH_SIGNAL_BLINKER_LEFT);
     150         1449 :                     if (pa) {
     151              :                         // update freePosition so other vehicles can help with insertion
     152         1113 :                         desc.myVeh->getCurrentParkingArea()->notifyEgressBlocked();
     153              :                     }
     154              :                 }
     155              :                 i++;
     156              :             }
     157       407239 :         } else if (desc.myJumping && desc.myProceedTime > time) {
     158              :             ++i;
     159              :         } else {
     160              :             const double departPos = 0;
     161              :             // get the lane on which this vehicle should continue
     162              :             // first select all the lanes which allow continuation onto nextEdge
     163              :             //   then pick the one which is least occupied
     164       406225 :             MSLane* l = (nextEdge != nullptr ? e->getFreeLane(e->allowedLanes(*nextEdge, vclass), vclass, departPos) :
     165        89740 :                          e->getFreeLane(nullptr, vclass, departPos));
     166              :             // handle teleporting vehicles, lane may be 0 because permissions were modified by a closing rerouter or TraCI
     167       406225 :             const bool busyBidi = l != nullptr && l->getBidiLane() != nullptr && l->getBidiLane()->getVehicleNumberWithPartials() > 0;
     168       810510 :             if (l != nullptr && !busyBidi && l->freeInsertion(*(desc.myVeh), MIN2(l->getSpeedLimit(), desc.myVeh->getMaxSpeed()), 0, MSMoveReminder::NOTIFICATION_TELEPORT)) {
     169         6405 :                 if (!desc.myJumping) {
     170        24976 :                     WRITE_WARNINGF(TL("Vehicle '%' ends teleporting on edge '%', time=%."), desc.myVeh->getID(), e->getID(), time2string(time));
     171              :                 }
     172        12810 :                 MSNet::getInstance()->informVehicleStateListener(desc.myVeh, MSNet::VehicleState::ENDING_TELEPORT);
     173              :                 i = vehInfos.erase(i);
     174       399820 :             } else if (desc.myJumping) {
     175              :                 // try again later
     176              :                 ++i;
     177              :             } else {
     178              :                 // vehicle is visible while show-route is active. Make its state more obvious
     179       398525 :                 desc.myVeh->computeAngle();
     180       398525 :                 desc.myVeh->setLateralPositionOnLane(-desc.myVeh->getLane()->getWidth() / 2);
     181       398525 :                 desc.myVeh->invalidateCachedPosition();
     182              :                 // could not insert. maybe we should proceed in virtual space
     183       398525 :                 if (desc.myProceedTime < 0) {
     184              :                     // initialize proceed time (delayed to avoid lane-order dependency in executeMove)
     185         2633 :                     desc.myProceedTime = time + TIME2STEPS(e->getCurrentTravelTime(TeleportMinSpeed));
     186       395892 :                 } else if (desc.myProceedTime < time) {
     187        12285 :                     if (desc.myVeh->succEdge(1) == nullptr) {
     188         1124 :                         WRITE_WARNINGF(TL("Vehicle '%' teleports beyond arrival edge '%', time=%."), desc.myVeh->getID(), e->getID(), time2string(time));
     189          281 :                         desc.myVeh->leaveLane(MSMoveReminder::NOTIFICATION_TELEPORT_ARRIVED);
     190          281 :                         MSNet::getInstance()->getVehicleControl().scheduleVehicleRemoval(desc.myVeh);
     191              :                         i = vehInfos.erase(i);
     192          281 :                         continue;
     193              :                     }
     194              :                     // let the vehicle move to the next edge
     195        12004 :                     desc.myVeh->leaveLane(MSMoveReminder::NOTIFICATION_TELEPORT_CONTINUATION);
     196              :                     // active move reminders (i.e. rerouters)
     197        12004 :                     const std::vector<MSLane*>* allowedLanes = nextEdge->allowedLanes(vclass);
     198        24008 :                     MSLane* laneToEnter = (allowedLanes != nullptr) ? allowedLanes->at(0) : nextEdge->getLanes()[0];
     199        12004 :                     desc.myVeh->enterLaneAtMove(laneToEnter, true);
     200              :                     // use current travel time to determine when to move the vehicle forward
     201        12004 :                     desc.myProceedTime = time + TIME2STEPS(e->getCurrentTravelTime(TeleportMinSpeed));
     202              :                 }
     203              :                 ++i;
     204              :             }
     205              :         }
     206              :     }
     207              :     myVehicles.unlock();
     208     82314054 : }
     209              : 
     210              : 
     211              : MSVehicleTransfer*
     212     84921855 : MSVehicleTransfer::getInstance() {
     213     84921855 :     if (myInstance == nullptr) {
     214        40046 :         myInstance = new MSVehicleTransfer();
     215              :     }
     216     84921855 :     return myInstance;
     217              : }
     218              : 
     219              : 
     220        40046 : MSVehicleTransfer::MSVehicleTransfer() : myVehicles(MSGlobals::gNumSimThreads > 1) {}
     221              : 
     222              : 
     223        80088 : MSVehicleTransfer::~MSVehicleTransfer() {
     224        40044 :     myInstance = nullptr;
     225        80088 : }
     226              : 
     227              : 
     228              : void
     229          424 : MSVehicleTransfer::saveState(OutputDevice& out) {
     230          609 :     for (const VehicleInformation& vehInfo : myVehicles.getContainer()) {
     231          185 :         out.openTag(SUMO_TAG_VEHICLETRANSFER);
     232          185 :         out.writeAttr(SUMO_ATTR_ID, vehInfo.myVeh->getID());
     233          185 :         out.writeAttr(SUMO_ATTR_DEPART, vehInfo.myProceedTime);
     234          185 :         if (vehInfo.myParking) {
     235          183 :             out.writeAttr(SUMO_ATTR_PARKING, vehInfo.myVeh->getLane()->getID());
     236              :         }
     237          185 :         if (vehInfo.myJumping) {
     238            0 :             out.writeAttr(SUMO_ATTR_JUMP, true);
     239              :         }
     240          370 :         out.closeTag();
     241              :     }
     242              :     myVehicles.unlock();
     243          424 : }
     244              : 
     245              : 
     246              : void
     247          186 : MSVehicleTransfer::clearState() {
     248          186 :     myVehicles.clear();
     249          186 : }
     250              : 
     251              : 
     252              : void
     253          185 : MSVehicleTransfer::loadState(const SUMOSAXAttributes& attrs, const SUMOTime offset, MSVehicleControl& vc) {
     254          185 :     MSVehicle* veh = dynamic_cast<MSVehicle*>(vc.getVehicle(attrs.getString(SUMO_ATTR_ID)));
     255          185 :     if (veh == nullptr) {
     256              :         // deleted
     257            0 :         return;
     258              :     }
     259          185 :     SUMOTime proceedTime = (SUMOTime)attrs.getLong(SUMO_ATTR_DEPART);
     260          185 :     MSLane* parkingLane = attrs.hasAttribute(SUMO_ATTR_PARKING) ? MSLane::dictionary(attrs.getString(SUMO_ATTR_PARKING)) : nullptr;
     261          185 :     bool ok = true;
     262          185 :     const bool jumping = attrs.getOpt<bool>(SUMO_ATTR_JUMP, veh->getID().c_str(), ok, false);
     263          185 :     myVehicles.push_back(VehicleInformation(-1, veh, proceedTime - offset, parkingLane != nullptr, jumping));
     264          185 :     if (parkingLane != nullptr) {
     265          183 :         parkingLane->addParking(veh);
     266          183 :         veh->setTentativeLaneAndPosition(parkingLane, veh->getPositionOnLane());
     267          183 :         veh->processNextStop(veh->getSpeed());
     268              :     }
     269          185 :     MSNet::getInstance()->getInsertionControl().alreadyDeparted(veh);
     270              : }
     271              : 
     272              : 
     273              : /****************************************************************************/
        

Generated by: LCOV version 2.0-1