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 82386 : 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 82386 : double angle) :
50 : Named(id),
51 82386 : myElement(element),
52 164772 : myLines(lines), myLane(lane),
53 82386 : myBegPos(begPos), myEndPos(endPos),
54 82386 : myLastFreePos(endPos),
55 82386 : myLastParking(nullptr),
56 82386 : myName(name),
57 82386 : myTransportableCapacity(capacity),
58 82386 : myParkingFactor(parkingLength <= 0 ? 1 : (endPos - begPos) / parkingLength),
59 82386 : myColor(color),
60 82386 : myAngle(DEG2RAD(angle)),
61 : // see MSVehicleControl defContainerType
62 82386 : myTransportableDepth(element == SUMO_TAG_CONTAINER_STOP ? SUMO_const_waitingContainerDepth : SUMO_const_waitingPersonDepth),
63 164772 : myTransportableWidth(getDefaultTransportableWidth(myElement)) {
64 82386 : computeLastFreePos();
65 3537036 : for (int i = 0; i < capacity; i++) {
66 : myWaitingSpots.insert(i);
67 : }
68 82386 : }
69 :
70 :
71 293939 : MSStoppingPlace::~MSStoppingPlace() {}
72 :
73 :
74 : double
75 132464 : MSStoppingPlace::getDefaultTransportableWidth(SumoXMLTag element) {
76 : return element == SUMO_TAG_CONTAINER_STOP
77 132464 : ? SUMO_const_waitingContainerWidth
78 132464 : : SUMO_const_waitingPersonWidth;
79 :
80 : }
81 :
82 : void
83 65184 : MSStoppingPlace::finishedLoading() {
84 130368 : const std::string waitingWidth = getParameter("waitingWidth");
85 65184 : 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 130368 : const std::string waitingDepth = getParameter("waitingDepth");
93 65184 : 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 65184 : }
101 :
102 :
103 : const MSLane&
104 1310565 : MSStoppingPlace::getLane() const {
105 1310565 : return myLane;
106 : }
107 :
108 :
109 : double
110 956622 : MSStoppingPlace::getBeginLanePosition() const {
111 956622 : return myBegPos;
112 : }
113 :
114 :
115 : double
116 314608 : MSStoppingPlace::getEndLanePosition() const {
117 314608 : return myEndPos;
118 : }
119 :
120 : Position
121 3361 : MSStoppingPlace::getCenterPos() const {
122 3361 : return myLane.getShape().positionAtOffset(myLane.interpolateLanePosToGeometryPos((myBegPos + myEndPos) / 2),
123 3361 : myLane.getWidth() / 2 + 0.5);
124 : }
125 :
126 :
127 : void
128 22286 : MSStoppingPlace::enter(SUMOVehicle* veh, const bool parking) {
129 22286 : const double beg = veh->getPositionOnLane() + veh->getVehicleType().getMinGap() * (parking ? myParkingFactor : 1);
130 22286 : const double end = beg - veh->getVehicleType().getLengthWithGap() * (parking ? myParkingFactor : 1);
131 22286 : myEndPositions[veh] = std::make_pair(beg, end);
132 22286 : computeLastFreePos();
133 22286 : }
134 :
135 :
136 : double
137 4305991 : MSStoppingPlace::getLastFreePos(const SUMOVehicle& forVehicle, double /*brakePos*/) const {
138 4305991 : if (getStoppedVehicleNumber() > 0) {
139 2586264 : const double vehGap = forVehicle.getVehicleType().getMinGap();
140 2586264 : double pos = myLastFreePos - vehGap - NUMERICAL_EPS;
141 1561 : if (myParkingFactor < 1 && myLastParking != nullptr && forVehicle.hasStops() && (forVehicle.getStops().front().pars.parking == ParkingType::ONROAD)
142 2586606 : && 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 2586264 : if (!fits(pos, forVehicle)) {
148 : // try to find a place ahead of the waiting vehicles
149 2393165 : const double vehLength = forVehicle.getVehicleType().getLength() * myParkingFactor;
150 : std::vector<std::pair<double, std::pair<double, const SUMOVehicle*> > > spaces;
151 6842456 : for (auto it : myEndPositions) {
152 4449291 : 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 2393165 : std::sort(spaces.begin(), spaces.end());
156 2393165 : std::reverse(spaces.begin(), spaces.end());
157 2393165 : double prev = myEndPos;
158 6557081 : 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 4611507 : if (prev - it.first + NUMERICAL_EPS >= vehLength && (
163 225786 : it.second.second->isParking()
164 4090 : || it.second.second->remainingStopDuration() > TIME2STEPS(10))) {
165 : return prev;
166 : }
167 4163916 : prev = it.second.first - vehGap;
168 : }
169 2171360 : 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 2393165 : }
174 2364459 : return pos;
175 : }
176 1719727 : return myLastFreePos;
177 : }
178 :
179 : bool
180 4264442 : 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 4264442 : return pos + POSITION_EPS >= myEndPos || (pos - myBegPos >= veh.getVehicleType().getLength() * myParkingFactor / 2);
184 : }
185 :
186 : double
187 112571 : MSStoppingPlace::getWaitingPositionOnLane(MSTransportable* t) const {
188 : auto it = myWaitingTransportables.find(t);
189 112571 : if (it != myWaitingTransportables.end() && it->second >= 0) {
190 36700 : return myEndPos - (0.5 + (it->second) % getTransportablesAbreast()) * myTransportableWidth;
191 : } else {
192 75871 : return (myEndPos + myBegPos) / 2;
193 : }
194 : }
195 :
196 :
197 : int
198 50078 : MSStoppingPlace::getDefaultTransportablesAbreast(double length, SumoXMLTag element) {
199 50078 : return MAX2(1, (int)floor(length / getDefaultTransportableWidth(element)));
200 : }
201 :
202 : int
203 70011 : MSStoppingPlace::getTransportablesAbreast() const {
204 70011 : return MAX2(1, (int)floor((myEndPos - myBegPos) / myTransportableWidth));
205 : }
206 :
207 : Position
208 88747 : MSStoppingPlace::getWaitPosition(MSTransportable* t) const {
209 88747 : double lanePos = getWaitingPositionOnLane(t);
210 : int row = 0;
211 : auto it = myWaitingTransportables.find(t);
212 88747 : if (it != myWaitingTransportables.end()) {
213 31229 : if (it->second >= 0) {
214 31229 : row = int(it->second / getTransportablesAbreast());
215 : } else {
216 : // invalid position, draw outside bounds
217 0 : row = 1 + myTransportableCapacity / getTransportablesAbreast();
218 : }
219 : }
220 88747 : const double lefthandSign = (MSGlobals::gLefthand ? -1 : 1);
221 88747 : return myLane.getShape().positionAtOffset(myLane.interpolateLanePosToGeometryPos(lanePos),
222 88747 : 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 130414 : MSStoppingPlace::hasSpaceForTransportable() const {
247 130414 : return myWaitingSpots.size() > 0;
248 : }
249 :
250 : bool
251 130414 : MSStoppingPlace::addTransportable(const MSTransportable* p) {
252 : int spot = -1;
253 130414 : if (!hasSpaceForTransportable()) {
254 : return false;
255 : }
256 89940 : spot = *myWaitingSpots.begin();
257 : myWaitingSpots.erase(myWaitingSpots.begin());
258 89940 : myWaitingTransportables[p] = spot;
259 89940 : return true;
260 : }
261 :
262 :
263 : void
264 197167 : MSStoppingPlace::removeTransportable(const MSTransportable* p) {
265 : auto i = myWaitingTransportables.find(p);
266 197167 : if (i != myWaitingTransportables.end()) {
267 89899 : if (i->second >= 0) {
268 89899 : myWaitingSpots.insert(i->second);
269 : }
270 : myWaitingTransportables.erase(i);
271 : }
272 197167 : }
273 :
274 :
275 : void
276 21934 : MSStoppingPlace::leaveFrom(SUMOVehicle* what) {
277 : assert(myEndPositions.find(what) != myEndPositions.end());
278 : myEndPositions.erase(myEndPositions.find(what));
279 21934 : computeLastFreePos();
280 21934 : }
281 :
282 :
283 : void
284 126656 : MSStoppingPlace::computeLastFreePos() {
285 126656 : myLastFreePos = myEndPos;
286 126656 : myLastParking = nullptr;
287 156329 : for (auto item : myEndPositions) {
288 : // vehicle might be stopped beyond myEndPos
289 29673 : if (myLastFreePos >= item.second.second || myLastFreePos == myEndPos) {
290 26657 : myLastFreePos = item.second.second;
291 26657 : if (item.first->isStoppedParking()) {
292 6095 : myLastParking = item.first;
293 : }
294 : }
295 : }
296 126656 : }
297 :
298 :
299 : double
300 63757 : MSStoppingPlace::getAccessPos(const MSEdge* edge, SumoRNG* rng) const {
301 63757 : if (edge == &myLane.getEdge()) {
302 58135 : return (myBegPos + myEndPos) / 2.;
303 : }
304 5861 : for (const auto& access : myAccessPos) {
305 4723 : if (edge == &access.lane->getEdge()) {
306 4484 : if (rng == nullptr || access.startPos == access.endPos) {
307 3726 : 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 59748 : MSStoppingPlace::getAccess(const MSEdge* edge) const {
318 61755 : for (const auto& access : myAccessPos) {
319 5801 : if (edge == &access.lane->getEdge()) {
320 : return &access;
321 : }
322 : }
323 : return nullptr;
324 : }
325 :
326 :
327 : const std::string&
328 161450 : MSStoppingPlace::getMyName() const {
329 161450 : return myName;
330 : }
331 :
332 :
333 : const RGBColor&
334 72712 : MSStoppingPlace::getColor() const {
335 72712 : return myColor;
336 : }
337 :
338 :
339 : bool
340 2183 : 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 3868 : for (const auto& access : myAccessPos) {
343 1692 : if (lane == access.lane) {
344 : return false;
345 : }
346 : }
347 2176 : if (length < 0.) {
348 1310 : const Position accPos = lane->geometryPositionAtOffset((startPos + endPos) / 2.);
349 1310 : const Position stopPos = myLane.geometryPositionAtOffset((myBegPos + myEndPos) / 2.);
350 1310 : length = accPos.distanceTo(stopPos);
351 : }
352 2176 : myAccessPos.push_back({lane, startPos, endPos, length, exit});
353 2176 : return true;
354 : }
355 :
356 :
357 : std::vector<const SUMOVehicle*>
358 720 : MSStoppingPlace::getStoppedVehicles() const {
359 : std::vector<const SUMOVehicle*> result;
360 1000 : for (auto item : myEndPositions) {
361 280 : result.push_back(item.first);
362 : }
363 720 : return result;
364 0 : }
365 :
366 :
367 : void
368 89 : MSStoppingPlace::getWaitingPersonIDs(std::vector<std::string>& into) const {
369 196 : for (auto item : myWaitingTransportables) {
370 107 : into.push_back(item.first->getID());
371 : }
372 89 : std::sort(into.begin(), into.end());
373 89 : }
374 :
375 :
376 : void
377 50 : MSStoppingPlace::clearState() {
378 : myEndPositions.clear();
379 : myWaitingTransportables.clear();
380 50 : computeLastFreePos();
381 50 : }
382 :
383 :
384 : /****************************************************************************/
|