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 63723 : 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 63723 : const RGBColor& color) :
48 : Named(id),
49 63723 : myElement(element),
50 127446 : myLines(lines), myLane(lane),
51 63723 : myBegPos(begPos), myEndPos(endPos),
52 63723 : myLastFreePos(endPos),
53 63723 : myLastParking(nullptr),
54 63723 : myName(name),
55 63723 : myTransportableCapacity(capacity),
56 63723 : myParkingFactor(parkingLength <= 0 ? 1 : (endPos - begPos) / parkingLength),
57 63723 : myColor(color),
58 : // see MSVehicleControl defContainerType
59 181094 : myTransportableDepth(element == SUMO_TAG_CONTAINER_STOP ? SUMO_const_waitingContainerDepth : SUMO_const_waitingPersonDepth) {
60 63723 : computeLastFreePos();
61 3000121 : for (int i = 0; i < capacity; i++) {
62 : myWaitingSpots.insert(i);
63 : }
64 63723 : }
65 :
66 :
67 227646 : MSStoppingPlace::~MSStoppingPlace() {}
68 :
69 :
70 : const MSLane&
71 786681 : MSStoppingPlace::getLane() const {
72 786681 : return myLane;
73 : }
74 :
75 :
76 : double
77 383448 : MSStoppingPlace::getBeginLanePosition() const {
78 383448 : return myBegPos;
79 : }
80 :
81 :
82 : double
83 204329 : MSStoppingPlace::getEndLanePosition() const {
84 204329 : 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 19289 : MSStoppingPlace::enter(SUMOVehicle* veh, bool parking) {
96 19289 : double beg = veh->getPositionOnLane() + veh->getVehicleType().getMinGap() * (parking ? myParkingFactor : 1);
97 19289 : double end = beg - veh->getVehicleType().getLengthWithGap() * (parking ? myParkingFactor : 1);
98 19289 : myEndPositions[veh] = std::make_pair(beg, end);
99 19289 : computeLastFreePos();
100 19289 : }
101 :
102 :
103 : double
104 1385963 : MSStoppingPlace::getLastFreePos(const SUMOVehicle& forVehicle, double /*brakePos*/) const {
105 1385963 : if (getStoppedVehicleNumber() > 0) {
106 544949 : const double vehGap = forVehicle.getVehicleType().getMinGap();
107 544949 : double pos = myLastFreePos - vehGap;
108 1659 : if (myParkingFactor < 1 && myLastParking != nullptr && forVehicle.hasStops() && (forVehicle.getStops().front().pars.parking == ParkingType::ONROAD)
109 545495 : && myLastParking->remainingStopDuration() < forVehicle.getStops().front().getMinDuration(SIMSTEP)) {
110 : // stop far back enough so that the previous parking vehicle can leave (even if this vehicle fits, it will
111 : // be a blocker because it stops on the road)
112 266 : pos = MIN2(pos, myLastParking->getPositionOnLane() - myLastParking->getLength() - vehGap - NUMERICAL_EPS);
113 : }
114 544949 : if (forVehicle.getLane() == &myLane && forVehicle.getPositionOnLane() < myEndPos && forVehicle.getPositionOnLane() > myBegPos && forVehicle.getSpeed() <= SUMO_const_haltingSpeed) {
115 45630 : return forVehicle.getPositionOnLane();
116 : }
117 499319 : if (!fits(pos, forVehicle)) {
118 : // try to find a place ahead of the waiting vehicles
119 486317 : const double vehLength = forVehicle.getVehicleType().getLength() * myParkingFactor;
120 : std::vector<std::pair<double, std::pair<double, const SUMOVehicle*> > > spaces;
121 1440219 : for (auto it : myEndPositions) {
122 953902 : spaces.push_back(std::make_pair(it.second.first, std::make_pair(it.second.second, it.first)));
123 : }
124 : // sorted from myEndPos towars myBegPos
125 486317 : std::sort(spaces.begin(), spaces.end());
126 486317 : std::reverse(spaces.begin(), spaces.end());
127 486317 : double prev = myEndPos;
128 1399595 : for (auto it : spaces) {
129 : //if (forVehicle.isSelected()) {
130 : // std::cout << SIMTIME << " fitPosFor " << forVehicle.getID() << " l=" << vehLength << " prev=" << prev << " vehBeg=" << it.first << " vehEnd=" << it.second.first << " found=" << (prev - it.first >= vehLength) << "\n";
131 : //}
132 936720 : if (prev - it.first + NUMERICAL_EPS >= vehLength && (
133 14103 : it.second.second->isParking()
134 5036 : || it.second.second->remainingStopDuration() > TIME2STEPS(10))) {
135 : return prev;
136 : }
137 913278 : prev = it.second.first - vehGap;
138 : }
139 476978 : if (myParkingFactor < 1 && myLastParking != nullptr) {
140 : // stop far back enough so that the previous vehicle can leave
141 488 : pos = MIN2(pos, myLastParking->getPositionOnLane() - myLastParking->getLength() - vehGap - NUMERICAL_EPS);
142 : }
143 486317 : }
144 489980 : return pos;
145 : }
146 841014 : return myLastFreePos;
147 : }
148 :
149 : bool
150 995826 : MSStoppingPlace::fits(double pos, const SUMOVehicle& veh) const {
151 : // always fit at the default position or if at least half the vehicle length
152 : // is within the stop range (debatable)
153 995826 : return pos + POSITION_EPS >= myEndPos || (pos - myBegPos >= veh.getVehicleType().getLength() * myParkingFactor / 2);
154 : }
155 :
156 : double
157 111400 : MSStoppingPlace::getWaitingPositionOnLane(MSTransportable* t) const {
158 : auto it = myWaitingTransportables.find(t);
159 111400 : const double waitingWidth = myElement == SUMO_TAG_CONTAINER_STOP
160 111400 : ? SUMO_const_waitingContainerWidth
161 : : SUMO_const_waitingPersonWidth;
162 111400 : if (it != myWaitingTransportables.end() && it->second >= 0) {
163 36039 : return myEndPos - (0.5 + (it->second) % getTransportablesAbreast()) * waitingWidth;
164 : } else {
165 75361 : return (myEndPos + myBegPos) / 2;
166 : }
167 : }
168 :
169 :
170 : int
171 107254 : MSStoppingPlace::getTransportablesAbreast(double length, SumoXMLTag element) {
172 107254 : return MAX2(1, (int)floor(length / (element == SUMO_TAG_CONTAINER_STOP
173 107254 : ? SUMO_const_waitingContainerWidth
174 107254 : : SUMO_const_waitingPersonWidth)));
175 : }
176 :
177 : int
178 68521 : MSStoppingPlace::getTransportablesAbreast() const {
179 68521 : return getTransportablesAbreast(myEndPos - myBegPos, myElement);
180 : }
181 :
182 : Position
183 88026 : MSStoppingPlace::getWaitPosition(MSTransportable* t) const {
184 88026 : double lanePos = getWaitingPositionOnLane(t);
185 : int row = 0;
186 : auto it = myWaitingTransportables.find(t);
187 88026 : if (it != myWaitingTransportables.end()) {
188 30788 : if (it->second >= 0) {
189 30788 : row = int(it->second / getTransportablesAbreast());
190 : } else {
191 : // invalid position, draw outside bounds
192 0 : row = 1 + myTransportableCapacity / getTransportablesAbreast();
193 : }
194 : }
195 88026 : const double lefthandSign = (MSGlobals::gLefthand ? -1 : 1);
196 88026 : return myLane.getShape().positionAtOffset(myLane.interpolateLanePosToGeometryPos(lanePos),
197 88026 : lefthandSign * (myLane.getWidth() / 2 + row * myTransportableDepth));
198 : }
199 :
200 :
201 : double
202 0 : MSStoppingPlace::getStoppingPosition(const SUMOVehicle* veh) const {
203 : auto i = myEndPositions.find(veh);
204 0 : if (i != myEndPositions.end()) {
205 0 : return i->second.second;
206 : } else {
207 0 : return getLastFreePos(*veh);
208 : }
209 : }
210 :
211 : std::vector<const MSTransportable*>
212 156 : MSStoppingPlace::getTransportables() const {
213 : std::vector<const MSTransportable*> result;
214 212 : for (auto item : myWaitingTransportables) {
215 56 : result.push_back(item.first);
216 : }
217 156 : return result;
218 0 : }
219 :
220 : bool
221 127212 : MSStoppingPlace::hasSpaceForTransportable() const {
222 127212 : return myWaitingSpots.size() > 0;
223 : }
224 :
225 : bool
226 127212 : MSStoppingPlace::addTransportable(const MSTransportable* p) {
227 : int spot = -1;
228 127212 : if (!hasSpaceForTransportable()) {
229 : return false;
230 : }
231 87868 : spot = *myWaitingSpots.begin();
232 : myWaitingSpots.erase(myWaitingSpots.begin());
233 87868 : myWaitingTransportables[p] = spot;
234 87868 : return true;
235 : }
236 :
237 :
238 : void
239 193942 : MSStoppingPlace::removeTransportable(const MSTransportable* p) {
240 : auto i = myWaitingTransportables.find(p);
241 193942 : if (i != myWaitingTransportables.end()) {
242 87701 : if (i->second >= 0) {
243 87701 : myWaitingSpots.insert(i->second);
244 : }
245 : myWaitingTransportables.erase(i);
246 : }
247 193942 : }
248 :
249 :
250 : void
251 19049 : MSStoppingPlace::leaveFrom(SUMOVehicle* what) {
252 : assert(myEndPositions.find(what) != myEndPositions.end());
253 : myEndPositions.erase(myEndPositions.find(what));
254 19049 : computeLastFreePos();
255 19049 : }
256 :
257 :
258 : void
259 102101 : MSStoppingPlace::computeLastFreePos() {
260 102101 : myLastFreePos = myEndPos;
261 102101 : myLastParking = nullptr;
262 127317 : for (auto item : myEndPositions) {
263 : // vehicle might be stopped beyond myEndPos
264 25216 : if (myLastFreePos >= item.second.second || myLastFreePos == myEndPos) {
265 22688 : myLastFreePos = item.second.second;
266 22688 : if (item.first->isStoppedParking()) {
267 3473 : myLastParking = item.first;
268 : }
269 : }
270 : }
271 102101 : }
272 :
273 :
274 : double
275 62478 : MSStoppingPlace::getAccessPos(const MSEdge* edge, SumoRNG* rng) const {
276 62478 : if (edge == &myLane.getEdge()) {
277 56256 : return (myBegPos + myEndPos) / 2.;
278 : }
279 7719 : for (const auto& access : myAccessPos) {
280 6476 : if (edge == &access.lane->getEdge()) {
281 4979 : if (rng == nullptr || access.startPos == access.endPos) {
282 4221 : return access.endPos;
283 : }
284 758 : return RandHelper::rand(access.startPos, access.endPos, rng);
285 : }
286 : }
287 : return -1.;
288 : }
289 :
290 :
291 : const MSStoppingPlace::Access*
292 57876 : MSStoppingPlace::getAccess(const MSEdge* edge) const {
293 61044 : for (const auto& access : myAccessPos) {
294 7288 : if (edge == &access.lane->getEdge()) {
295 : return &access;
296 : }
297 : }
298 : return nullptr;
299 : }
300 :
301 :
302 : const std::string&
303 1183 : MSStoppingPlace::getMyName() const {
304 1183 : return myName;
305 : }
306 :
307 :
308 : const RGBColor&
309 52518 : MSStoppingPlace::getColor() const {
310 52518 : return myColor;
311 : }
312 :
313 :
314 : bool
315 2169 : MSStoppingPlace::addAccess(MSLane* const lane, const double startPos, const double endPos, double length, const MSStoppingPlace::AccessExit exit) {
316 : // prevent multiple accesses on the same lane
317 4313 : for (const auto& access : myAccessPos) {
318 2151 : if (lane == access.lane) {
319 : return false;
320 : }
321 : }
322 2162 : if (length < 0.) {
323 1087 : const Position accPos = lane->geometryPositionAtOffset((startPos + endPos) / 2.);
324 1087 : const Position stopPos = myLane.geometryPositionAtOffset((myBegPos + myEndPos) / 2.);
325 1087 : length = accPos.distanceTo(stopPos);
326 : }
327 2162 : myAccessPos.push_back({lane, startPos, endPos, length, exit});
328 2162 : return true;
329 : }
330 :
331 :
332 : std::vector<const SUMOVehicle*>
333 602 : MSStoppingPlace::getStoppedVehicles() const {
334 : std::vector<const SUMOVehicle*> result;
335 872 : for (auto item : myEndPositions) {
336 270 : result.push_back(item.first);
337 : }
338 602 : return result;
339 0 : }
340 :
341 :
342 : void
343 101 : MSStoppingPlace::getWaitingPersonIDs(std::vector<std::string>& into) const {
344 228 : for (auto item : myWaitingTransportables) {
345 127 : into.push_back(item.first->getID());
346 : }
347 101 : std::sort(into.begin(), into.end());
348 101 : }
349 :
350 :
351 : void
352 40 : MSStoppingPlace::clearState() {
353 : myEndPositions.clear();
354 : myWaitingTransportables.clear();
355 40 : computeLastFreePos();
356 40 : }
357 :
358 :
359 : /****************************************************************************/
|