LCOV - code coverage report
Current view: top level - src/microsim - MSStoppingPlace.cpp (source / functions) Coverage Total Hit
Test: lcov.info Lines: 91.0 % 167 152
Test Date: 2026-05-24 16:29:35 Functions: 96.9 % 32 31

            Line data    Source code
       1              : /****************************************************************************/
       2              : // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
       3              : // Copyright (C) 2005-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    MSStoppingPlace.cpp
      15              : /// @author  Daniel Krajzewicz
      16              : /// @author  Michael Behrisch
      17              : /// @author  Johannes Rummel
      18              : /// @date    Mon, 13.12.2005
      19              : ///
      20              : // A lane area vehicles can halt at
      21              : /****************************************************************************/
      22              : #include <config.h>
      23              : 
      24              : #include <cassert>
      25              : #include <map>
      26              : #include <utils/vehicle/SUMOVehicle.h>
      27              : #include <utils/geom/Position.h>
      28              : #include <utils/geom/GeomHelper.h>
      29              : #include <utils/common/RGBColor.h>
      30              : #include <microsim/transportables/MSTransportable.h>
      31              : #include <microsim/MSGlobals.h>
      32              : #include <microsim/MSVehicleType.h>
      33              : #include <microsim/MSNet.h>
      34              : #include <microsim/MSLane.h>
      35              : #include <microsim/MSStop.h>
      36              : #include "MSStoppingPlace.h"
      37              : 
      38              : // ===========================================================================
      39              : // method definitions
      40              : // ===========================================================================
      41        83824 : MSStoppingPlace::MSStoppingPlace(const std::string& id,
      42              :                                  SumoXMLTag element,
      43              :                                  const std::vector<std::string>& lines,
      44              :                                  MSLane& lane,
      45              :                                  double begPos, double endPos, const std::string name,
      46              :                                  int capacity,
      47              :                                  double parkingLength,
      48              :                                  const RGBColor& color,
      49        83824 :                                  double angle) :
      50              :     Named(id),
      51        83824 :     myElement(element),
      52       167648 :     myLines(lines), myLane(lane),
      53        83824 :     myBegPos(begPos), myEndPos(endPos),
      54        83824 :     myLastFreePos(endPos),
      55        83824 :     myLastParking(nullptr),
      56        83824 :     myName(name),
      57        83824 :     myTransportableCapacity(capacity),
      58        83824 :     myParkingFactor(parkingLength <= 0 ? 1 : (endPos - begPos) / parkingLength),
      59        83824 :     myColor(color),
      60        83824 :     myAngle(DEG2RAD(angle)),
      61              :     // see MSVehicleControl defContainerType
      62        83824 :     myTransportableDepth(element == SUMO_TAG_CONTAINER_STOP ? SUMO_const_waitingContainerDepth : SUMO_const_waitingPersonDepth),
      63       167648 :     myTransportableWidth(getDefaultTransportableWidth(myElement)) {
      64        83824 :     computeLastFreePos();
      65      3677418 :     for (int i = 0; i < capacity; i++) {
      66              :         myWaitingSpots.insert(i);
      67              :     }
      68        83824 : }
      69              : 
      70              : 
      71       299567 : MSStoppingPlace::~MSStoppingPlace() {}
      72              : 
      73              : 
      74              : double
      75       134998 : MSStoppingPlace::getDefaultTransportableWidth(SumoXMLTag element) {
      76              :     return element == SUMO_TAG_CONTAINER_STOP
      77       134998 :            ? SUMO_const_waitingContainerWidth
      78       134998 :            : SUMO_const_waitingPersonWidth;
      79              : 
      80              : }
      81              : 
      82              : void
      83        66401 : MSStoppingPlace::finishedLoading() {
      84       132802 :     const std::string waitingWidth = getParameter("waitingWidth");
      85        66401 :     if (waitingWidth != "") {
      86              :         try {
      87            0 :             myTransportableWidth = StringUtils::toDouble(waitingWidth);
      88            0 :         } catch (ProcessError& e) {
      89            0 :             WRITE_WARNINGF("Could not load waitingWidth (m) '%' (%)", waitingWidth, e.what());
      90            0 :         }
      91              :     }
      92       132802 :     const std::string waitingDepth = getParameter("waitingDepth");
      93        66401 :     if (waitingDepth != "") {
      94              :         try {
      95            0 :             myTransportableDepth = StringUtils::toDouble(waitingDepth);
      96            0 :         } catch (ProcessError& e) {
      97            0 :             WRITE_WARNINGF("Could not load waitingDepth (m) '%' (%)", waitingWidth, e.what());
      98            0 :         }
      99              :     }
     100        66401 : }
     101              : 
     102              : 
     103              : const MSLane&
     104      1472260 : MSStoppingPlace::getLane() const {
     105      1472260 :     return myLane;
     106              : }
     107              : 
     108              : 
     109              : double
     110      1027023 : MSStoppingPlace::getBeginLanePosition() const {
     111      1027023 :     return myBegPos;
     112              : }
     113              : 
     114              : 
     115              : double
     116       338992 : MSStoppingPlace::getEndLanePosition() const {
     117       338992 :     return myEndPos;
     118              : }
     119              : 
     120              : Position
     121         3003 : MSStoppingPlace::getCenterPos() const {
     122         3003 :     return myLane.getShape().positionAtOffset(myLane.interpolateLanePosToGeometryPos((myBegPos + myEndPos) / 2),
     123         3003 :             myLane.getWidth() / 2 + 0.5);
     124              : }
     125              : 
     126              : 
     127              : void
     128      2573571 : MSStoppingPlace::enter(SUMOVehicle* veh, const bool parking) {
     129      2573571 :     const double beg = veh->getPositionOnLane() + veh->getVehicleType().getMinGap() * (parking ? myParkingFactor : 1);
     130      2573571 :     const double end = beg - veh->getVehicleType().getLengthWithGap() * (parking ? myParkingFactor : 1);
     131      2573571 :     myEndPositions[veh] = std::make_pair(beg, end);
     132      2573571 :     computeLastFreePos();
     133      2573571 : }
     134              : 
     135              : 
     136              : double
     137      6962479 : MSStoppingPlace::getLastFreePos(const SUMOVehicle& forVehicle, double /*brakePos*/) const {
     138      6962479 :     if (getStoppedVehicleNumber() > 0) {
     139      2555076 :         const double vehGap = forVehicle.getVehicleType().getMinGap();
     140      2555076 :         double pos = myLastFreePos - vehGap - NUMERICAL_EPS;
     141         1561 :         if (myParkingFactor < 1 && myLastParking != nullptr && forVehicle.hasStops() && (forVehicle.getStops().front().pars.parking == ParkingType::ONROAD)
     142      2555418 :                 && myLastParking->remainingStopDuration() < forVehicle.getStops().front().getMinDuration(SIMSTEP)) {
     143              :             // stop far back enough so that the previous parking vehicle can leave (even if this vehicle fits, it will
     144              :             // be a blocker because it stops on the road)
     145           62 :             pos = MIN2(pos, myLastParking->getPositionOnLane() - myLastParking->getLength() - vehGap - NUMERICAL_EPS);
     146              :         }
     147      2555076 :         if (!fits(pos, forVehicle)) {
     148              :             // try to find a place ahead of the waiting vehicles
     149      2407267 :             const double vehLength = forVehicle.getVehicleType().getLength() * myParkingFactor;
     150              :             std::vector<std::pair<double, std::pair<double, const SUMOVehicle*> > > spaces;
     151      6371533 :             for (auto it : myEndPositions) {
     152      3964266 :                 spaces.push_back(std::make_pair(it.second.first, std::make_pair(it.second.second, it.first)));
     153              :             }
     154              :             // sorted from myEndPos towars myBegPos
     155      2407267 :             std::sort(spaces.begin(), spaces.end());
     156      2407267 :             std::reverse(spaces.begin(), spaces.end());
     157      2407267 :             double prev = myEndPos;
     158      6223940 :             for (auto it : spaces) {
     159              :                 //if (forVehicle.isSelected()) {
     160              :                 //    std::cout << SIMTIME << " fitPosFor " << forVehicle.getID() << " l=" << vehLength << " prev=" << prev << " vehBeg=" << it.first << " vehEnd=" << it.second.first << " found=" << (prev - it.first >= vehLength) << "\n";
     161              :                 //}
     162      4105417 :                 if (prev - it.first + NUMERICAL_EPS >= vehLength && (
     163       146002 :                             it.second.second->isParking()
     164         3519 :                             || it.second.second->remainingStopDuration() > TIME2STEPS(10))) {
     165              :                     return prev;
     166              :                 }
     167      3816673 :                 prev = it.second.first - vehGap;
     168              :             }
     169      2264525 :             if (myParkingFactor < 1 && myLastParking != nullptr) {
     170              :                 // stop far back enough so that the previous vehicle can leave
     171          734 :                 pos = MIN2(pos, myLastParking->getPositionOnLane() - myLastParking->getLength() - vehGap - NUMERICAL_EPS);
     172              :             }
     173      2407267 :         }
     174      2412334 :         return pos;
     175              :     }
     176      4407403 :     return myLastFreePos;
     177              : }
     178              : 
     179              : bool
     180      4281767 : MSStoppingPlace::fits(double pos, const SUMOVehicle& veh) const {
     181              :     // always fit at the default position or if at least half the vehicle length
     182              :     // is within the stop range (debatable)
     183      4281767 :     return pos + POSITION_EPS >= myEndPos || (pos - myBegPos >= veh.getVehicleType().getLength() * myParkingFactor / 2);
     184              : }
     185              : 
     186              : double
     187       112907 : MSStoppingPlace::getWaitingPositionOnLane(MSTransportable* t) const {
     188              :     auto it = myWaitingTransportables.find(t);
     189       112907 :     if (it != myWaitingTransportables.end() && it->second >= 0) {
     190        37042 :         return myEndPos - (0.5 + (it->second) % getTransportablesAbreast()) * myTransportableWidth;
     191              :     } else {
     192        75865 :         return (myEndPos + myBegPos) / 2;
     193              :     }
     194              : }
     195              : 
     196              : 
     197              : int
     198        51174 : MSStoppingPlace::getDefaultTransportablesAbreast(double length, SumoXMLTag element) {
     199        51174 :     return MAX2(1, (int)floor(length / getDefaultTransportableWidth(element)));
     200              : }
     201              : 
     202              : int
     203        70688 : MSStoppingPlace::getTransportablesAbreast() const {
     204        70688 :     return MAX2(1, (int)floor((myEndPos - myBegPos) / myTransportableWidth));
     205              : }
     206              : 
     207              : Position
     208        88904 : MSStoppingPlace::getWaitPosition(MSTransportable* t) const {
     209        88904 :     double lanePos = getWaitingPositionOnLane(t);
     210              :     int row = 0;
     211              :     auto it = myWaitingTransportables.find(t);
     212        88904 :     if (it != myWaitingTransportables.end()) {
     213        31389 :         if (it->second >= 0) {
     214        31389 :             row = int(it->second / getTransportablesAbreast());
     215              :         } else {
     216              :             // invalid position, draw outside bounds
     217            0 :             row = 1 + myTransportableCapacity / getTransportablesAbreast();
     218              :         }
     219              :     }
     220        88904 :     const double lefthandSign = (MSGlobals::gLefthand ? -1 : 1);
     221        88904 :     return myLane.getShape().positionAtOffset(myLane.interpolateLanePosToGeometryPos(lanePos),
     222        88904 :             lefthandSign * (myLane.getWidth() / 2 + row * myTransportableDepth + fabs(cos(myAngle)) * myTransportableWidth / 2));
     223              : }
     224              : 
     225              : 
     226              : double
     227            0 : MSStoppingPlace::getStoppingPosition(const SUMOVehicle* veh) const {
     228              :     auto i = myEndPositions.find(veh);
     229            0 :     if (i != myEndPositions.end()) {
     230            0 :         return i->second.second;
     231              :     } else {
     232            0 :         return getLastFreePos(*veh);
     233              :     }
     234              : }
     235              : 
     236              : std::vector<const MSTransportable*>
     237          156 : MSStoppingPlace::getTransportables() const {
     238              :     std::vector<const MSTransportable*> result;
     239          212 :     for (auto item : myWaitingTransportables) {
     240           56 :         result.push_back(item.first);
     241              :     }
     242          156 :     return result;
     243            0 : }
     244              : 
     245              : bool
     246       130926 : MSStoppingPlace::hasSpaceForTransportable() const {
     247       130926 :     return myWaitingSpots.size() > 0;
     248              : }
     249              : 
     250              : bool
     251       130928 : MSStoppingPlace::addTransportable(const MSTransportable* p, int spot) {
     252       130928 :     if (spot < 0 && !hasSpaceForTransportable()) {
     253              :         return false;
     254              :     }
     255        90458 :     if (spot < 0) {
     256        90456 :         spot = *myWaitingSpots.begin();
     257              :     }
     258              :     myWaitingSpots.erase(spot);
     259        90458 :     myWaitingTransportables[p] = spot;
     260        90458 :     return true;
     261              : }
     262              : 
     263              : 
     264              : void
     265       197888 : MSStoppingPlace::removeTransportable(const MSTransportable* p) {
     266              :     auto i = myWaitingTransportables.find(p);
     267       197888 :     if (i != myWaitingTransportables.end()) {
     268        90417 :         if (i->second >= 0) {
     269        90417 :             myWaitingSpots.insert(i->second);
     270              :         }
     271              :         myWaitingTransportables.erase(i);
     272              :     }
     273       197888 : }
     274              : 
     275              : 
     276              : int
     277            2 : MSStoppingPlace::checkWaitingSpot(const MSTransportable* p) const {
     278              :     auto i = myWaitingTransportables.find(p);
     279            2 :     if (i != myWaitingTransportables.end()) {
     280            2 :         return i->second;
     281              :     } else {
     282              :         return -1;
     283              :     }
     284              : }
     285              : 
     286              : 
     287              : void
     288        22350 : MSStoppingPlace::leaveFrom(SUMOVehicle* what) {
     289              :     assert(myEndPositions.find(what) != myEndPositions.end());
     290              :     myEndPositions.erase(myEndPositions.find(what));
     291        22350 :     computeLastFreePos();
     292        22350 : }
     293              : 
     294              : 
     295              : void
     296      2679786 : MSStoppingPlace::computeLastFreePos() {
     297      2679786 :     myLastFreePos = myEndPos;
     298      2679786 :     myLastParking = nullptr;
     299      5263201 :     for (auto item : myEndPositions) {
     300              :         // vehicle might be stopped beyond myEndPos
     301      2583415 :         if (myLastFreePos >= item.second.second || myLastFreePos == myEndPos) {
     302      2579344 :             myLastFreePos = item.second.second;
     303      2579344 :             if (item.first->isStoppedParking()) {
     304      2544556 :                 myLastParking = item.first;
     305              :             }
     306              :         }
     307              :     }
     308      2679786 : }
     309              : 
     310              : 
     311              : double
     312        64823 : MSStoppingPlace::getAccessPos(const MSEdge* edge, SumoRNG* rng) const {
     313        64823 :     if (edge == &myLane.getEdge()) {
     314        58357 :         return (myBegPos + myEndPos) / 2.;
     315              :     }
     316         8237 :     for (const auto& access : myAccessPos) {
     317         6948 :         if (edge == &access.lane->getEdge()) {
     318         5177 :             if (rng == nullptr || access.startPos == access.endPos) {
     319         4419 :                 return access.endPos;
     320              :             }
     321          758 :             return RandHelper::rand(access.startPos, access.endPos, rng);
     322              :         }
     323              :     }
     324              :     return -1.;
     325              : }
     326              : 
     327              : 
     328              : const MSStoppingPlace::Access*
     329        60572 : MSStoppingPlace::getAccess(const MSEdge* edge) const {
     330        64015 :     for (const auto& access : myAccessPos) {
     331         7698 :         if (edge == &access.lane->getEdge()) {
     332              :             return &access;
     333              :         }
     334              :     }
     335              :     return nullptr;
     336              : }
     337              : 
     338              : 
     339              : const std::string&
     340       144631 : MSStoppingPlace::getMyName() const {
     341       144631 :     return myName;
     342              : }
     343              : 
     344              : 
     345              : const RGBColor&
     346        76184 : MSStoppingPlace::getColor() const {
     347        76184 :     return myColor;
     348              : }
     349              : 
     350              : 
     351              : bool
     352         2252 : MSStoppingPlace::addAccess(MSLane* const lane, const double startPos, const double endPos, double length, const MSStoppingPlace::AccessExit exit) {
     353              :     // prevent multiple accesses on the same lane
     354         3941 :     for (const auto& access : myAccessPos) {
     355         1696 :         if (lane == access.lane) {
     356              :             return false;
     357              :         }
     358              :     }
     359         2245 :     if (length < 0.) {
     360         1379 :         const Position accPos = lane->geometryPositionAtOffset((startPos + endPos) / 2.);
     361         1379 :         const Position stopPos = myLane.geometryPositionAtOffset((myBegPos + myEndPos) / 2.);
     362         1379 :         length = accPos.distanceTo(stopPos);
     363              :     }
     364         2245 :     myAccessPos.push_back({lane, startPos, endPos, length, exit});
     365         2245 :     return true;
     366              : }
     367              : 
     368              : 
     369              : std::vector<const SUMOVehicle*>
     370          755 : MSStoppingPlace::getStoppedVehicles() const {
     371              :     std::vector<const SUMOVehicle*> result;
     372         1007 :     for (auto item : myEndPositions) {
     373          252 :         result.push_back(item.first);
     374              :     }
     375          755 :     return result;
     376            0 : }
     377              : 
     378              : 
     379              : void
     380          109 : MSStoppingPlace::getWaitingPersonIDs(std::vector<std::string>& into) const {
     381          236 :     for (auto item : myWaitingTransportables) {
     382          127 :         into.push_back(item.first->getID());
     383              :     }
     384          109 :     std::sort(into.begin(), into.end());
     385          109 : }
     386              : 
     387              : 
     388              : void
     389           41 : MSStoppingPlace::clearState() {
     390              :     myEndPositions.clear();
     391              :     myWaitingTransportables.clear();
     392           41 :     computeLastFreePos();
     393           41 : }
     394              : 
     395              : 
     396              : /****************************************************************************/
        

Generated by: LCOV version 2.0-1