Line data Source code
1 : /****************************************************************************/
2 : // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
3 : // Copyright (C) 2005-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 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/common/RGBColor.h>
29 : #include <microsim/transportables/MSTransportable.h>
30 : #include <microsim/MSGlobals.h>
31 : #include <microsim/MSVehicleType.h>
32 : #include <microsim/MSNet.h>
33 : #include <microsim/MSLane.h>
34 : #include <microsim/MSStop.h>
35 : #include "MSStoppingPlace.h"
36 :
37 : // ===========================================================================
38 : // method definitions
39 : // ===========================================================================
40 63589 : MSStoppingPlace::MSStoppingPlace(const std::string& id,
41 : SumoXMLTag element,
42 : const std::vector<std::string>& lines,
43 : MSLane& lane,
44 : double begPos, double endPos, const std::string name,
45 : int capacity,
46 : double parkingLength,
47 63589 : const RGBColor& color) :
48 : Named(id),
49 63589 : myElement(element),
50 127178 : myLines(lines), myLane(lane),
51 63589 : myBegPos(begPos), myEndPos(endPos),
52 63589 : myLastFreePos(endPos),
53 63589 : myLastParking(nullptr),
54 63589 : myName(name),
55 63589 : myTransportableCapacity(capacity),
56 63589 : myParkingFactor(parkingLength <= 0 ? 1 : (endPos - begPos) / parkingLength),
57 63589 : myColor(color),
58 : // see MSVehicleControl defContainerType
59 180697 : myTransportableDepth(element == SUMO_TAG_CONTAINER_STOP ? SUMO_const_waitingContainerDepth : SUMO_const_waitingPersonDepth) {
60 63589 : computeLastFreePos();
61 2994666 : for (int i = 0; i < capacity; i++) {
62 : myWaitingSpots.insert(i);
63 : }
64 63589 : }
65 :
66 :
67 227193 : MSStoppingPlace::~MSStoppingPlace() {}
68 :
69 :
70 : const MSLane&
71 778538 : MSStoppingPlace::getLane() const {
72 778538 : return myLane;
73 : }
74 :
75 :
76 : double
77 381053 : MSStoppingPlace::getBeginLanePosition() const {
78 381053 : return myBegPos;
79 : }
80 :
81 :
82 : double
83 202973 : MSStoppingPlace::getEndLanePosition() const {
84 202973 : return myEndPos;
85 : }
86 :
87 : Position
88 2992 : MSStoppingPlace::getCenterPos() const {
89 2992 : return myLane.getShape().positionAtOffset(myLane.interpolateLanePosToGeometryPos((myBegPos + myEndPos) / 2),
90 2992 : myLane.getWidth() / 2 + 0.5);
91 : }
92 :
93 :
94 : void
95 19187 : MSStoppingPlace::enter(SUMOVehicle* veh, bool parking) {
96 19187 : double beg = veh->getPositionOnLane() + veh->getVehicleType().getMinGap();
97 19187 : double end = beg - veh->getVehicleType().getLengthWithGap() * (parking ? myParkingFactor : 1);
98 19187 : myEndPositions[veh] = std::make_pair(beg, end);
99 19187 : computeLastFreePos();
100 19187 : }
101 :
102 :
103 : double
104 1381866 : MSStoppingPlace::getLastFreePos(const SUMOVehicle& forVehicle, double /*brakePos*/) const {
105 1381866 : if (getStoppedVehicleNumber() > 0) {
106 544938 : const double vehGap = forVehicle.getVehicleType().getMinGap();
107 544938 : double pos = myLastFreePos - vehGap;
108 629 : if (myParkingFactor < 1 && myLastParking != nullptr && forVehicle.hasStops() && (forVehicle.getStops().front().pars.parking == ParkingType::ONROAD)
109 545029 : && myLastParking->remainingStopDuration() < forVehicle.getStops().front().getMinDuration(SIMSTEP)) {
110 : // stop far back enough so that the previous vehicle can leave
111 21 : pos = myLastParking->getPositionOnLane() - myLastParking->getLength() - vehGap - NUMERICAL_EPS;
112 : }
113 544938 : if (forVehicle.getLane() == &myLane && forVehicle.getPositionOnLane() < myEndPos && forVehicle.getPositionOnLane() > myBegPos && forVehicle.getSpeed() <= SUMO_const_haltingSpeed) {
114 45293 : return forVehicle.getPositionOnLane();
115 : }
116 499645 : if (!fits(pos, forVehicle)) {
117 : // try to find a place ahead of the waiting vehicles
118 486741 : const double vehLength = forVehicle.getVehicleType().getLength();
119 : std::vector<std::pair<double, std::pair<double, const SUMOVehicle*> > > spaces;
120 1440957 : for (auto it : myEndPositions) {
121 954216 : spaces.push_back(std::make_pair(it.second.first, std::make_pair(it.second.second, it.first)));
122 : }
123 : // sorted from myEndPos towars myBegPos
124 486741 : std::sort(spaces.begin(), spaces.end());
125 486741 : std::reverse(spaces.begin(), spaces.end());
126 486741 : double prev = myEndPos;
127 1400554 : for (auto it : spaces) {
128 : //if (forVehicle.isSelected()) {
129 : // std::cout << SIMTIME << " fitPosFor " << forVehicle.getID() << " l=" << vehLength << " prev=" << prev << " vehBeg=" << it.first << " vehEnd=" << it.second.first << " found=" << (prev - it.first >= vehLength) << "\n";
130 : //}
131 936939 : if (prev - it.first + NUMERICAL_EPS >= vehLength && (
132 13915 : it.second.second->isParking()
133 4976 : || it.second.second->remainingStopDuration() > TIME2STEPS(10))) {
134 : return prev;
135 : }
136 913813 : prev = it.second.first - vehGap;
137 : }
138 486741 : }
139 490434 : return pos;
140 : }
141 836928 : return myLastFreePos;
142 : }
143 :
144 : bool
145 994616 : MSStoppingPlace::fits(double pos, const SUMOVehicle& veh) const {
146 : // always fit at the default position or if at least half the vehicle length
147 : // is within the stop range (debatable)
148 994616 : return pos + POSITION_EPS >= myEndPos || (pos - myBegPos >= veh.getVehicleType().getLength() * myParkingFactor / 2);
149 : }
150 :
151 : double
152 111398 : MSStoppingPlace::getWaitingPositionOnLane(MSTransportable* t) const {
153 : auto it = myWaitingTransportables.find(t);
154 111398 : const double waitingWidth = myElement == SUMO_TAG_CONTAINER_STOP
155 111398 : ? SUMO_const_waitingContainerWidth
156 : : SUMO_const_waitingPersonWidth;
157 111398 : if (it != myWaitingTransportables.end() && it->second >= 0) {
158 36037 : return myEndPos - (0.5 + (it->second) % getTransportablesAbreast()) * waitingWidth;
159 : } else {
160 75361 : return (myEndPos + myBegPos) / 2;
161 : }
162 : }
163 :
164 :
165 : int
166 107105 : MSStoppingPlace::getTransportablesAbreast(double length, SumoXMLTag element) {
167 107105 : return MAX2(1, (int)floor(length / (element == SUMO_TAG_CONTAINER_STOP
168 107105 : ? SUMO_const_waitingContainerWidth
169 107105 : : SUMO_const_waitingPersonWidth)));
170 : }
171 :
172 : int
173 68482 : MSStoppingPlace::getTransportablesAbreast() const {
174 68482 : return getTransportablesAbreast(myEndPos - myBegPos, myElement);
175 : }
176 :
177 : Position
178 88025 : MSStoppingPlace::getWaitPosition(MSTransportable* t) const {
179 88025 : double lanePos = getWaitingPositionOnLane(t);
180 : int row = 0;
181 : auto it = myWaitingTransportables.find(t);
182 88025 : if (it != myWaitingTransportables.end()) {
183 30787 : if (it->second >= 0) {
184 30787 : row = int(it->second / getTransportablesAbreast());
185 : } else {
186 : // invalid position, draw outside bounds
187 0 : row = 1 + myTransportableCapacity / getTransportablesAbreast();
188 : }
189 : }
190 88025 : const double lefthandSign = (MSGlobals::gLefthand ? -1 : 1);
191 88025 : return myLane.getShape().positionAtOffset(myLane.interpolateLanePosToGeometryPos(lanePos),
192 88025 : lefthandSign * (myLane.getWidth() / 2 + row * myTransportableDepth));
193 : }
194 :
195 :
196 : double
197 0 : MSStoppingPlace::getStoppingPosition(const SUMOVehicle* veh) const {
198 : auto i = myEndPositions.find(veh);
199 0 : if (i != myEndPositions.end()) {
200 0 : return i->second.second;
201 : } else {
202 0 : return getLastFreePos(*veh);
203 : }
204 : }
205 :
206 : std::vector<const MSTransportable*>
207 156 : MSStoppingPlace::getTransportables() const {
208 : std::vector<const MSTransportable*> result;
209 212 : for (auto item : myWaitingTransportables) {
210 56 : result.push_back(item.first);
211 : }
212 156 : return result;
213 0 : }
214 :
215 : bool
216 127204 : MSStoppingPlace::hasSpaceForTransportable() const {
217 127204 : return myWaitingSpots.size() > 0;
218 : }
219 :
220 : bool
221 127204 : MSStoppingPlace::addTransportable(const MSTransportable* p) {
222 : int spot = -1;
223 127204 : if (!hasSpaceForTransportable()) {
224 : return false;
225 : }
226 87862 : spot = *myWaitingSpots.begin();
227 : myWaitingSpots.erase(myWaitingSpots.begin());
228 87862 : myWaitingTransportables[p] = spot;
229 87862 : return true;
230 : }
231 :
232 :
233 : void
234 193935 : MSStoppingPlace::removeTransportable(const MSTransportable* p) {
235 : auto i = myWaitingTransportables.find(p);
236 193935 : if (i != myWaitingTransportables.end()) {
237 87695 : if (i->second >= 0) {
238 87695 : myWaitingSpots.insert(i->second);
239 : }
240 : myWaitingTransportables.erase(i);
241 : }
242 193935 : }
243 :
244 :
245 : void
246 18941 : MSStoppingPlace::leaveFrom(SUMOVehicle* what) {
247 : assert(myEndPositions.find(what) != myEndPositions.end());
248 : myEndPositions.erase(myEndPositions.find(what));
249 18941 : computeLastFreePos();
250 18941 : }
251 :
252 :
253 : void
254 101767 : MSStoppingPlace::computeLastFreePos() {
255 101767 : myLastFreePos = myEndPos;
256 101767 : myLastParking = nullptr;
257 126869 : for (auto item : myEndPositions) {
258 : // vehicle might be stopped beyond myEndPos
259 25102 : if (myLastFreePos >= item.second.second || myLastFreePos == myEndPos) {
260 22579 : myLastFreePos = item.second.second;
261 22579 : if (item.first->isStoppedParking()) {
262 3430 : myLastParking = item.first;
263 : }
264 : }
265 : }
266 101767 : }
267 :
268 :
269 : double
270 62476 : MSStoppingPlace::getAccessPos(const MSEdge* edge, SumoRNG* rng) const {
271 62476 : if (edge == &myLane.getEdge()) {
272 56244 : return (myBegPos + myEndPos) / 2.;
273 : }
274 7741 : for (const auto& access : myAccessPos) {
275 6495 : if (edge == &access.lane->getEdge()) {
276 4986 : if (rng == nullptr || access.startPos == access.endPos) {
277 4228 : return access.endPos;
278 : }
279 758 : return RandHelper::rand(access.startPos, access.endPos, rng);
280 : }
281 : }
282 : return -1.;
283 : }
284 :
285 :
286 : const MSStoppingPlace::Access*
287 57867 : MSStoppingPlace::getAccess(const MSEdge* edge) const {
288 61055 : for (const auto& access : myAccessPos) {
289 7311 : if (edge == &access.lane->getEdge()) {
290 : return &access;
291 : }
292 : }
293 : return nullptr;
294 : }
295 :
296 :
297 : const std::string&
298 1178 : MSStoppingPlace::getMyName() const {
299 1178 : return myName;
300 : }
301 :
302 :
303 : const RGBColor&
304 51675 : MSStoppingPlace::getColor() const {
305 51675 : return myColor;
306 : }
307 :
308 :
309 : bool
310 2169 : MSStoppingPlace::addAccess(MSLane* const lane, const double startPos, const double endPos, double length, const MSStoppingPlace::AccessExit exit) {
311 : // prevent multiple accesses on the same lane
312 4313 : for (const auto& access : myAccessPos) {
313 2151 : if (lane == access.lane) {
314 : return false;
315 : }
316 : }
317 2162 : if (length < 0.) {
318 1087 : const Position accPos = lane->geometryPositionAtOffset((startPos + endPos) / 2.);
319 1087 : const Position stopPos = myLane.geometryPositionAtOffset((myBegPos + myEndPos) / 2.);
320 1087 : length = accPos.distanceTo(stopPos);
321 : }
322 2162 : myAccessPos.push_back({lane, startPos, endPos, length, exit});
323 2162 : return true;
324 : }
325 :
326 :
327 : std::vector<const SUMOVehicle*>
328 602 : MSStoppingPlace::getStoppedVehicles() const {
329 : std::vector<const SUMOVehicle*> result;
330 872 : for (auto item : myEndPositions) {
331 270 : result.push_back(item.first);
332 : }
333 602 : return result;
334 0 : }
335 :
336 :
337 : void
338 101 : MSStoppingPlace::getWaitingPersonIDs(std::vector<std::string>& into) const {
339 228 : for (auto item : myWaitingTransportables) {
340 127 : into.push_back(item.first->getID());
341 : }
342 101 : std::sort(into.begin(), into.end());
343 101 : }
344 :
345 :
346 : void
347 50 : MSStoppingPlace::clearState() {
348 : myEndPositions.clear();
349 : myWaitingTransportables.clear();
350 50 : computeLastFreePos();
351 50 : }
352 :
353 :
354 : /****************************************************************************/
|