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 9943 : MSIdling_Stop::idle(MSDevice_Taxi* taxi) {
47 9943 : 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 194 : double brakeGap = 0;
55 : std::pair<const MSLane*, double> stopPos;
56 194 : if (MSGlobals::gUseMesoSim) {
57 : // stops are only checked in MESegment::receive so we need to put this onto the next segment
58 59 : MSBaseVehicle& veh = dynamic_cast<MSBaseVehicle&>(taxi->getHolder());
59 59 : MSRouteIterator ri = veh.getCurrentRouteEdge();
60 59 : MESegment* curSeg = MSGlobals::gMesoNet->getSegmentForEdge(**ri, veh.getPositionOnLane());
61 : MESegment* stopSeg = curSeg->getNextSegment();
62 59 : if (stopSeg == nullptr) {
63 3 : if ((ri + 1) != veh.getRoute().end()) {
64 0 : stopSeg = MSGlobals::gMesoNet->getSegmentForEdge(**(ri + 1), 0);
65 : } else {
66 9 : 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 56 : MESegment* seg = MSGlobals::gMesoNet->getSegmentForEdge(stopEdge);
74 112 : while (seg != stopSeg) {
75 56 : stopOffset += seg->getLength();
76 : seg = seg->getNextSegment();
77 : }
78 : stopPos = std::make_pair(stopEdge.getLanes()[0], stopOffset);
79 : } else {
80 135 : MSVehicle& veh = dynamic_cast<MSVehicle&>(taxi->getHolder());
81 135 : brakeGap = veh.getCarFollowModel().brakeGap(veh.getSpeed(), veh.getCarFollowModel().getMaxDecel(), 0.0);
82 135 : stopPos = veh.getLanePosAfterDist(brakeGap);
83 : }
84 191 : if (stopPos.first != nullptr) {
85 191 : SUMOVehicleParameter::Stop stop;
86 191 : if (MSGlobals::gUseMesoSim) {
87 : stop.edge = stopPos.first->getEdge().getID();
88 : } else {
89 : stop.lane = stopPos.first->getID();
90 : }
91 191 : stop.startPos = MAX2(0.0, stopPos.second - POSITION_EPS);
92 191 : stop.endPos = stopPos.second;
93 191 : if (MSGlobals::gUseMesoSim) {
94 : // meso needs the stop to be on the next segment
95 56 : stop.startPos += POSITION_EPS;
96 56 : stop.endPos += POSITION_EPS;
97 : }
98 191 : if (taxi->getHolder().getVehicleType().getContainerCapacity() > 0) {
99 24 : stop.containerTriggered = true;
100 : } else {
101 167 : stop.triggered = true;
102 : }
103 : stop.actType = "idling";
104 191 : stop.parking = ParkingType::OFFROAD;
105 191 : taxi->getHolder().addTraciStop(stop, errorOut);
106 191 : if (errorOut != "") {
107 0 : WRITE_WARNING(errorOut);
108 : }
109 191 : } else {
110 0 : WRITE_WARNINGF(TL("Idle taxi '%' could not stop within %m"), taxi->getHolder().getID(), toString(brakeGap));
111 : }
112 : } else {
113 9749 : MSStop& stop = taxi->getHolder().getNextStop();
114 : #ifdef DEBUG_IDLING
115 : if (DEBUG_COND(taxi)) {
116 : std::cout << SIMTIME << " taxi=" << taxi->getHolder().getID() << " MSIdling_Stop reusing stop with duration " << time2string(stop.duration) << "\n";
117 : }
118 : #endif
119 9749 : if (taxi->getHolder().getVehicleType().getContainerCapacity() > 0) {
120 636 : stop.containerTriggered = true;
121 : } else {
122 9113 : stop.triggered = true;
123 : }
124 : }
125 : }
126 :
127 :
128 : // ===========================================================================
129 : // MSIdling_RandomCircling methods
130 : // ===========================================================================
131 :
132 : void
133 90553 : MSIdling_RandomCircling::idle(MSDevice_Taxi* taxi) {
134 : SUMOVehicle& veh = taxi->getHolder();
135 90553 : ConstMSEdgeVector edges = veh.getRoute().getEdges();
136 : ConstMSEdgeVector newEdges;
137 90553 : double remainingDist = -veh.getPositionOnLane();
138 : int remainingEdges = 0;
139 90553 : int routePos = veh.getRoutePosition();
140 90553 : const int routeLength = (int)edges.size();
141 298510 : while (routePos + 1 < routeLength && (remainingEdges < 2 || remainingDist < 200)) {
142 207957 : const MSEdge* edge = edges[routePos];
143 207957 : remainingDist += edge->getLength();
144 207957 : remainingEdges++;
145 : routePos++;
146 207957 : newEdges.push_back(edge);
147 : }
148 90553 : const MSEdge* lastEdge = edges.back();
149 90553 : newEdges.push_back(lastEdge);
150 : int added = 0;
151 97781 : while (remainingEdges < 2 || remainingDist < 200) {
152 7228 : remainingDist += lastEdge->getLength();
153 7228 : remainingEdges++;
154 7228 : MSEdgeVector successors = lastEdge->getSuccessors(veh.getVClass());
155 26456 : for (auto it = successors.begin(); it != successors.end();) {
156 19228 : if ((*it)->getFunction() == SumoXMLEdgeFunc::CONNECTOR) {
157 : it = successors.erase(it);
158 : } else {
159 : it++;
160 : }
161 : }
162 7228 : if (successors.size() == 0) {
163 0 : WRITE_WARNINGF(TL("Vehicle '%' ends idling in a cul-de-sac"), veh.getID());
164 : break;
165 : } else {
166 7228 : int nextIndex = RandHelper::rand((int)successors.size(), veh.getRNG());
167 7228 : newEdges.push_back(successors[nextIndex]);
168 7228 : lastEdge = newEdges.back();
169 7228 : added++;
170 : }
171 7228 : }
172 90553 : if (added > 0) {
173 : //std::cout << SIMTIME << " circleVeh=" << veh.getID() << " newEdges=" << toString(newEdges) << "\n";
174 13686 : veh.replaceRouteEdges(newEdges, -1, 0, "taxi:idling:randomCircling", false, false, false);
175 : }
176 90553 : }
177 :
178 : // ===========================================================================
179 : // MSIdling_TaxiStand methods
180 : // ===========================================================================
181 :
182 : void
183 6615 : MSIdling_TaxiStand::idle(MSDevice_Taxi* taxi) {
184 6615 : MSBaseVehicle& veh = dynamic_cast<MSBaseVehicle&>(taxi->getHolder());
185 :
186 6615 : const MSTriggeredRerouter::RerouteInterval* rerouteDef = myRerouter->getCurrentReroute(SIMSTEP);
187 6615 : if (rerouteDef == nullptr || rerouteDef->parkProbs.getVals().size() == 0) {
188 0 : if (!myHaveWarned) {
189 0 : WRITE_WARNINGF(TL("Could not determine taxi stand for vehicle '%' at time=%"), veh.getID(), time2string(SIMSTEP));
190 0 : myHaveWarned = true;
191 : }
192 0 : return;
193 : }
194 : MSStop* lastStop = nullptr;
195 6615 : if (veh.hasStops()) {
196 6561 : lastStop = &veh.getStop((int)veh.getStops().size() - 1);
197 : }
198 6561 : if (lastStop == nullptr || lastStop->parkingarea == nullptr) {
199 137 : const MSParkingArea* pa = dynamic_cast<MSParkingArea*>(rerouteDef->parkProbs.getVals().front().first);
200 137 : SUMOVehicleParameter::Stop stop;
201 137 : stop.lane = pa->getLane().getID();
202 137 : stop.startPos = pa->getBeginLanePosition();
203 137 : stop.endPos = pa->getEndLanePosition();
204 :
205 137 : if (taxi->getHolder().getVehicleType().getContainerCapacity() > 0) {
206 0 : stop.containerTriggered = true;
207 : } else {
208 137 : stop.triggered = true;
209 : }
210 : stop.actType = "idling";
211 : stop.parkingarea = pa->getID();
212 137 : stop.parking = ParkingType::OFFROAD;
213 137 : const int nextStopIndex = (int)veh.getStops().size();
214 : std::string error;
215 137 : if (!veh.insertStop(nextStopIndex, stop, "taxi:taxistand", false, error)) {
216 0 : WRITE_WARNING("Stop insertion failed for idling taxi '" + veh.getID() + "' (" + error + ").");
217 : } else {
218 : //std::cout << SIMTIME << " taxistandsVeh=" << veh.getID() << " driving to parkingArea " << pa->getID() << "\n";
219 137 : veh.activateReminders(MSMoveReminder::NOTIFICATION_PARKING_REROUTE, &pa->getLane());
220 : }
221 137 : } else {
222 : //std::cout << SIMTIME << " taxistandsVeh=" << veh.getID() << " already driving to parkingArea\n";
223 : }
224 : }
225 :
226 :
227 :
228 : /****************************************************************************/
|