Line data Source code
1 : /****************************************************************************/ 2 : // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo 3 : // Copyright (C) 2007-2024 German Aerospace Center (DLR) and others. 4 : // This program and the accompanying materials are made available under the 5 : // terms of the Eclipse Public License 2.0 which is available at 6 : // https://www.eclipse.org/legal/epl-2.0/ 7 : // This Source Code may also be made available under the following Secondary 8 : // Licenses when the conditions for such availability set forth in the Eclipse 9 : // Public License 2.0 are satisfied: GNU General Public License, version 2 10 : // or later which is available at 11 : // https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html 12 : // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later 13 : /****************************************************************************/ 14 : /// @file MSIdling.cpp 15 : /// @author Jakob Erdmann 16 : /// @author Mirko Barthauer 17 : /// @date 17.08.2020 18 : /// 19 : // An algorithm that performs Idling for the taxi device 20 : /****************************************************************************/ 21 : #include <config.h> 22 : 23 : #include <limits> 24 : #include <microsim/MSNet.h> 25 : #include <microsim/MSEdge.h> 26 : #include <microsim/MSLane.h> 27 : #include <microsim/MSStop.h> 28 : #include <microsim/MSParkingArea.h> 29 : #include <microsim/transportables/MSTransportable.h> 30 : #include <microsim/trigger/MSTriggeredRerouter.h> 31 : #include <mesosim/MELoop.h> 32 : #include "MSRoutingEngine.h" 33 : #include "MSIdling.h" 34 : 35 : //#define DEBUG_IDLING 36 : //#define DEBUG_COND(obj) (obj->getHolder().getID() == "p0") 37 : //#define DEBUG_COND(obj) (obj->getHolder().isSelected()) 38 : #define DEBUG_COND(obj) (true) 39 : 40 : 41 : // =========================================================================== 42 : // MSIdling_stop methods 43 : // =========================================================================== 44 : 45 : void 46 9005 : MSIdling_Stop::idle(MSDevice_Taxi* taxi) { 47 9005 : if (!taxi->getHolder().hasStops()) { 48 : #ifdef DEBUG_IDLING 49 : if (DEBUG_COND(taxi)) { 50 : std::cout << SIMTIME << " taxi=" << taxi->getHolder().getID() << " MSIdling_Stop add stop\n"; 51 : } 52 : #endif 53 : std::string errorOut; 54 150 : double brakeGap = 0; 55 : std::pair<const MSLane*, double> stopPos; 56 150 : if (MSGlobals::gUseMesoSim) { 57 : // stops are only checked in MESegment::receive so we need to put this onto the next segment 58 44 : MSBaseVehicle& veh = dynamic_cast<MSBaseVehicle&>(taxi->getHolder()); 59 44 : MSRouteIterator ri = veh.getCurrentRouteEdge(); 60 44 : MESegment* curSeg = MSGlobals::gMesoNet->getSegmentForEdge(**ri, veh.getPositionOnLane()); 61 : MESegment* stopSeg = curSeg->getNextSegment(); 62 44 : if (stopSeg == nullptr) { 63 2 : if ((ri + 1) != veh.getRoute().end()) { 64 0 : stopSeg = MSGlobals::gMesoNet->getSegmentForEdge(**(ri + 1), 0); 65 : } else { 66 6 : WRITE_WARNINGF(TL("Idle taxi '%' has no next segment to stop. time=%."), taxi->getHolder().getID(), time2string(SIMSTEP)); 67 : return; 68 : } 69 : } 70 : // determine offset of stopSeg 71 : double stopOffset = 0; 72 : const MSEdge& stopEdge = stopSeg->getEdge(); 73 42 : MESegment* seg = MSGlobals::gMesoNet->getSegmentForEdge(stopEdge); 74 84 : while (seg != stopSeg) { 75 42 : stopOffset += seg->getLength(); 76 : seg = seg->getNextSegment(); 77 : } 78 : stopPos = std::make_pair(stopEdge.getLanes()[0], stopOffset); 79 : } else { 80 106 : MSVehicle& veh = dynamic_cast<MSVehicle&>(taxi->getHolder()); 81 106 : brakeGap = veh.getCarFollowModel().brakeGap(veh.getSpeed()); 82 106 : stopPos = veh.getLanePosAfterDist(brakeGap); 83 : } 84 148 : if (stopPos.first != nullptr) { 85 148 : SUMOVehicleParameter::Stop stop; 86 148 : if (MSGlobals::gUseMesoSim) { 87 : stop.edge = stopPos.first->getEdge().getID(); 88 : } else { 89 : stop.lane = stopPos.first->getID(); 90 : } 91 148 : stop.startPos = stopPos.second; 92 148 : stop.endPos = stopPos.second + POSITION_EPS; 93 148 : if (taxi->getHolder().getVehicleType().getContainerCapacity() > 0) { 94 12 : stop.containerTriggered = true; 95 : } else { 96 136 : stop.triggered = true; 97 : } 98 : stop.actType = "idling"; 99 148 : stop.parking = ParkingType::OFFROAD; 100 148 : taxi->getHolder().addTraciStop(stop, errorOut); 101 148 : if (errorOut != "") { 102 0 : WRITE_WARNING(errorOut); 103 : } 104 148 : } else { 105 0 : WRITE_WARNINGF(TL("Idle taxi '%' could not stop within %m"), taxi->getHolder().getID(), toString(brakeGap)); 106 : } 107 : } else { 108 8855 : MSStop& stop = taxi->getHolder().getNextStop(); 109 : #ifdef DEBUG_IDLING 110 : if (DEBUG_COND(taxi)) { 111 : std::cout << SIMTIME << " taxi=" << taxi->getHolder().getID() << " MSIdling_Stop reusing stop with duration " << time2string(stop.duration) << "\n"; 112 : } 113 : #endif 114 8855 : if (taxi->getHolder().getVehicleType().getContainerCapacity() > 0) { 115 366 : stop.containerTriggered = true; 116 : } else { 117 8489 : stop.triggered = true; 118 : } 119 : } 120 : } 121 : 122 : 123 : // =========================================================================== 124 : // MSIdling_RandomCircling methods 125 : // =========================================================================== 126 : 127 : void 128 111644 : MSIdling_RandomCircling::idle(MSDevice_Taxi* taxi) { 129 : SUMOVehicle& veh = taxi->getHolder(); 130 111644 : ConstMSEdgeVector edges = veh.getRoute().getEdges(); 131 : ConstMSEdgeVector newEdges; 132 111644 : double remainingDist = -veh.getPositionOnLane(); 133 : int remainingEdges = 0; 134 111644 : int routePos = veh.getRoutePosition(); 135 111644 : const int routeLength = (int)edges.size(); 136 363292 : while (routePos + 1 < routeLength && (remainingEdges < 2 || remainingDist < 200)) { 137 251648 : const MSEdge* edge = edges[routePos]; 138 251648 : remainingDist += edge->getLength(); 139 251648 : remainingEdges++; 140 : routePos++; 141 251648 : newEdges.push_back(edge); 142 : } 143 111644 : const MSEdge* lastEdge = edges.back(); 144 111644 : newEdges.push_back(lastEdge); 145 : int added = 0; 146 119954 : while (remainingEdges < 2 || remainingDist < 200) { 147 8310 : remainingDist += lastEdge->getLength(); 148 8310 : remainingEdges++; 149 8310 : MSEdgeVector successors = lastEdge->getSuccessors(veh.getVClass()); 150 28338 : for (auto it = successors.begin(); it != successors.end();) { 151 20028 : if ((*it)->getFunction() == SumoXMLEdgeFunc::CONNECTOR) { 152 : it = successors.erase(it); 153 : } else { 154 : it++; 155 : } 156 : } 157 8310 : if (successors.size() == 0) { 158 0 : WRITE_WARNINGF(TL("Vehicle '%' ends idling in a cul-de-sac"), veh.getID()); 159 : break; 160 : } else { 161 8310 : int nextIndex = RandHelper::rand((int)successors.size(), veh.getRNG()); 162 8310 : newEdges.push_back(successors[nextIndex]); 163 8310 : lastEdge = newEdges.back(); 164 8310 : added++; 165 : } 166 : } 167 111644 : if (added > 0) { 168 : //std::cout << SIMTIME << " circleVeh=" << veh.getID() << " newEdges=" << toString(newEdges) << "\n"; 169 15864 : veh.replaceRouteEdges(newEdges, -1, 0, "taxi:idling:randomCircling", false, false, false); 170 : } 171 111644 : } 172 : 173 : // =========================================================================== 174 : // MSIdling_TaxiStand methods 175 : // =========================================================================== 176 : 177 : void 178 4512 : MSIdling_TaxiStand::idle(MSDevice_Taxi* taxi) { 179 4512 : MSBaseVehicle& veh = dynamic_cast<MSBaseVehicle&>(taxi->getHolder()); 180 : 181 4512 : const MSTriggeredRerouter::RerouteInterval* rerouteDef = myRerouter->getCurrentReroute(SIMSTEP); 182 4512 : if (rerouteDef == nullptr || rerouteDef->parkProbs.getVals().size() == 0) { 183 0 : if (!myHaveWarned) { 184 0 : WRITE_WARNINGF(TL("Could not determine taxi stand for vehicle '%' at time=%"), veh.getID(), time2string(SIMSTEP)); 185 0 : myHaveWarned = true; 186 : } 187 0 : return; 188 : } 189 : MSStop* lastStop = nullptr; 190 4512 : if (veh.hasStops()) { 191 4458 : lastStop = &veh.getStop((int)veh.getStops().size() - 1); 192 : } 193 4458 : if (lastStop == nullptr || lastStop->parkingarea == nullptr) { 194 132 : const MSParkingArea* pa = rerouteDef->parkProbs.getVals().front().first; 195 132 : SUMOVehicleParameter::Stop stop; 196 132 : stop.lane = pa->getLane().getID(); 197 132 : stop.startPos = pa->getBeginLanePosition(); 198 132 : stop.endPos = pa->getEndLanePosition(); 199 : 200 132 : if (taxi->getHolder().getVehicleType().getContainerCapacity() > 0) { 201 0 : stop.containerTriggered = true; 202 : } else { 203 132 : stop.triggered = true; 204 : } 205 : stop.actType = "idling"; 206 : stop.parkingarea = pa->getID(); 207 132 : stop.parking = ParkingType::OFFROAD; 208 132 : const int nextStopIndex = (int)veh.getStops().size(); 209 : std::string error; 210 132 : if (!veh.insertStop(nextStopIndex, stop, "taxi:taxistand", false, error)) { 211 0 : WRITE_WARNING("Stop insertion failed for idling taxi '" + veh.getID() + "' (" + error + ")."); 212 : } else { 213 : //std::cout << SIMTIME << " taxistandsVeh=" << veh.getID() << " driving to parkingArea " << pa->getID() << "\n"; 214 132 : veh.activateReminders(MSMoveReminder::NOTIFICATION_PARKING_REROUTE, &pa->getLane()); 215 : } 216 132 : } else { 217 : //std::cout << SIMTIME << " taxistandsVeh=" << veh.getID() << " already driving to parkingArea\n"; 218 : } 219 : } 220 : 221 : 222 : 223 : /****************************************************************************/