LCOV - code coverage report
Current view: top level - src/microsim - MSParkingArea.cpp (source / functions) Coverage Total Hit
Test: lcov.info Lines: 89.4 % 331 296
Test Date: 2026-03-02 16:00:03 Functions: 87.5 % 48 42

            Line data    Source code
       1              : /****************************************************************************/
       2              : // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
       3              : // Copyright (C) 2015-2026 German Aerospace Center (DLR) and others.
       4              : // This program and the accompanying materials are made available under the
       5              : // terms of the Eclipse Public License 2.0 which is available at
       6              : // https://www.eclipse.org/legal/epl-2.0/
       7              : // This Source Code may also be made available under the following Secondary
       8              : // Licenses when the conditions for such availability set forth in the Eclipse
       9              : // Public License 2.0 are satisfied: GNU General Public License, version 2
      10              : // or later which is available at
      11              : // https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
      12              : // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
      13              : /****************************************************************************/
      14              : /// @file    MSParkingArea.cpp
      15              : /// @author  Mirco Sturari
      16              : /// @author  Jakob Erdmann
      17              : /// @author  Mirko Barthauer
      18              : /// @date    Tue, 19.01.2016
      19              : ///
      20              : // A area where vehicles can park next to the road
      21              : /****************************************************************************/
      22              : #include <config.h>
      23              : 
      24              : #include <cassert>
      25              : #include <utils/common/WrappingCommand.h>
      26              : #include <utils/vehicle/SUMOVehicle.h>
      27              : #include <utils/geom/Position.h>
      28              : #include <utils/geom/GeomHelper.h>
      29              : #include <microsim/MSEventControl.h>
      30              : #include <microsim/MSNet.h>
      31              : #include <microsim/MSEdge.h>
      32              : #include <microsim/MSVehicle.h>
      33              : #include <microsim/MSVehicleType.h>
      34              : #include "MSLane.h"
      35              : #include <microsim/transportables/MSTransportable.h>
      36              : #include "MSParkingArea.h"
      37              : #include "MSGlobals.h"
      38              : #include <utils/common/MsgHandler.h>
      39              : 
      40              : //#define DEBUG_RESERVATIONS
      41              : //#define DEBUG_GET_LAST_FREE_POS
      42              : //#define DEBUG_COND2(obj) (obj.getID() == "v.3")
      43              : #define DEBUG_COND2(obj) (obj.isSelected())
      44              : 
      45              : 
      46              : // ===========================================================================
      47              : // method definitions
      48              : // ===========================================================================
      49        17406 : MSParkingArea::MSParkingArea(const std::string& id, const std::vector<std::string>& lines,
      50              :                              const std::vector<std::string>& badges, MSLane& lane,
      51              :                              double begPos, double endPos, int capacity, double width, double length,
      52              :                              double angle, const std::string& name, bool onRoad,
      53        17406 :                              const std::string& departPos, bool lefthand, bool reservable) :
      54              :     MSStoppingPlace(id, SUMO_TAG_PARKING_AREA, lines, lane, begPos, endPos, name),
      55        17406 :     myRoadSideCapacity(capacity),
      56        17406 :     myCapacity(0),
      57        17406 :     myOnRoad(onRoad),
      58        17406 :     myReservable(reservable),
      59        17406 :     myWidth(width),
      60        17406 :     myLength(length),
      61        17406 :     myAngle(lefthand ? -angle : angle),
      62        17406 :     myAcceptedBadges(badges.begin(), badges.end()),
      63        17406 :     myEgressBlocked(false),
      64        17406 :     myReservationTime(-1),
      65        17406 :     myLastReservationTime(-1),
      66        17406 :     myReservations(0),
      67        17406 :     myLastReservations(0),
      68        17406 :     myReservationMaxLength(0),
      69        17406 :     myLastReservationMaxLength(0),
      70        17406 :     myMaxVehLength(0),
      71        17406 :     myNumAlternatives(0),
      72        17406 :     myLastStepOccupancy(0),
      73        17406 :     myDepartPos(-1),
      74        17406 :     myDepartPosDefinition(DepartPosDefinition::DEFAULT),
      75        34826 :     myUpdateEvent(nullptr) {
      76              :     // initialize unspecified defaults
      77        17406 :     if (myWidth == 0) {
      78        15048 :         myWidth = SUMO_const_laneWidth;
      79              :     }
      80              : 
      81        17406 :     if (departPos != "") {
      82              :         std::string error;
      83           60 :         if (!SUMOVehicleParameter::parseDepartPos(departPos, toString(myElement), getID(), myDepartPos, myDepartPosDefinition, error)) {
      84            0 :             throw ProcessError(error);
      85              :         }
      86           30 :         if (myDepartPosDefinition != DepartPosDefinition::GIVEN) {
      87              :             // maybe allow other methods at a later time
      88            0 :             throw ProcessError(TLF("Only a numerical departPos is supported for % '%'", toString(myElement), getID()));
      89           30 :         } else if (myDepartPos < 0 || myDepartPos > lane.getLength()) {
      90            0 :             throw ProcessError(TLF("Invalid departPos for % '%'", toString(myElement), getID()));
      91              :         }
      92              :     }
      93              : 
      94        17406 :     const double offset = (MSGlobals::gLefthand != lefthand) ? -1 : 1;
      95        34812 :     myShape = lane.getShape().getSubpart(
      96              :                   lane.interpolateLanePosToGeometryPos(begPos),
      97              :                   lane.interpolateLanePosToGeometryPos(endPos));
      98        17406 :     if (!myOnRoad) {
      99        17266 :         myShape.move2side((lane.getWidth() / 2. + myWidth / 2.) * offset);
     100              :     }
     101        17406 :     setRoadsideCapacity(capacity);
     102        17406 : }
     103              : 
     104              : 
     105        51228 : MSParkingArea::~MSParkingArea() {}
     106              : 
     107              : 
     108              : void
     109        54124 : MSParkingArea::addLotEntry(double x, double y, double z, double width, double length, double angle, double slope) {
     110              :     // create LotSpaceDefinition
     111        54124 :     LotSpaceDefinition lsd((int)mySpaceOccupancies.size(), nullptr, x, y, z, angle, slope, width, length);
     112              :     // If we are modelling parking set the end position to the lot position relative to the lane
     113              :     // rather than the end of the parking area - this results in vehicles stopping nearer the space
     114              :     // and re-entering the lane nearer the space. (If we are not modelling parking the vehicle will usually
     115              :     // enter the space and re-enter at the end of the parking area.)
     116        54124 :     if (MSGlobals::gModelParkingManoeuver) {
     117           30 :         const double offset = this->getLane().getShape().nearest_offset_to_point2D(lsd.position);
     118           30 :         if (offset <  getBeginLanePosition()) {
     119            0 :             lsd.endPos =  getBeginLanePosition() + POSITION_EPS;
     120              :         } else {
     121           30 :             if (this->getLane().getLength() > offset) {
     122           30 :                 lsd.endPos = offset;
     123              :             } else {
     124            0 :                 lsd.endPos = this->getLane().getLength() - POSITION_EPS;
     125              :             }
     126              :         }
     127              :         // Work out the angle of the lot relative to the lane  (-90 adjusts for the way the bay is drawn )
     128           30 :         double relativeAngle = fmod(lsd.rotation - 90., 360) - fmod(RAD2DEG(this->getLane().getShape().rotationAtOffset(lsd.endPos)), 360) + 0.5;
     129           30 :         if (relativeAngle < 0.) {
     130           10 :             relativeAngle += 360.;
     131              :         }
     132           30 :         lsd.manoeuverAngle = relativeAngle;
     133              : 
     134              :         // if p2.y is -ve the lot is on LHS of lane relative to lane direction
     135              :         // we need to know this because it inverts the complexity of the parking manoeuver
     136           30 :         Position p2 = this->getLane().getShape().transformToVectorCoordinates(lsd.position);
     137           30 :         if (p2.y() < (0. + POSITION_EPS)) {
     138           30 :             lsd.sideIsLHS = true;
     139              :         } else {
     140            0 :             lsd.sideIsLHS = false;
     141              :         }
     142              :     } else {
     143        54094 :         lsd.endPos = myEndPos;
     144        54094 :         lsd.manoeuverAngle = int(angle); // unused unless gModelParkingManoeuver is true
     145        54094 :         lsd.sideIsLHS = true;
     146              :     }
     147        54124 :     mySpaceOccupancies.push_back(lsd);
     148        54124 :     myCapacity++;
     149        54124 :     computeLastFreePos();
     150        54124 : }
     151              : 
     152              : int
     153           30 : MSParkingArea::getLastFreeLotAngle() const {
     154              :     assert(myLastFreeLot >= 0);
     155              :     assert(myLastFreeLot < (int)mySpaceOccupancies.size());
     156              : 
     157           30 :     const LotSpaceDefinition& lsd = mySpaceOccupancies[myLastFreeLot];
     158           30 :     if (lsd.sideIsLHS) {
     159           30 :         return abs(int(lsd.manoeuverAngle)) % 180;
     160              :     } else {
     161            0 :         return abs(abs(int(lsd.manoeuverAngle)) % 180 - 180) % 180;
     162              :     }
     163              : }
     164              : 
     165              : double
     166           30 : MSParkingArea::getLastFreeLotGUIAngle() const {
     167              :     assert(myLastFreeLot >= 0);
     168              :     assert(myLastFreeLot < (int)mySpaceOccupancies.size());
     169              : 
     170           30 :     const LotSpaceDefinition& lsd = mySpaceOccupancies[myLastFreeLot];
     171           30 :     if (lsd.manoeuverAngle > 180.) {
     172           15 :         return DEG2RAD(lsd.manoeuverAngle - 360.);
     173              :     } else {
     174           15 :         return DEG2RAD(lsd.manoeuverAngle);
     175              :     }
     176              : }
     177              : 
     178              : 
     179              : double
     180      2719074 : MSParkingArea::getLastFreePos(const SUMOVehicle& forVehicle, double brakePos) const {
     181      2719074 :     if (myCapacity == (int)myEndPositions.size()) {
     182              :         // keep enough space so that  parking vehicles can leave
     183              : #ifdef DEBUG_GET_LAST_FREE_POS
     184              :         if (DEBUG_COND2(forVehicle)) {
     185              :             std::cout << SIMTIME << " getLastFreePos veh=" << forVehicle.getID() << " allOccupied\n";
     186              :         }
     187              : #endif
     188      1787531 :         return myLastFreePos - forVehicle.getVehicleType().getMinGap() - POSITION_EPS;
     189       931543 :     } else if (mustAdvance(forVehicle.getVClass())) {
     190              :         // vehicles cannot overtake so we must fill from the downstream end
     191       148505 :         int skipN = SIMSTEP == myReservationTime ? myReservations - 1 : 0;
     192              :         //std::cout << SIMTIME << " v=" << forVehicle.getID() << " t=" << SIMTIME << " resTime=" << STEPS2TIME(myReservationTime) << " myR=" << myReservations << " skip=" << skipN << " rV=" << toString(myReservedVehicles) << "\n";
     193       384186 :         for (auto it_lsd = mySpaceOccupancies.rbegin(); it_lsd != mySpaceOccupancies.rend(); it_lsd++) {
     194       383944 :             if (it_lsd->vehicle == nullptr) {
     195       153858 :                 if (skipN > 0) {
     196              :                     // skip reservations
     197         5595 :                     skipN--;
     198         5595 :                     continue;
     199              :                 }
     200              : #ifdef DEBUG_GET_LAST_FREE_POS
     201              :                 if (DEBUG_COND2(forVehicle)) {
     202              :                     std::cout << SIMTIME << " getLastFreePos (onRoad-upstream) veh=" << forVehicle.getID() << " brakePos=" << brakePos << " myEndPos=" << myEndPos << " nextFreePos=" << it_lsd->endPos << "\n";
     203              :                 }
     204              : #endif
     205       148263 :                 return it_lsd->endPos;
     206              :             }
     207              :         }
     208              :         // should not happen
     209              :         return brakePos;
     210              :     } else {
     211       783038 :         const double minPos = MIN2(myEndPos, brakePos);
     212       783038 :         if (myLastFreePos >= minPos) {
     213              : #ifdef DEBUG_GET_LAST_FREE_POS
     214              :             if (DEBUG_COND2(forVehicle)) {
     215              :                 std::cout << SIMTIME << " getLastFreePos veh=" << forVehicle.getID() << " brakePos=" << brakePos << " myEndPos=" << myEndPos << " using myLastFreePos=" << myLastFreePos << "\n";
     216              :             }
     217              : #endif
     218              :             return myLastFreePos;
     219              :         } else {
     220              :             // find free pos after minPos
     221        58492 :             for (const auto& lsd : mySpaceOccupancies) {
     222        58289 :                 if (lsd.vehicle == nullptr && lsd.endPos >= minPos) {
     223              : #ifdef DEBUG_GET_LAST_FREE_POS
     224              :                     if (DEBUG_COND2(forVehicle)) {
     225              :                         std::cout << SIMTIME << " getLastFreePos veh=" << forVehicle.getID() << " brakePos=" << brakePos << " myEndPos=" << myEndPos << " nextFreePos=" << lsd.endPos << "\n";
     226              :                     }
     227              : #endif
     228              :                     return lsd.endPos;
     229              :                 }
     230              :             }
     231              :             // shouldn't happen. No good solution seems possible
     232              : #ifdef DEBUG_GET_LAST_FREE_POS
     233              :             if (DEBUG_COND2(forVehicle)) {
     234              :                 std::cout << SIMTIME << " getLastFreePos veh=" << forVehicle.getID() << " brakePos=" << brakePos << " myEndPos=" << myEndPos << " noGoodFreePos blockedAt=" << brakePos << "\n";
     235              :             }
     236              : #endif
     237              :             return brakePos;
     238              :         }
     239              :     }
     240              : }
     241              : 
     242              : bool
     243      1196266 : MSParkingArea::mustAdvance(SUMOVehicleClass svc) const {
     244      1196266 :     return myOnRoad && cannotChange(svc);
     245              : }
     246              : 
     247              : bool
     248       450635 : MSParkingArea::cannotChange(SUMOVehicleClass svc) const {
     249       450635 :     const MSLane* left = myLane.getParallelLane(1, false);
     250       450635 :     const MSLane* right = myLane.getParallelLane(-1, false);
     251        37499 :     return ((left == nullptr || !left->allowsVehicleClass(svc) || !myLane.allowsChangingLeft(svc))
     252       450635 :         && (right == nullptr || !right->allowsVehicleClass(svc) || !myLane.allowsChangingRight(svc)));
     253              : }
     254              : 
     255              : 
     256              : Position
     257        22057 : MSParkingArea::getVehiclePosition(const SUMOVehicle& forVehicle) const {
     258        51127 :     for (const auto& lsd : mySpaceOccupancies) {
     259        51127 :         if (lsd.vehicle == &forVehicle) {
     260        22057 :             return lsd.position;
     261              :         }
     262              :     }
     263            0 :     return Position::INVALID;
     264              : }
     265              : 
     266              : 
     267              : double
     268        56336 : MSParkingArea::getInsertionPosition(const SUMOVehicle& forVehicle) const {
     269        56336 :     if (myDepartPosDefinition == DepartPosDefinition::GIVEN) {
     270          250 :         return myDepartPos;
     271              :     }
     272       141108 :     for (const auto& lsd : mySpaceOccupancies) {
     273       141098 :         if (lsd.vehicle == &forVehicle) {
     274        56076 :             return lsd.endPos;
     275              :         }
     276              :     }
     277              :     return -1;
     278              : }
     279              : 
     280              : 
     281              : double
     282        15713 : MSParkingArea::getVehicleAngle(const SUMOVehicle& forVehicle) const {
     283        39332 :     for (const auto& lsd : mySpaceOccupancies) {
     284        39311 :         if (lsd.vehicle == &forVehicle) {
     285        15692 :             return (lsd.rotation - 90.) * (double) M_PI / (double) 180.0;
     286              :         }
     287              :     }
     288              :     return 0;
     289              : }
     290              : 
     291              : double
     292         3901 : MSParkingArea::getVehicleSlope(const SUMOVehicle& forVehicle) const {
     293        12511 :     for (const auto& lsd : mySpaceOccupancies) {
     294        12511 :         if (lsd.vehicle == &forVehicle) {
     295         3901 :             return lsd.slope;
     296              :         }
     297              :     }
     298              :     return 0;
     299              : }
     300              : 
     301              : double
     302           30 : MSParkingArea::getGUIAngle(const SUMOVehicle& forVehicle) const {
     303           60 :     for (const auto& lsd : mySpaceOccupancies) {
     304           60 :         if (lsd.vehicle == &forVehicle) {
     305           30 :             if (lsd.manoeuverAngle > 180.) {
     306           15 :                 return DEG2RAD(lsd.manoeuverAngle - 360.);
     307              :             } else {
     308           15 :                 return DEG2RAD(lsd.manoeuverAngle);
     309              :             }
     310              :         }
     311              :     }
     312              :     return 0.;
     313              : }
     314              : 
     315              : int
     316           30 : MSParkingArea::getManoeuverAngle(const SUMOVehicle& forVehicle) const {
     317           60 :     for (const auto& lsd : mySpaceOccupancies) {
     318           60 :         if (lsd.vehicle == &forVehicle) {
     319           30 :             if (lsd.sideIsLHS) {
     320           30 :                 return abs(int(lsd.manoeuverAngle)) % 180;
     321              :             } else {
     322            0 :                 return abs(abs(int(lsd.manoeuverAngle)) % 180 - 180) % 180;
     323              :             }
     324              :         }
     325              :     }
     326              :     return 0;
     327              : }
     328              : 
     329              : int
     330        41342 : MSParkingArea::getLotIndex(const SUMOVehicle* veh) const {
     331        41342 :     if (veh->getPositionOnLane() > myLastFreePos) {
     332              :         // vehicle has gone past myLastFreePos and we need to find the actual lot
     333              :         int closestLot = -1;
     334        19447 :         for (int i = 0; i < (int)mySpaceOccupancies.size(); i++) {
     335        19375 :             const LotSpaceDefinition lsd = mySpaceOccupancies[i];
     336        19375 :             if (lsd.vehicle == nullptr) {
     337              :                 closestLot = i;
     338        14165 :                 if (lsd.endPos >= veh->getPositionOnLane()) {
     339         5270 :                     return i;
     340              :                 }
     341              :             }
     342              :         }
     343           72 :         return closestLot;
     344              :     }
     345        36000 :     if (myOnRoad && myLastFreePos - veh->getPositionOnLane() > POSITION_EPS) {
     346              :         // for on-road parking we need to be precise
     347              :         return -1;
     348              :     }
     349         9216 :     return myLastFreeLot;
     350              : }
     351              : 
     352              : void
     353         9853 : MSParkingArea::enter(SUMOVehicle* veh, const bool /* parking */) {
     354         9853 :     removeSpaceReservation(veh);
     355         9853 :     double beg = veh->getPositionOnLane() + veh->getVehicleType().getMinGap();
     356         9853 :     double end = veh->getPositionOnLane() - veh->getVehicleType().getLength();
     357         9853 :     if (myUpdateEvent == nullptr) {
     358            0 :         myUpdateEvent = new WrappingCommand<MSParkingArea>(this, &MSParkingArea::updateOccupancy);
     359            0 :         MSNet::getInstance()->getEndOfTimestepEvents()->addEvent(myUpdateEvent);
     360              :     }
     361         9853 :     int lotIndex = getLotIndex(veh);
     362         9853 :     if (lotIndex < 0) {
     363            0 :         WRITE_WARNING("Unsuitable parking position for vehicle '" + veh->getID() + "' at parkingArea '" + getID() + "' time=" + time2string(SIMSTEP));
     364            0 :         lotIndex = myLastFreeLot;
     365              :     }
     366              : #ifdef DEBUG_GET_LAST_FREE_POS
     367              :     ((SUMOVehicleParameter&)veh->getParameter()).setParameter("lotIndex", toString(lotIndex));
     368              : #endif
     369              :     assert(myLastFreePos >= 0);
     370              :     assert(lotIndex < (int)mySpaceOccupancies.size());
     371         9853 :     mySpaceOccupancies[lotIndex].vehicle = veh;
     372         9853 :     myEndPositions[veh] = std::pair<double, double>(beg, end);
     373         9853 :     computeLastFreePos();
     374         9853 :     myMaxVehLength = MAX2(myMaxVehLength, veh->getLength());
     375              :     // current search ends here
     376         9853 :     veh->setNumberParkingReroutes(0);
     377         9853 : }
     378              : 
     379              : 
     380              : void
     381           30 : MSParkingArea::addSpaceReservation(const SUMOVehicle* veh) {
     382              :     myRemoteReservedVehicles.insert(veh);
     383           30 :     if (myUpdateEvent == nullptr) {
     384           25 :         myUpdateEvent = new WrappingCommand<MSParkingArea>(this, &MSParkingArea::updateOccupancy);
     385           25 :         MSNet::getInstance()->getEndOfTimestepEvents()->addEvent(myUpdateEvent);
     386              :     }
     387           30 : }
     388              : 
     389              : void
     390         9873 : MSParkingArea::removeSpaceReservation(const SUMOVehicle* veh) {
     391              :     myRemoteReservedVehicles.erase(veh);
     392         9873 :     if (myUpdateEvent == nullptr) {
     393         9088 :         myUpdateEvent = new WrappingCommand<MSParkingArea>(this, &MSParkingArea::updateOccupancy);
     394         9088 :         MSNet::getInstance()->getEndOfTimestepEvents()->addEvent(myUpdateEvent);
     395              :     }
     396         9873 : }
     397              : 
     398              : void
     399         8375 : MSParkingArea::leaveFrom(SUMOVehicle* what) {
     400              :     assert(myEndPositions.find(what) != myEndPositions.end());
     401         8375 :     if (myUpdateEvent == nullptr) {
     402         8097 :         myUpdateEvent = new WrappingCommand<MSParkingArea>(this, &MSParkingArea::updateOccupancy);
     403         8097 :         MSNet::getInstance()->getEndOfTimestepEvents()->addEvent(myUpdateEvent);
     404              :     }
     405        22234 :     for (auto& lsd : mySpaceOccupancies) {
     406        22234 :         if (lsd.vehicle == what) {
     407         8375 :             lsd.vehicle = nullptr;
     408         8375 :             break;
     409              :         }
     410              :     }
     411         8375 :     if (what->getLength() == myMaxVehLength) {
     412         8300 :         myMaxVehLength = 0;
     413        35163 :         for (auto item : myEndPositions) {
     414        53656 :             myMaxVehLength = MAX2(myMaxVehLength, item.first->getLength());
     415              :         }
     416              :     }
     417              :     myEndPositions.erase(myEndPositions.find(what));
     418         8375 :     computeLastFreePos();
     419         8375 : }
     420              : 
     421              : 
     422              : SUMOTime
     423        17210 : MSParkingArea::updateOccupancy(SUMOTime /* currentTime */) {
     424        17210 :     myLastStepOccupancy = getOccupancy();
     425              :     myLastRemoteReservedVehicles = myRemoteReservedVehicles;
     426        17210 :     myUpdateEvent = nullptr;
     427        17210 :     return 0;
     428              : }
     429              : 
     430              : 
     431            0 : MSParkingArea::LotSpaceDefinition::LotSpaceDefinition() :
     432            0 :     index(-1),
     433            0 :     vehicle(nullptr),
     434            0 :     rotation(0),
     435            0 :     slope(0),
     436            0 :     width(0),
     437            0 :     length(0),
     438            0 :     endPos(0),
     439            0 :     manoeuverAngle(0),
     440            0 :     sideIsLHS(false) {
     441            0 : }
     442              : 
     443              : 
     444        54124 : MSParkingArea::LotSpaceDefinition::LotSpaceDefinition(int index_, SUMOVehicle* vehicle_, double x, double y, double z, double rotation_, double slope_, double width_, double length_) :
     445        54124 :     index(index_),
     446        54124 :     vehicle(vehicle_),
     447              :     position(Position(x, y, z)),
     448        54124 :     rotation(rotation_),
     449        54124 :     slope(slope_),
     450        54124 :     width(width_),
     451        54124 :     length(length_),
     452        54124 :     endPos(0),
     453        54124 :     manoeuverAngle(0),
     454        54124 :     sideIsLHS(false) {
     455        54124 : }
     456              : 
     457              : 
     458              : void
     459       104113 : MSParkingArea::computeLastFreePos() {
     460       104113 :     myLastFreeLot = -1;
     461       104113 :     myLastFreePos = myBegPos;
     462       104113 :     myEgressBlocked = false;
     463       135782 :     for (auto& lsd : mySpaceOccupancies) {
     464       118137 :         if (lsd.vehicle == nullptr
     465       118137 :                 || (getOccupancy() == getCapacity()
     466        11585 :                     && lsd.vehicle->remainingStopDuration() <= 0
     467         1633 :                     && !lsd.vehicle->isStoppedTriggered())) {
     468        86468 :             if (lsd.vehicle == nullptr) {
     469        85553 :                 myLastFreeLot = lsd.index;
     470        85553 :                 myLastFreePos = lsd.endPos;
     471              :             } else {
     472              :                 // vehicle wants to exit the parking area
     473          915 :                 myLastFreeLot = lsd.index;
     474          915 :                 myLastFreePos = lsd.endPos - lsd.vehicle->getVehicleType().getLength() - POSITION_EPS;
     475          915 :                 myEgressBlocked = true;
     476              :             }
     477              :             break;
     478              :         } else {
     479        31669 :             myLastFreePos = MIN2(myLastFreePos,
     480        31669 :                                  lsd.endPos - lsd.vehicle->getVehicleType().getLength() - NUMERICAL_EPS);
     481              :         }
     482              :     }
     483       104113 : }
     484              : 
     485              : 
     486              : double
     487      1632209 : MSParkingArea::getLastFreePosWithReservation(SUMOTime t, const SUMOVehicle& forVehicle, double brakePos) {
     488              :     // do not perform reservation when far away
     489      1632209 :     if (forVehicle.getLane() != &myLane || forVehicle.getPositionOnLane() < (myBegPos - myMaxVehLength - forVehicle.getVehicleType().getMinGap())) {
     490              :         // for different lanes, do not consider reservations to avoid lane-order
     491              :         // dependency in parallel simulation
     492              : #ifdef DEBUG_RESERVATIONS
     493              :         if (DEBUG_COND2(forVehicle)) {
     494              :             std::cout << SIMTIME << " pa=" << getID() << " freePosRes veh=" << forVehicle.getID() << " other lane\n";
     495              :         }
     496              : #endif
     497      1422665 :         if (myNumAlternatives > 0 && getOccupancy() == getCapacity()) {
     498              :             // ensure that the vehicle reaches the rerouter lane
     499       175947 :             if (mySpaceOccupancies.size() > 0) {
     500              :                 assert(mySpaceOccupancies[0].vehicle != nullptr);
     501       175094 :                 const double waitPos = (mySpaceOccupancies[0].endPos
     502       175094 :                                         - mySpaceOccupancies[0].vehicle->getLength()
     503       175094 :                                         - forVehicle.getVehicleType().getMinGap()
     504       175094 :                                         - NUMERICAL_EPS);
     505       175094 :                 return MAX2(waitPos, MIN2(POSITION_EPS, myEndPos));
     506              :             } else {
     507          853 :                 return MAX2(myBegPos, MIN2(POSITION_EPS, myEndPos));
     508              :             }
     509              :         } else {
     510              :             // check if there is a reservation from the last time step
     511              :             // (this could also be in myReserations, if myLane wasn't processed before the forVehicle-lane)
     512      1246718 :             const SUMOTime last = t - DELTA_T;
     513              : #ifdef DEBUG_RESERVATIONS
     514              :             if (DEBUG_COND2(forVehicle)) {
     515              :                 std::cout << SIMTIME << " last=" << time2string(last) << " lastRes=" << time2string(myLastReservationTime) << " resTime=" << toString(myReservationTime) << "\n";
     516              :             }
     517              : #endif
     518      1246718 :             if (myLastReservationTime == last || myReservationTime == last) {
     519       839907 :                 int res = myLastReservationTime == last ? myLastReservations : myReservations;
     520       839907 :                 if (myCapacity <= getOccupancy() + res) {
     521       810896 :                     double maxLen = myLastReservationTime == last ? myLastReservationMaxLength : myReservationMaxLength;
     522              : #ifdef DEBUG_RESERVATIONS
     523              :                     if (DEBUG_COND2(forVehicle)) std::cout << SIMTIME << " pa=" << getID() << " freePosRes veh=" << forVehicle.getID()
     524              :                                                                << " lastRes=" << res << " resTime=" << myReservationTime << " reserved full, maxLen=" << maxLen << " endPos=" << mySpaceOccupancies[0].endPos << "\n";
     525              : #endif
     526       810896 :                     return (mySpaceOccupancies[0].endPos
     527       810896 :                             - maxLen
     528       810896 :                             - forVehicle.getVehicleType().getMinGap()
     529       810896 :                             - NUMERICAL_EPS);
     530              :                 }
     531              :             }
     532       435822 :             return getLastFreePos(forVehicle, brakePos);
     533              :         }
     534              :     }
     535       209544 :     if (t > myReservationTime) {
     536              : #ifdef DEBUG_RESERVATIONS
     537              :         if (DEBUG_COND2(forVehicle)) {
     538              :             std::cout << SIMTIME << " pa=" << getID() << " freePosRes veh=" << forVehicle.getID() << " first reservation\n";
     539              :         }
     540              : #endif
     541       161359 :         myLastReservationTime = myReservationTime;
     542       161359 :         myLastReservations = myReservations;
     543       161359 :         myLastReservationMaxLength = myReservationMaxLength;
     544       161359 :         myReservationTime = t;
     545       161359 :         myReservations = 1;
     546       161359 :         myReservationMaxLength = forVehicle.getVehicleType().getLength();
     547              :         myReservedVehicles.clear();
     548       161359 :         myReservedVehicles.insert(&forVehicle);
     549       779570 :         for (const auto& lsd : mySpaceOccupancies) {
     550       618211 :             if (lsd.vehicle != nullptr) {
     551       682802 :                 myReservationMaxLength = MAX2(myReservationMaxLength, lsd.vehicle->getVehicleType().getLength());
     552              :             }
     553              :         }
     554       161359 :         return getLastFreePos(forVehicle, brakePos);
     555              :     } else {
     556        48185 :         if (myCapacity > getOccupancy() + myReservations) {
     557              : #ifdef DEBUG_RESERVATIONS
     558              :             if (DEBUG_COND2(forVehicle)) {
     559              :                 std::cout << SIMTIME << " pa=" << getID() << " freePosRes veh=" << forVehicle.getID() << " res=" << myReservations << " enough space\n";
     560              :             }
     561              : #endif
     562         9561 :             myReservations++;
     563         9561 :             myReservationMaxLength = MAX2(myReservationMaxLength, forVehicle.getVehicleType().getLength());
     564         9561 :             myReservedVehicles.insert(&forVehicle);
     565         9561 :             return getLastFreePos(forVehicle, brakePos);
     566              :         } else {
     567        38624 :             if (myCapacity == 0) {
     568            0 :                 return getLastFreePos(forVehicle, brakePos);
     569              :             } else {
     570              : #ifdef DEBUG_RESERVATIONS
     571              :                 if (DEBUG_COND2(forVehicle)) std::cout << SIMTIME << " pa=" << getID() << " freePosRes veh=" << forVehicle.getID()
     572              :                                                            << " res=" << myReservations << " resTime=" << myReservationTime << " reserved full, maxLen=" << myReservationMaxLength << " endPos=" << mySpaceOccupancies[0].endPos << "\n";
     573              : #endif
     574        38624 :                 return (mySpaceOccupancies[0].endPos
     575        38624 :                         - myReservationMaxLength
     576        38624 :                         - forVehicle.getVehicleType().getMinGap()
     577        38624 :                         - NUMERICAL_EPS);
     578              :             }
     579              :         }
     580              :     }
     581              : }
     582              : 
     583              : 
     584              : double
     585          655 : MSParkingArea::getWidth() const {
     586          655 :     return myWidth;
     587              : }
     588              : 
     589              : 
     590              : double
     591          655 : MSParkingArea::getLength() const {
     592          655 :     return myLength;
     593              : }
     594              : 
     595              : 
     596              : double
     597          655 : MSParkingArea::getAngle() const {
     598          655 :     return myAngle;
     599              : }
     600              : 
     601              : 
     602              : int
     603      1497547 : MSParkingArea::getCapacity() const {
     604      1497547 :     return myCapacity;
     605              : }
     606              : 
     607              : 
     608              : bool
     609      1337469 : MSParkingArea::parkOnRoad() const {
     610      1337469 :     return myOnRoad;
     611              : }
     612              : 
     613              : 
     614              : int
     615      1972670 : MSParkingArea::getOccupancy() const {
     616      1972670 :     return (int)myEndPositions.size() - (myEgressBlocked ? 1 : 0);
     617              : }
     618              : 
     619              : 
     620              : int
     621            5 : MSParkingArea::getOccupancyIncludingBlocked() const {
     622            5 :     return (int)myEndPositions.size();
     623              : }
     624              : 
     625              : int
     626       250787 : MSParkingArea::getOccupancyIncludingReservations(const SUMOVehicle* forVehicle) const {
     627              :     const bool reservedLocal = myReservedVehicles.count(forVehicle) != 0;
     628              :     const bool reservedRemote = myRemoteReservedVehicles.count(forVehicle) != 0;
     629              :     return ((int)myEndPositions.size()
     630       250787 :         + (reservedLocal ? 0 : myReservations)
     631       250787 :         + (reservedRemote ? 0 : myRemoteReservedVehicles.size()));
     632              : }
     633              : 
     634              : 
     635              : int
     636        96448 : MSParkingArea::getOccupancyIncludingRemoteReservations(const SUMOVehicle* forVehicle) const {
     637              :     const bool reservedRemote = myRemoteReservedVehicles.count(forVehicle) != 0;
     638        96448 :     return getOccupancy() + (int)myRemoteReservedVehicles.size() - (reservedRemote ? 1 : 0);
     639              : }
     640              : 
     641              : 
     642              : int
     643            0 : MSParkingArea::getLastStepOccupancy() const {
     644            0 :     return myLastStepOccupancy;
     645              : }
     646              : 
     647              : 
     648              : int
     649        93721 : MSParkingArea::getLastStepOccupancyIncludingRemoteReservations(const SUMOVehicle* forVehicle) const {
     650              :     const bool reservedRemote = myLastRemoteReservedVehicles.count(forVehicle) != 0;
     651        93721 :     return myLastStepOccupancy - (int)myLastRemoteReservedVehicles.size() + (reservedRemote ? 1 : 0);
     652              : }
     653              : 
     654              : 
     655              : void
     656            0 : MSParkingArea::accept(std::string badge) {
     657              :     myAcceptedBadges.insert(badge);
     658            0 : }
     659              : 
     660              : 
     661              : void
     662            0 : MSParkingArea::accept(std::vector<std::string> badges) {
     663              :     myAcceptedBadges.insert(badges.begin(), badges.end());
     664            0 : }
     665              : 
     666              : 
     667              : void
     668            0 : MSParkingArea::refuse(std::string badge) {
     669              :     myAcceptedBadges.erase(badge);
     670            0 : }
     671              : 
     672              : 
     673              : bool
     674       231409 : MSParkingArea::accepts(SUMOVehicle* veh) const {
     675       231409 :     if (myAcceptedBadges.size() == 0) {
     676              :         return true;
     677              :     } else {
     678         1656 :         std::vector<std::string> vehicleBadges = veh->getParkingBadges();
     679         1656 :         for (auto badge : vehicleBadges) {
     680              :             if (myAcceptedBadges.count(badge) != 0) {
     681              :                 return true;
     682              :             }
     683              :         }
     684          687 :         return false;
     685         1656 :     }
     686              : }
     687              : 
     688              : 
     689              : void
     690         1406 : MSParkingArea::notifyEgressBlocked() {
     691         1406 :     computeLastFreePos();
     692         1406 : }
     693              : 
     694              : 
     695              : int
     696            0 : MSParkingArea::getNumAlternatives() const {
     697            0 :     return myNumAlternatives;
     698              : }
     699              : 
     700              : 
     701              : void
     702        13581 : MSParkingArea::setNumAlternatives(int alternatives) {
     703        13581 :     myNumAlternatives = MAX2(myNumAlternatives, alternatives);
     704        13581 : }
     705              : 
     706              : 
     707              : std::vector<std::string>
     708           28 : MSParkingArea::getAcceptedBadges() const {
     709           28 :     std::vector<std::string> result(myAcceptedBadges.begin(), myAcceptedBadges.end());
     710           28 :     return result;
     711              : }
     712              : 
     713              : 
     714              : void
     715           10 : MSParkingArea::setAcceptedBadges(const std::vector<std::string>& badges) {
     716              :     myAcceptedBadges.clear();
     717              :     myAcceptedBadges.insert(badges.begin(), badges.end());
     718           10 : }
     719              : 
     720              : 
     721              : const std::vector<MSParkingArea::LotSpaceDefinition>&
     722           90 : MSParkingArea::getSpaceOccupancies() const {
     723           90 :     return mySpaceOccupancies;
     724              : }
     725              : 
     726              : 
     727              : const PositionVector&
     728            5 : MSParkingArea::getShape() const {
     729            5 :     return myShape;
     730              : }
     731              : 
     732              : 
     733              : void
     734        30355 : MSParkingArea::setRoadsideCapacity(int capacity) {
     735              :     // reinit parking lot generation process
     736        30355 :     myRoadSideCapacity = capacity;
     737              : 
     738              :     // Initialize space occupancies if there is a road-side capacity
     739              :     // The overall number of lots is fixed and each lot accepts one vehicle regardless of size
     740        30355 :     const double spaceDim = myRoadSideCapacity > 0 ? myLane.interpolateLanePosToGeometryPos((myEndPos - myBegPos) / myRoadSideCapacity) : 7.5;
     741        30355 :     const double spaceOffset = myRoadSideCapacity > 0 ? (myEndPos - myBegPos) / myRoadSideCapacity : 7.5;
     742        30355 :     if (myLength == 0) {
     743        14227 :         myLength = spaceDim;
     744              :     }
     745              :     mySpaceOccupancies.clear();
     746        30355 :     myCapacity = 0;
     747        83824 :     for (int i = 0; i < myRoadSideCapacity; ++i) {
     748              :         // calculate pos, angle and slope of parking lot space
     749        53469 :         const Position pos = GeomHelper::calculateLotSpacePosition(myShape, i, spaceDim, myAngle, myWidth, myLength);
     750        53469 :         double spaceAngle = GeomHelper::calculateLotSpaceAngle(myShape, i, spaceDim, myAngle);
     751        53469 :         double spaceSlope = GeomHelper::calculateLotSpaceSlope(myShape, i, spaceDim);
     752              :         // add lotEntry
     753        53469 :         addLotEntry(pos.x(), pos.y(), pos.z(), myWidth, myLength, spaceAngle, spaceSlope);
     754              :         // update endPos
     755       159122 :         mySpaceOccupancies.back().endPos = MIN2(myEndPos, myBegPos + MAX2(POSITION_EPS, spaceOffset * (i + 1)));
     756              :     }
     757              :     // recompute after modifying the last endPos
     758        30355 :     computeLastFreePos();
     759        30355 : }
     760              : 
     761              : /****************************************************************************/
        

Generated by: LCOV version 2.0-1