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 : /****************************************************************************/
|