LCOV - code coverage report
Current view: top level - src/microsim - MSStoppingPlace.cpp (source / functions) Coverage Total Hit
Test: lcov.info Lines: 90.8 % 163 148
Test Date: 2025-11-13 15:38:19 Functions: 96.8 % 31 30

            Line data    Source code
       1              : /****************************************************************************/
       2              : // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
       3              : // Copyright (C) 2005-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    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        66977 : 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        66977 :                                  double angle) :
      50              :     Named(id),
      51        66977 :     myElement(element),
      52       133954 :     myLines(lines), myLane(lane),
      53        66977 :     myBegPos(begPos), myEndPos(endPos),
      54        66977 :     myLastFreePos(endPos),
      55        66977 :     myLastParking(nullptr),
      56        66977 :     myName(name),
      57        66977 :     myTransportableCapacity(capacity),
      58        66977 :     myParkingFactor(parkingLength <= 0 ? 1 : (endPos - begPos) / parkingLength),
      59        66977 :     myColor(color),
      60        66977 :     myAngle(DEG2RAD(angle)),
      61              :     // see MSVehicleControl defContainerType
      62        66977 :     myTransportableDepth(element == SUMO_TAG_CONTAINER_STOP ? SUMO_const_waitingContainerDepth : SUMO_const_waitingPersonDepth),
      63       133954 :     myTransportableWidth(getDefaultTransportableWidth(myElement)) {
      64        66977 :     computeLastFreePos();
      65      3197269 :     for (int i = 0; i < capacity; i++) {
      66              :         myWaitingSpots.insert(i);
      67              :     }
      68        66977 : }
      69              : 
      70              : 
      71       239068 : MSStoppingPlace::~MSStoppingPlace() {}
      72              : 
      73              : 
      74              : double
      75       107524 : MSStoppingPlace::getDefaultTransportableWidth(SumoXMLTag element) {
      76              :     return element == SUMO_TAG_CONTAINER_STOP
      77       107524 :            ? SUMO_const_waitingContainerWidth
      78       107524 :            : SUMO_const_waitingPersonWidth;
      79              : 
      80              : }
      81              : 
      82              : void
      83        52696 : MSStoppingPlace::finishedLoading() {
      84       105392 :     const std::string waitingWidth = getParameter("waitingWidth");
      85        52696 :     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       105392 :     const std::string waitingDepth = getParameter("waitingDepth");
      93        52696 :     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        52696 : }
     101              : 
     102              : 
     103              : const MSLane&
     104      1153066 : MSStoppingPlace::getLane() const {
     105      1153066 :     return myLane;
     106              : }
     107              : 
     108              : 
     109              : double
     110       927900 : MSStoppingPlace::getBeginLanePosition() const {
     111       927900 :     return myBegPos;
     112              : }
     113              : 
     114              : 
     115              : double
     116       279978 : MSStoppingPlace::getEndLanePosition() const {
     117       279978 :     return myEndPos;
     118              : }
     119              : 
     120              : Position
     121         3359 : MSStoppingPlace::getCenterPos() const {
     122         3359 :     return myLane.getShape().positionAtOffset(myLane.interpolateLanePosToGeometryPos((myBegPos + myEndPos) / 2),
     123         3359 :             myLane.getWidth() / 2 + 0.5);
     124              : }
     125              : 
     126              : 
     127              : void
     128        21968 : MSStoppingPlace::enter(SUMOVehicle* veh, bool parking) {
     129        21968 :     double beg = veh->getPositionOnLane() + veh->getVehicleType().getMinGap() * (parking ? myParkingFactor : 1);
     130        21968 :     double end = beg - veh->getVehicleType().getLengthWithGap() * (parking ? myParkingFactor : 1);
     131        21968 :     myEndPositions[veh] = std::make_pair(beg, end);
     132        21968 :     computeLastFreePos();
     133        21968 : }
     134              : 
     135              : 
     136              : double
     137      3759643 : MSStoppingPlace::getLastFreePos(const SUMOVehicle& forVehicle, double /*brakePos*/) const {
     138      3759643 :     if (getStoppedVehicleNumber() > 0) {
     139      2039084 :         const double vehGap = forVehicle.getVehicleType().getMinGap();
     140      2039084 :         double pos = myLastFreePos - vehGap - NUMERICAL_EPS;
     141         1561 :         if (myParkingFactor < 1 && myLastParking != nullptr && forVehicle.hasStops() && (forVehicle.getStops().front().pars.parking == ParkingType::ONROAD)
     142      2039426 :                 && 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      2039084 :         if (!fits(pos, forVehicle)) {
     148              :             // try to find a place ahead of the waiting vehicles
     149      1853214 :             const double vehLength = forVehicle.getVehicleType().getLength() * myParkingFactor;
     150              :             std::vector<std::pair<double, std::pair<double, const SUMOVehicle*> > > spaces;
     151      5142897 :             for (auto it : myEndPositions) {
     152      3289683 :                 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      1853214 :             std::sort(spaces.begin(), spaces.end());
     156      1853214 :             std::reverse(spaces.begin(), spaces.end());
     157      1853214 :             double prev = myEndPos;
     158      4883789 :             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      3483991 :                 if (prev - it.first + NUMERICAL_EPS >= vehLength && (
     163       228691 :                             it.second.second->isParking()
     164         4075 :                             || it.second.second->remainingStopDuration() > TIME2STEPS(10))) {
     165              :                     return prev;
     166              :                 }
     167      3030575 :                 prev = it.second.first - vehGap;
     168              :             }
     169      1628489 :             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      1853214 :         }
     174      1814359 :         return pos;
     175              :     }
     176      1720559 :     return myLastFreePos;
     177              : }
     178              : 
     179              : bool
     180      3717922 : 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      3717922 :     return pos + POSITION_EPS >= myEndPos || (pos - myBegPos >= veh.getVehicleType().getLength() * myParkingFactor / 2);
     184              : }
     185              : 
     186              : double
     187       112332 : MSStoppingPlace::getWaitingPositionOnLane(MSTransportable* t) const {
     188              :     auto it = myWaitingTransportables.find(t);
     189       112332 :     if (it != myWaitingTransportables.end() && it->second >= 0) {
     190        36729 :         return myEndPos - (0.5 + (it->second) % getTransportablesAbreast()) * myTransportableWidth;
     191              :     } else {
     192        75603 :         return (myEndPos + myBegPos) / 2;
     193              :     }
     194              : }
     195              : 
     196              : 
     197              : int
     198        40547 : MSStoppingPlace::getDefaultTransportablesAbreast(double length, SumoXMLTag element) {
     199        40547 :     return MAX2(1, (int)floor(length / getDefaultTransportableWidth(element)));
     200              : }
     201              : 
     202              : int
     203        69756 : MSStoppingPlace::getTransportablesAbreast() const {
     204        69756 :     return MAX2(1, (int)floor((myEndPos - myBegPos) / myTransportableWidth));
     205              : }
     206              : 
     207              : Position
     208        88573 : MSStoppingPlace::getWaitPosition(MSTransportable* t) const {
     209        88573 :     double lanePos = getWaitingPositionOnLane(t);
     210              :     int row = 0;
     211              :     auto it = myWaitingTransportables.find(t);
     212        88573 :     if (it != myWaitingTransportables.end()) {
     213        31214 :         if (it->second >= 0) {
     214        31214 :             row = int(it->second / getTransportablesAbreast());
     215              :         } else {
     216              :             // invalid position, draw outside bounds
     217            0 :             row = 1 + myTransportableCapacity / getTransportablesAbreast();
     218              :         }
     219              :     }
     220        88573 :     const double lefthandSign = (MSGlobals::gLefthand ? -1 : 1);
     221        88573 :     return myLane.getShape().positionAtOffset(myLane.interpolateLanePosToGeometryPos(lanePos),
     222        88573 :             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       128866 : MSStoppingPlace::hasSpaceForTransportable() const {
     247       128866 :     return myWaitingSpots.size() > 0;
     248              : }
     249              : 
     250              : bool
     251       128866 : MSStoppingPlace::addTransportable(const MSTransportable* p) {
     252              :     int spot = -1;
     253       128866 :     if (!hasSpaceForTransportable()) {
     254              :         return false;
     255              :     }
     256        88701 :     spot = *myWaitingSpots.begin();
     257              :     myWaitingSpots.erase(myWaitingSpots.begin());
     258        88701 :     myWaitingTransportables[p] = spot;
     259        88701 :     return true;
     260              : }
     261              : 
     262              : 
     263              : void
     264       195418 : MSStoppingPlace::removeTransportable(const MSTransportable* p) {
     265              :     auto i = myWaitingTransportables.find(p);
     266       195418 :     if (i != myWaitingTransportables.end()) {
     267        88534 :         if (i->second >= 0) {
     268        88534 :             myWaitingSpots.insert(i->second);
     269              :         }
     270              :         myWaitingTransportables.erase(i);
     271              :     }
     272       195418 : }
     273              : 
     274              : 
     275              : void
     276        21675 : MSStoppingPlace::leaveFrom(SUMOVehicle* what) {
     277              :     assert(myEndPositions.find(what) != myEndPositions.end());
     278              :     myEndPositions.erase(myEndPositions.find(what));
     279        21675 :     computeLastFreePos();
     280        21675 : }
     281              : 
     282              : 
     283              : void
     284       110670 : MSStoppingPlace::computeLastFreePos() {
     285       110670 :     myLastFreePos = myEndPos;
     286       110670 :     myLastParking = nullptr;
     287       139945 :     for (auto item : myEndPositions) {
     288              :         // vehicle might be stopped beyond myEndPos
     289        29275 :         if (myLastFreePos >= item.second.second || myLastFreePos == myEndPos) {
     290        26325 :             myLastFreePos = item.second.second;
     291        26325 :             if (item.first->isStoppedParking()) {
     292         5900 :                 myLastParking = item.first;
     293              :             }
     294              :         }
     295              :     }
     296       110670 : }
     297              : 
     298              : 
     299              : double
     300        64404 : MSStoppingPlace::getAccessPos(const MSEdge* edge, SumoRNG* rng) const {
     301        64404 :     if (edge == &myLane.getEdge()) {
     302        58024 :         return (myBegPos + myEndPos) / 2.;
     303              :     }
     304         8033 :     for (const auto& access : myAccessPos) {
     305         6757 :         if (edge == &access.lane->getEdge()) {
     306         5104 :             if (rng == nullptr || access.startPos == access.endPos) {
     307         4346 :                 return access.endPos;
     308              :             }
     309          758 :             return RandHelper::rand(access.startPos, access.endPos, rng);
     310              :         }
     311              :     }
     312              :     return -1.;
     313              : }
     314              : 
     315              : 
     316              : const MSStoppingPlace::Access*
     317        59322 : MSStoppingPlace::getAccess(const MSEdge* edge) const {
     318        62667 :     for (const auto& access : myAccessPos) {
     319         7556 :         if (edge == &access.lane->getEdge()) {
     320              :             return &access;
     321              :         }
     322              :     }
     323              :     return nullptr;
     324              : }
     325              : 
     326              : 
     327              : const std::string&
     328         1413 : MSStoppingPlace::getMyName() const {
     329         1413 :     return myName;
     330              : }
     331              : 
     332              : 
     333              : const RGBColor&
     334        60133 : MSStoppingPlace::getColor() const {
     335        60133 :     return myColor;
     336              : }
     337              : 
     338              : 
     339              : bool
     340         2302 : MSStoppingPlace::addAccess(MSLane* const lane, const double startPos, const double endPos, double length, const MSStoppingPlace::AccessExit exit) {
     341              :     // prevent multiple accesses on the same lane
     342         3987 :     for (const auto& access : myAccessPos) {
     343         1692 :         if (lane == access.lane) {
     344              :             return false;
     345              :         }
     346              :     }
     347         2295 :     if (length < 0.) {
     348         1429 :         const Position accPos = lane->geometryPositionAtOffset((startPos + endPos) / 2.);
     349         1429 :         const Position stopPos = myLane.geometryPositionAtOffset((myBegPos + myEndPos) / 2.);
     350         1429 :         length = accPos.distanceTo(stopPos);
     351              :     }
     352         2295 :     myAccessPos.push_back({lane, startPos, endPos, length, exit});
     353         2295 :     return true;
     354              : }
     355              : 
     356              : 
     357              : std::vector<const SUMOVehicle*>
     358          760 : MSStoppingPlace::getStoppedVehicles() const {
     359              :     std::vector<const SUMOVehicle*> result;
     360         1050 :     for (auto item : myEndPositions) {
     361          290 :         result.push_back(item.first);
     362              :     }
     363          760 :     return result;
     364            0 : }
     365              : 
     366              : 
     367              : void
     368          109 : MSStoppingPlace::getWaitingPersonIDs(std::vector<std::string>& into) const {
     369          236 :     for (auto item : myWaitingTransportables) {
     370          127 :         into.push_back(item.first->getID());
     371              :     }
     372          109 :     std::sort(into.begin(), into.end());
     373          109 : }
     374              : 
     375              : 
     376              : void
     377           50 : MSStoppingPlace::clearState() {
     378              :     myEndPositions.clear();
     379              :     myWaitingTransportables.clear();
     380           50 :     computeLastFreePos();
     381           50 : }
     382              : 
     383              : 
     384              : /****************************************************************************/
        

Generated by: LCOV version 2.0-1