LCOV - code coverage report
Current view: top level - src/microsim - MSParkingArea.cpp (source / functions) Coverage Total Hit
Test: lcov.info Lines: 89.7 % 300 269
Test Date: 2025-12-06 15:35:27 Functions: 88.1 % 42 37

            Line data    Source code
       1              : /****************************************************************************/
       2              : // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
       3              : // Copyright (C) 2015-2025 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/MSVehicle.h>
      32              : #include <microsim/MSVehicleType.h>
      33              : #include "MSLane.h"
      34              : #include <microsim/transportables/MSTransportable.h>
      35              : #include "MSParkingArea.h"
      36              : #include "MSGlobals.h"
      37              : #include <utils/common/MsgHandler.h>
      38              : 
      39              : //#define DEBUG_RESERVATIONS
      40              : //#define DEBUG_GET_LAST_FREE_POS
      41              : //#define DEBUG_COND2(obj) (obj.getID() == "v.3")
      42              : #define DEBUG_COND2(obj) (obj.isSelected())
      43              : 
      44              : 
      45              : // ===========================================================================
      46              : // method definitions
      47              : // ===========================================================================
      48        14362 : MSParkingArea::MSParkingArea(const std::string& id, const std::vector<std::string>& lines,
      49              :                              const std::vector<std::string>& badges, MSLane& lane,
      50              :                              double begPos, double endPos, int capacity, double width, double length,
      51              :                              double angle, const std::string& name, bool onRoad,
      52        14362 :                              const std::string& departPos, bool lefthand) :
      53              :     MSStoppingPlace(id, SUMO_TAG_PARKING_AREA, lines, lane, begPos, endPos, name),
      54        14362 :     myRoadSideCapacity(capacity),
      55        14362 :     myCapacity(0),
      56        14362 :     myOnRoad(onRoad),
      57        14362 :     myWidth(width),
      58        14362 :     myLength(length),
      59        14362 :     myAngle(lefthand ? -angle : angle),
      60        14362 :     myAcceptedBadges(badges.begin(), badges.end()),
      61        14362 :     myEgressBlocked(false),
      62        14362 :     myReservationTime(-1),
      63        14362 :     myLastReservationTime(-1),
      64        14362 :     myReservations(0),
      65        14362 :     myLastReservations(0),
      66        14362 :     myReservationMaxLength(0),
      67        14362 :     myLastReservationMaxLength(0),
      68        14362 :     myMaxVehLength(0),
      69        14362 :     myNumAlternatives(0),
      70        14362 :     myLastStepOccupancy(0),
      71        14362 :     myDepartPos(-1),
      72        14362 :     myDepartPosDefinition(DepartPosDefinition::DEFAULT),
      73        28738 :     myUpdateEvent(nullptr) {
      74              :     // initialize unspecified defaults
      75        14362 :     if (myWidth == 0) {
      76        12004 :         myWidth = SUMO_const_laneWidth;
      77              :     }
      78              : 
      79        14362 :     if (departPos != "") {
      80              :         std::string error;
      81           60 :         if (!SUMOVehicleParameter::parseDepartPos(departPos, toString(myElement), getID(), myDepartPos, myDepartPosDefinition, error)) {
      82            0 :             throw ProcessError(error);
      83              :         }
      84           30 :         if (myDepartPosDefinition != DepartPosDefinition::GIVEN) {
      85              :             // maybe allow other methods at a later time
      86            0 :             throw ProcessError(TLF("Only a numerical departPos is supported for % '%'", toString(myElement), getID()));
      87           30 :         } else if (myDepartPos < 0 || myDepartPos > lane.getLength()) {
      88            0 :             throw ProcessError(TLF("Invalid departPos for % '%'", toString(myElement), getID()));
      89              :         }
      90              :     }
      91              : 
      92        14362 :     const double offset = (MSGlobals::gLefthand != lefthand) ? -1 : 1;
      93        28724 :     myShape = lane.getShape().getSubpart(
      94              :                   lane.interpolateLanePosToGeometryPos(begPos),
      95              :                   lane.interpolateLanePosToGeometryPos(endPos));
      96        14362 :     if (!myOnRoad) {
      97        14295 :         myShape.move2side((lane.getWidth() / 2. + myWidth / 2.) * offset);
      98              :     }
      99        14362 :     setRoadsideCapacity(capacity);
     100        14362 : }
     101              : 
     102              : 
     103        42152 : MSParkingArea::~MSParkingArea() {}
     104              : 
     105              : 
     106              : void
     107        50965 : MSParkingArea::addLotEntry(double x, double y, double z, double width, double length, double angle, double slope) {
     108              :     // create LotSpaceDefinition
     109        50965 :     LotSpaceDefinition lsd((int)mySpaceOccupancies.size(), nullptr, x, y, z, angle, slope, width, length);
     110              :     // If we are modelling parking set the end position to the lot position relative to the lane
     111              :     // rather than the end of the parking area - this results in vehicles stopping nearer the space
     112              :     // and re-entering the lane nearer the space. (If we are not modelling parking the vehicle will usually
     113              :     // enter the space and re-enter at the end of the parking area.)
     114        50965 :     if (MSGlobals::gModelParkingManoeuver) {
     115           30 :         const double offset = this->getLane().getShape().nearest_offset_to_point2D(lsd.position);
     116           30 :         if (offset <  getBeginLanePosition()) {
     117            0 :             lsd.endPos =  getBeginLanePosition() + POSITION_EPS;
     118              :         } else {
     119           30 :             if (this->getLane().getLength() > offset) {
     120           30 :                 lsd.endPos = offset;
     121              :             } else {
     122            0 :                 lsd.endPos = this->getLane().getLength() - POSITION_EPS;
     123              :             }
     124              :         }
     125              :         // Work out the angle of the lot relative to the lane  (-90 adjusts for the way the bay is drawn )
     126           30 :         double relativeAngle = fmod(lsd.rotation - 90., 360) - fmod(RAD2DEG(this->getLane().getShape().rotationAtOffset(lsd.endPos)), 360) + 0.5;
     127           30 :         if (relativeAngle < 0.) {
     128           10 :             relativeAngle += 360.;
     129              :         }
     130           30 :         lsd.manoeuverAngle = relativeAngle;
     131              : 
     132              :         // if p2.y is -ve the lot is on LHS of lane relative to lane direction
     133              :         // we need to know this because it inverts the complexity of the parking manoeuver
     134           30 :         Position p2 = this->getLane().getShape().transformToVectorCoordinates(lsd.position);
     135           30 :         if (p2.y() < (0. + POSITION_EPS)) {
     136           30 :             lsd.sideIsLHS = true;
     137              :         } else {
     138            0 :             lsd.sideIsLHS = false;
     139              :         }
     140              :     } else {
     141        50935 :         lsd.endPos = myEndPos;
     142        50935 :         lsd.manoeuverAngle = int(angle); // unused unless gModelParkingManoeuver is true
     143        50935 :         lsd.sideIsLHS = true;
     144              :     }
     145        50965 :     mySpaceOccupancies.push_back(lsd);
     146        50965 :     myCapacity++;
     147        50965 :     computeLastFreePos();
     148        50965 : }
     149              : 
     150              : int
     151           30 : MSParkingArea::getLastFreeLotAngle() const {
     152              :     assert(myLastFreeLot >= 0);
     153              :     assert(myLastFreeLot < (int)mySpaceOccupancies.size());
     154              : 
     155           30 :     const LotSpaceDefinition& lsd = mySpaceOccupancies[myLastFreeLot];
     156           30 :     if (lsd.sideIsLHS) {
     157           30 :         return abs(int(lsd.manoeuverAngle)) % 180;
     158              :     } else {
     159            0 :         return abs(abs(int(lsd.manoeuverAngle)) % 180 - 180) % 180;
     160              :     }
     161              : }
     162              : 
     163              : double
     164           30 : MSParkingArea::getLastFreeLotGUIAngle() const {
     165              :     assert(myLastFreeLot >= 0);
     166              :     assert(myLastFreeLot < (int)mySpaceOccupancies.size());
     167              : 
     168           30 :     const LotSpaceDefinition& lsd = mySpaceOccupancies[myLastFreeLot];
     169           30 :     if (lsd.manoeuverAngle > 180.) {
     170           15 :         return DEG2RAD(lsd.manoeuverAngle - 360.);
     171              :     } else {
     172           15 :         return DEG2RAD(lsd.manoeuverAngle);
     173              :     }
     174              : }
     175              : 
     176              : 
     177              : double
     178      2283455 : MSParkingArea::getLastFreePos(const SUMOVehicle& forVehicle, double brakePos) const {
     179      2283455 :     if (myCapacity == (int)myEndPositions.size()) {
     180              :         // keep enough space so that  parking vehicles can leave
     181              : #ifdef DEBUG_GET_LAST_FREE_POS
     182              :         if (DEBUG_COND2(forVehicle)) {
     183              :             std::cout << SIMTIME << " getLastFreePos veh=" << forVehicle.getID() << " allOccupied\n";
     184              :         }
     185              : #endif
     186      1546728 :         return myLastFreePos - forVehicle.getVehicleType().getMinGap() - POSITION_EPS;
     187              :     } else {
     188       736727 :         const double minPos = MIN2(myEndPos, brakePos);
     189       736727 :         if (myLastFreePos >= minPos) {
     190              : #ifdef DEBUG_GET_LAST_FREE_POS
     191              :             if (DEBUG_COND2(forVehicle)) {
     192              :                 std::cout << SIMTIME << " getLastFreePos veh=" << forVehicle.getID() << " brakePos=" << brakePos << " myEndPos=" << myEndPos << " using myLastFreePos=" << myLastFreePos << "\n";
     193              :             }
     194              : #endif
     195              :             return myLastFreePos;
     196              :         } else {
     197              :             // find free pos after minPos
     198        48296 :             for (const auto& lsd : mySpaceOccupancies) {
     199        48091 :                 if (lsd.vehicle == nullptr && lsd.endPos >= minPos) {
     200              : #ifdef DEBUG_GET_LAST_FREE_POS
     201              :                     if (DEBUG_COND2(forVehicle)) {
     202              :                         std::cout << SIMTIME << " getLastFreePos veh=" << forVehicle.getID() << " brakePos=" << brakePos << " myEndPos=" << myEndPos << " nextFreePos=" << lsd.endPos << "\n";
     203              :                     }
     204              : #endif
     205              :                     return lsd.endPos;
     206              :                 }
     207              :             }
     208              :             // shouldn't happen. No good solution seems possible
     209              : #ifdef DEBUG_GET_LAST_FREE_POS
     210              :             if (DEBUG_COND2(forVehicle)) {
     211              :                 std::cout << SIMTIME << " getLastFreePos veh=" << forVehicle.getID() << " brakePos=" << brakePos << " myEndPos=" << myEndPos << " noGoodFreePos blockedAt=" << brakePos << "\n";
     212              :             }
     213              : #endif
     214              :             return brakePos;
     215              :         }
     216              :     }
     217              : }
     218              : 
     219              : Position
     220        22601 : MSParkingArea::getVehiclePosition(const SUMOVehicle& forVehicle) const {
     221        50671 :     for (const auto& lsd : mySpaceOccupancies) {
     222        50671 :         if (lsd.vehicle == &forVehicle) {
     223        22601 :             return lsd.position;
     224              :         }
     225              :     }
     226            0 :     return Position::INVALID;
     227              : }
     228              : 
     229              : 
     230              : double
     231        50008 : MSParkingArea::getInsertionPosition(const SUMOVehicle& forVehicle) const {
     232        50008 :     if (myDepartPosDefinition == DepartPosDefinition::GIVEN) {
     233          250 :         return myDepartPos;
     234              :     }
     235       135942 :     for (const auto& lsd : mySpaceOccupancies) {
     236       135932 :         if (lsd.vehicle == &forVehicle) {
     237        49748 :             return lsd.endPos;
     238              :         }
     239              :     }
     240              :     return -1;
     241              : }
     242              : 
     243              : 
     244              : double
     245        15650 : MSParkingArea::getVehicleAngle(const SUMOVehicle& forVehicle) const {
     246        39622 :     for (const auto& lsd : mySpaceOccupancies) {
     247        39601 :         if (lsd.vehicle == &forVehicle) {
     248        15629 :             return (lsd.rotation - 90.) * (double) M_PI / (double) 180.0;
     249              :         }
     250              :     }
     251              :     return 0;
     252              : }
     253              : 
     254              : double
     255         3901 : MSParkingArea::getVehicleSlope(const SUMOVehicle& forVehicle) const {
     256        12511 :     for (const auto& lsd : mySpaceOccupancies) {
     257        12511 :         if (lsd.vehicle == &forVehicle) {
     258         3901 :             return lsd.slope;
     259              :         }
     260              :     }
     261              :     return 0;
     262              : }
     263              : 
     264              : double
     265           30 : MSParkingArea::getGUIAngle(const SUMOVehicle& forVehicle) const {
     266           60 :     for (const auto& lsd : mySpaceOccupancies) {
     267           60 :         if (lsd.vehicle == &forVehicle) {
     268           30 :             if (lsd.manoeuverAngle > 180.) {
     269           15 :                 return DEG2RAD(lsd.manoeuverAngle - 360.);
     270              :             } else {
     271           15 :                 return DEG2RAD(lsd.manoeuverAngle);
     272              :             }
     273              :         }
     274              :     }
     275              :     return 0.;
     276              : }
     277              : 
     278              : int
     279           30 : MSParkingArea::getManoeuverAngle(const SUMOVehicle& forVehicle) const {
     280           60 :     for (const auto& lsd : mySpaceOccupancies) {
     281           60 :         if (lsd.vehicle == &forVehicle) {
     282           30 :             if (lsd.sideIsLHS) {
     283           30 :                 return abs(int(lsd.manoeuverAngle)) % 180;
     284              :             } else {
     285            0 :                 return abs(abs(int(lsd.manoeuverAngle)) % 180 - 180) % 180;
     286              :             }
     287              :         }
     288              :     }
     289              :     return 0;
     290              : }
     291              : 
     292              : int
     293        26096 : MSParkingArea::getLotIndex(const SUMOVehicle* veh) const {
     294        26096 :     if (veh->getPositionOnLane() > myLastFreePos) {
     295              :         // vehicle has gone past myLastFreePos and we need to find the actual lot
     296              :         int closestLot = -1;
     297         6445 :         for (int i = 0; i < (int)mySpaceOccupancies.size(); i++) {
     298         6397 :             const LotSpaceDefinition lsd = mySpaceOccupancies[i];
     299         6397 :             if (lsd.vehicle == nullptr) {
     300              :                 closestLot = i;
     301         2455 :                 if (lsd.endPos >= veh->getPositionOnLane()) {
     302         1102 :                     return i;
     303              :                 }
     304              :             }
     305              :         }
     306           48 :         return closestLot;
     307              :     }
     308        24946 :     if (myOnRoad && myLastFreePos - veh->getPositionOnLane() > POSITION_EPS) {
     309              :         // for on-road parking we need to be precise
     310              :         return -1;
     311              :     }
     312         8721 :     return myLastFreeLot;
     313              : }
     314              : 
     315              : void
     316         8932 : MSParkingArea::enter(SUMOVehicle* veh, const bool /* parking */) {
     317         8932 :     double beg = veh->getPositionOnLane() + veh->getVehicleType().getMinGap();
     318         8932 :     double end = veh->getPositionOnLane() - veh->getVehicleType().getLength();
     319         8932 :     if (myUpdateEvent == nullptr) {
     320         8218 :         myUpdateEvent = new WrappingCommand<MSParkingArea>(this, &MSParkingArea::updateOccupancy);
     321         8218 :         MSNet::getInstance()->getEndOfTimestepEvents()->addEvent(myUpdateEvent);
     322              :     }
     323         8932 :     int lotIndex = getLotIndex(veh);
     324         8932 :     if (lotIndex < 0) {
     325            0 :         WRITE_WARNING("Unsuitable parking position for vehicle '" + veh->getID() + "' at parkingArea '" + getID() + "' time=" + time2string(SIMSTEP));
     326            0 :         lotIndex = myLastFreeLot;
     327              :     }
     328              : #ifdef DEBUG_GET_LAST_FREE_POS
     329              :     ((SUMOVehicleParameter&)veh->getParameter()).setParameter("lotIndex", toString(lotIndex));
     330              : #endif
     331              :     assert(myLastFreePos >= 0);
     332              :     assert(lotIndex < (int)mySpaceOccupancies.size());
     333         8932 :     mySpaceOccupancies[lotIndex].vehicle = veh;
     334         8932 :     myEndPositions[veh] = std::pair<double, double>(beg, end);
     335         8932 :     computeLastFreePos();
     336         8932 :     myMaxVehLength = MAX2(myMaxVehLength, veh->getLength());
     337              :     // current search ends here
     338         8932 :     veh->setNumberParkingReroutes(0);
     339         8932 : }
     340              : 
     341              : 
     342              : void
     343         7530 : MSParkingArea::leaveFrom(SUMOVehicle* what) {
     344              :     assert(myEndPositions.find(what) != myEndPositions.end());
     345         7530 :     if (myUpdateEvent == nullptr) {
     346         7418 :         myUpdateEvent = new WrappingCommand<MSParkingArea>(this, &MSParkingArea::updateOccupancy);
     347         7418 :         MSNet::getInstance()->getEndOfTimestepEvents()->addEvent(myUpdateEvent);
     348              :     }
     349        20439 :     for (auto& lsd : mySpaceOccupancies) {
     350        20439 :         if (lsd.vehicle == what) {
     351         7530 :             lsd.vehicle = nullptr;
     352         7530 :             break;
     353              :         }
     354              :     }
     355         7530 :     if (what->getLength() == myMaxVehLength) {
     356         7455 :         myMaxVehLength = 0;
     357        32929 :         for (auto item : myEndPositions) {
     358        50878 :             myMaxVehLength = MAX2(myMaxVehLength, item.first->getLength());
     359              :         }
     360              :     }
     361              :     myEndPositions.erase(myEndPositions.find(what));
     362         7530 :     computeLastFreePos();
     363         7530 : }
     364              : 
     365              : 
     366              : SUMOTime
     367        15636 : MSParkingArea::updateOccupancy(SUMOTime /* currentTime */) {
     368        15636 :     myLastStepOccupancy = getOccupancy();
     369        15636 :     myUpdateEvent = nullptr;
     370        15636 :     return 0;
     371              : }
     372              : 
     373              : 
     374            0 : MSParkingArea::LotSpaceDefinition::LotSpaceDefinition() :
     375            0 :     index(-1),
     376            0 :     vehicle(nullptr),
     377            0 :     rotation(0),
     378            0 :     slope(0),
     379            0 :     width(0),
     380            0 :     length(0),
     381            0 :     endPos(0),
     382            0 :     manoeuverAngle(0),
     383            0 :     sideIsLHS(false) {
     384            0 : }
     385              : 
     386              : 
     387        50965 : MSParkingArea::LotSpaceDefinition::LotSpaceDefinition(int index_, SUMOVehicle* vehicle_, double x, double y, double z, double rotation_, double slope_, double width_, double length_) :
     388        50965 :     index(index_),
     389        50965 :     vehicle(vehicle_),
     390              :     position(Position(x, y, z)),
     391        50965 :     rotation(rotation_),
     392        50965 :     slope(slope_),
     393        50965 :     width(width_),
     394        50965 :     length(length_),
     395        50965 :     endPos(0),
     396        50965 :     manoeuverAngle(0),
     397        50965 :     sideIsLHS(false) {
     398        50965 : }
     399              : 
     400              : 
     401              : void
     402        68751 : MSParkingArea::computeLastFreePos() {
     403        68751 :     myLastFreeLot = -1;
     404        68751 :     myLastFreePos = myBegPos;
     405        68751 :     myEgressBlocked = false;
     406       100206 :     for (auto& lsd : mySpaceOccupancies) {
     407        96003 :         if (lsd.vehicle == nullptr
     408        96003 :                 || (getOccupancy() == getCapacity()
     409        11683 :                     && lsd.vehicle->remainingStopDuration() <= 0
     410          946 :                     && !lsd.vehicle->isStoppedTriggered())) {
     411        64548 :             if (lsd.vehicle == nullptr) {
     412        63713 :                 myLastFreeLot = lsd.index;
     413        63713 :                 myLastFreePos = lsd.endPos;
     414              :             } else {
     415              :                 // vehicle wants to exit the parking area
     416          835 :                 myLastFreeLot = lsd.index;
     417          835 :                 myLastFreePos = lsd.endPos - lsd.vehicle->getVehicleType().getLength() - POSITION_EPS;
     418          835 :                 myEgressBlocked = true;
     419              :             }
     420              :             break;
     421              :         } else {
     422        31455 :             myLastFreePos = MIN2(myLastFreePos,
     423        31455 :                                  lsd.endPos - lsd.vehicle->getVehicleType().getLength() - NUMERICAL_EPS);
     424              :         }
     425              :     }
     426        68751 : }
     427              : 
     428              : 
     429              : double
     430      1568054 : MSParkingArea::getLastFreePosWithReservation(SUMOTime t, const SUMOVehicle& forVehicle, double brakePos) {
     431              :     // do not perform reservation when far away
     432      1568054 :     if (forVehicle.getLane() != &myLane || forVehicle.getPositionOnLane() < (myBegPos - myMaxVehLength - forVehicle.getVehicleType().getMinGap())) {
     433              :         // for different lanes, do not consider reservations to avoid lane-order
     434              :         // dependency in parallel simulation
     435              : #ifdef DEBUG_RESERVATIONS
     436              :         if (DEBUG_COND2(forVehicle)) {
     437              :             std::cout << SIMTIME << " pa=" << getID() << " freePosRes veh=" << forVehicle.getID() << " other lane\n";
     438              :         }
     439              : #endif
     440      1374376 :         if (myNumAlternatives > 0 && getOccupancy() == getCapacity()) {
     441              :             // ensure that the vehicle reaches the rerouter lane
     442       167875 :             if (mySpaceOccupancies.size() > 0) {
     443              :                 assert(mySpaceOccupancies[0].vehicle != nullptr);
     444       167367 :                 const double waitPos = (mySpaceOccupancies[0].endPos
     445       167367 :                                         - mySpaceOccupancies[0].vehicle->getLength()
     446       167367 :                                         - forVehicle.getVehicleType().getMinGap()
     447       167367 :                                         - NUMERICAL_EPS);
     448       167367 :                 return MAX2(waitPos, MIN2(POSITION_EPS, myEndPos));
     449              :             } else {
     450          508 :                 return MAX2(myBegPos, MIN2(POSITION_EPS, myEndPos));
     451              :             }
     452              :         } else {
     453              :             // check if there is a reservation from the last time step
     454              :             // (this could also be in myReserations, if myLane wasn't processed before the forVehicle-lane)
     455      1206501 :             const SUMOTime last = t - DELTA_T;
     456      1206501 :             if (DEBUG_COND2(forVehicle)) {
     457            0 :                 std::cout << SIMTIME << " last=" << time2string(last) << " lastRes=" << time2string(myLastReservationTime) << " resTime=" << toString(myReservationTime) << "\n";
     458              :             }
     459      1206501 :             if (myLastReservationTime == last || myReservationTime == last) {
     460       830255 :                 int res = myLastReservationTime == last ? myLastReservations : myReservations;
     461       830255 :                 if (myCapacity <= getOccupancy() + res) {
     462       806021 :                     double maxLen = myLastReservationTime == last ? myLastReservationMaxLength : myReservationMaxLength;
     463              : #ifdef DEBUG_RESERVATIONS
     464              :                     if (DEBUG_COND2(forVehicle)) std::cout << SIMTIME << " pa=" << getID() << " freePosRes veh=" << forVehicle.getID()
     465              :                                                                << " lastRes=" << res << " resTime=" << myReservationTime << " reserved full, maxLen=" << maxLen << " endPos=" << mySpaceOccupancies[0].endPos << "\n";
     466              : #endif
     467       806021 :                     return (mySpaceOccupancies[0].endPos
     468       806021 :                             - maxLen
     469       806021 :                             - forVehicle.getVehicleType().getMinGap()
     470       806021 :                             - NUMERICAL_EPS);
     471              :                 }
     472              :             }
     473       400480 :             return getLastFreePos(forVehicle, brakePos);
     474              :         }
     475              :     }
     476       193678 :     if (t > myReservationTime) {
     477              : #ifdef DEBUG_RESERVATIONS
     478              :         if (DEBUG_COND2(forVehicle)) {
     479              :             std::cout << SIMTIME << " pa=" << getID() << " freePosRes veh=" << forVehicle.getID() << " first reservation\n";
     480              :         }
     481              : #endif
     482       148017 :         myLastReservationTime = myReservationTime;
     483       148017 :         myLastReservations = myReservations;
     484       148017 :         myLastReservationMaxLength = myReservationMaxLength;
     485       148017 :         myReservationTime = t;
     486       148017 :         myReservations = 1;
     487       148017 :         myReservationMaxLength = forVehicle.getVehicleType().getLength();
     488              :         myReservedVehicles.clear();
     489       148017 :         myReservedVehicles.insert(&forVehicle);
     490       726821 :         for (const auto& lsd : mySpaceOccupancies) {
     491       578804 :             if (lsd.vehicle != nullptr) {
     492       644674 :                 myReservationMaxLength = MAX2(myReservationMaxLength, lsd.vehicle->getVehicleType().getLength());
     493              :             }
     494              :         }
     495       148017 :         return getLastFreePos(forVehicle, brakePos);
     496              :     } else {
     497        45661 :         if (myCapacity > getOccupancy() + myReservations) {
     498              : #ifdef DEBUG_RESERVATIONS
     499              :             if (DEBUG_COND2(forVehicle)) {
     500              :                 std::cout << SIMTIME << " pa=" << getID() << " freePosRes veh=" << forVehicle.getID() << " res=" << myReservations << " enough space\n";
     501              :             }
     502              : #endif
     503         6410 :             myReservations++;
     504         6410 :             myReservationMaxLength = MAX2(myReservationMaxLength, forVehicle.getVehicleType().getLength());
     505         6410 :             myReservedVehicles.insert(&forVehicle);
     506         6410 :             return getLastFreePos(forVehicle, brakePos);
     507              :         } else {
     508        39251 :             if (myCapacity == 0) {
     509          380 :                 return getLastFreePos(forVehicle, brakePos);
     510              :             } else {
     511              : #ifdef DEBUG_RESERVATIONS
     512              :                 if (DEBUG_COND2(forVehicle)) std::cout << SIMTIME << " pa=" << getID() << " freePosRes veh=" << forVehicle.getID()
     513              :                                                            << " res=" << myReservations << " resTime=" << myReservationTime << " reserved full, maxLen=" << myReservationMaxLength << " endPos=" << mySpaceOccupancies[0].endPos << "\n";
     514              : #endif
     515        38871 :                 return (mySpaceOccupancies[0].endPos
     516        38871 :                         - myReservationMaxLength
     517        38871 :                         - forVehicle.getVehicleType().getMinGap()
     518        38871 :                         - NUMERICAL_EPS);
     519              :             }
     520              :         }
     521              :     }
     522              : }
     523              : 
     524              : 
     525              : double
     526          805 : MSParkingArea::getWidth() const {
     527          805 :     return myWidth;
     528              : }
     529              : 
     530              : 
     531              : double
     532          805 : MSParkingArea::getLength() const {
     533          805 :     return myLength;
     534              : }
     535              : 
     536              : 
     537              : double
     538          805 : MSParkingArea::getAngle() const {
     539          805 :     return myAngle;
     540              : }
     541              : 
     542              : 
     543              : int
     544      1403024 : MSParkingArea::getCapacity() const {
     545      1403024 :     return myCapacity;
     546              : }
     547              : 
     548              : 
     549              : bool
     550       399040 : MSParkingArea::parkOnRoad() const {
     551       399040 :     return myOnRoad;
     552              : }
     553              : 
     554              : 
     555              : int
     556      1905449 : MSParkingArea::getOccupancy() const {
     557      1905449 :     return (int)myEndPositions.size() - (myEgressBlocked ? 1 : 0);
     558              : }
     559              : 
     560              : 
     561              : int
     562            5 : MSParkingArea::getOccupancyIncludingBlocked() const {
     563            5 :     return (int)myEndPositions.size();
     564              : }
     565              : 
     566              : int
     567       231809 : MSParkingArea::getOccupancyIncludingReservations(const SUMOVehicle* forVehicle) const {
     568              :     if (myReservedVehicles.count(forVehicle) != 0) {
     569        79757 :         return (int)myEndPositions.size();
     570              :     } else {
     571       152052 :         return (int)myEndPositions.size() + myReservations;
     572              :     }
     573              : }
     574              : 
     575              : int
     576        81835 : MSParkingArea::getLastStepOccupancy() const {
     577        81835 :     return myLastStepOccupancy;
     578              : }
     579              : 
     580              : 
     581              : void
     582            0 : MSParkingArea::accept(std::string badge) {
     583              :     myAcceptedBadges.insert(badge);
     584            0 : }
     585              : 
     586              : 
     587              : void
     588            0 : MSParkingArea::accept(std::vector<std::string> badges) {
     589              :     myAcceptedBadges.insert(badges.begin(), badges.end());
     590            0 : }
     591              : 
     592              : 
     593              : void
     594            0 : MSParkingArea::refuse(std::string badge) {
     595              :     myAcceptedBadges.erase(badge);
     596            0 : }
     597              : 
     598              : 
     599              : bool
     600       202235 : MSParkingArea::accepts(SUMOVehicle* veh) const {
     601       202235 :     if (myAcceptedBadges.size() == 0) {
     602              :         return true;
     603              :     } else {
     604         1656 :         std::vector<std::string> vehicleBadges = veh->getParkingBadges();
     605         1656 :         for (auto badge : vehicleBadges) {
     606              :             if (myAcceptedBadges.count(badge) != 0) {
     607              :                 return true;
     608              :             }
     609              :         }
     610          687 :         return false;
     611         1656 :     }
     612              : }
     613              : 
     614              : 
     615              : void
     616         1324 : MSParkingArea::notifyEgressBlocked() {
     617         1324 :     computeLastFreePos();
     618         1324 : }
     619              : 
     620              : 
     621              : int
     622            0 : MSParkingArea::getNumAlternatives() const {
     623            0 :     return myNumAlternatives;
     624              : }
     625              : 
     626              : 
     627              : void
     628        13515 : MSParkingArea::setNumAlternatives(int alternatives) {
     629        13515 :     myNumAlternatives = MAX2(myNumAlternatives, alternatives);
     630        13515 : }
     631              : 
     632              : 
     633              : std::vector<std::string>
     634           28 : MSParkingArea::getAcceptedBadges() const {
     635           28 :     std::vector<std::string> result(myAcceptedBadges.begin(), myAcceptedBadges.end());
     636           28 :     return result;
     637              : }
     638              : 
     639              : 
     640              : void
     641           10 : MSParkingArea::setAcceptedBadges(const std::vector<std::string>& badges) {
     642              :     myAcceptedBadges.clear();
     643              :     myAcceptedBadges.insert(badges.begin(), badges.end());
     644           10 : }
     645              : 
     646              : 
     647              : const std::vector<MSParkingArea::LotSpaceDefinition>&
     648          122 : MSParkingArea::getSpaceOccupancies() const {
     649          122 :     return mySpaceOccupancies;
     650              : }
     651              : 
     652              : 
     653              : const PositionVector&
     654            5 : MSParkingArea::getShape() const {
     655            5 :     return myShape;
     656              : }
     657              : 
     658              : 
     659              : void
     660        24191 : MSParkingArea::setRoadsideCapacity(int capacity) {
     661              :     // reinit parking lot generation process
     662        24191 :     myRoadSideCapacity = capacity;
     663              : 
     664              :     // Initialize space occupancies if there is a road-side capacity
     665              :     // The overall number of lots is fixed and each lot accepts one vehicle regardless of size
     666        24191 :     const double spaceDim = myRoadSideCapacity > 0 ? myLane.interpolateLanePosToGeometryPos((myEndPos - myBegPos) / myRoadSideCapacity) : 7.5;
     667        24191 :     if (myLength == 0) {
     668        11190 :         myLength = spaceDim;
     669              :     }
     670              :     mySpaceOccupancies.clear();
     671        24191 :     myCapacity = 0;
     672        74351 :     for (int i = 0; i < myRoadSideCapacity; ++i) {
     673              :         // calculate pos, angle and slope of parking lot space
     674        50160 :         const Position pos = GeomHelper::calculateLotSpacePosition(myShape, i, spaceDim, myAngle, myWidth, myLength);
     675        50160 :         double spaceAngle = GeomHelper::calculateLotSpaceAngle(myShape, i, spaceDim, myAngle);
     676        50160 :         double spaceSlope = GeomHelper::calculateLotSpaceSlope(myShape, i, spaceDim);
     677              :         // add lotEntry
     678        50160 :         addLotEntry(pos.x(), pos.y(), pos.z(), myWidth, myLength, spaceAngle, spaceSlope);
     679              :         // update endPos
     680       148315 :         mySpaceOccupancies.back().endPos = MIN2(myEndPos, myBegPos + MAX2(POSITION_EPS, spaceDim * (i + 1)));
     681              :     }
     682        24191 : }
     683              : 
     684              : /****************************************************************************/
        

Generated by: LCOV version 2.0-1