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 64599 : 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 64599 : const RGBColor& color) :
48 : Named(id),
49 64599 : myElement(element),
50 129198 : myLines(lines), myLane(lane),
51 64599 : myBegPos(begPos), myEndPos(endPos),
52 64599 : myLastFreePos(endPos),
53 64599 : myLastParking(nullptr),
54 64599 : myName(name),
55 64599 : myTransportableCapacity(capacity),
56 64599 : myParkingFactor(parkingLength <= 0 ? 1 : (endPos - begPos) / parkingLength),
57 64599 : myColor(color),
58 : // see MSVehicleControl defContainerType
59 183578 : myTransportableDepth(element == SUMO_TAG_CONTAINER_STOP ? SUMO_const_waitingContainerDepth : SUMO_const_waitingPersonDepth) {
60 64599 : computeLastFreePos();
61 3024249 : for (int i = 0; i < capacity; i++) {
62 : myWaitingSpots.insert(i);
63 : }
64 64599 : }
65 :
66 :
67 230763 : MSStoppingPlace::~MSStoppingPlace() {}
68 :
69 :
70 : const MSLane&
71 961261 : MSStoppingPlace::getLane() const {
72 961261 : return myLane;
73 : }
74 :
75 :
76 : double
77 420825 : MSStoppingPlace::getBeginLanePosition() const {
78 420825 : return myBegPos;
79 : }
80 :
81 :
82 : double
83 236480 : MSStoppingPlace::getEndLanePosition() const {
84 236480 : 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 20140 : MSStoppingPlace::enter(SUMOVehicle* veh, bool parking) {
96 20140 : double beg = veh->getPositionOnLane() + veh->getVehicleType().getMinGap() * (parking ? myParkingFactor : 1);
97 20140 : double end = beg - veh->getVehicleType().getLengthWithGap() * (parking ? myParkingFactor : 1);
98 20140 : myEndPositions[veh] = std::make_pair(beg, end);
99 20140 : computeLastFreePos();
100 20140 : }
101 :
102 :
103 : double
104 1935365 : MSStoppingPlace::getLastFreePos(const SUMOVehicle& forVehicle, double /*brakePos*/) const {
105 1935365 : if (getStoppedVehicleNumber() > 0) {
106 1023287 : const double vehGap = forVehicle.getVehicleType().getMinGap();
107 1023287 : double pos = myLastFreePos - vehGap;
108 1659 : if (myParkingFactor < 1 && myLastParking != nullptr && forVehicle.hasStops() && (forVehicle.getStops().front().pars.parking == ParkingType::ONROAD)
109 1023833 : && 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 1023287 : if (forVehicle.getLane() == &myLane && forVehicle.getPositionOnLane() < myEndPos && forVehicle.getPositionOnLane() > myBegPos && forVehicle.getSpeed() <= SUMO_const_haltingSpeed) {
115 80533 : return forVehicle.getPositionOnLane();
116 : }
117 942754 : if (!fits(pos, forVehicle)) {
118 : // try to find a place ahead of the waiting vehicles
119 897529 : const double vehLength = forVehicle.getVehicleType().getLength() * myParkingFactor;
120 : std::vector<std::pair<double, std::pair<double, const SUMOVehicle*> > > spaces;
121 2533122 : for (auto it : myEndPositions) {
122 1635593 : 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 897529 : std::sort(spaces.begin(), spaces.end());
126 897529 : std::reverse(spaces.begin(), spaces.end());
127 897529 : double prev = myEndPos;
128 2489103 : 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 1613396 : if (prev - it.first + NUMERICAL_EPS >= vehLength && (
133 13293 : it.second.second->isParking()
134 5036 : || it.second.second->remainingStopDuration() > TIME2STEPS(10))) {
135 : return prev;
136 : }
137 1591574 : prev = it.second.first - vehGap;
138 : }
139 889000 : 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 897529 : }
144 934225 : return pos;
145 : }
146 912078 : return myLastFreePos;
147 : }
148 :
149 : bool
150 1904868 : 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 1904868 : return pos + POSITION_EPS >= myEndPos || (pos - myBegPos >= veh.getVehicleType().getLength() * myParkingFactor / 2);
154 : }
155 :
156 : double
157 111420 : MSStoppingPlace::getWaitingPositionOnLane(MSTransportable* t) const {
158 : auto it = myWaitingTransportables.find(t);
159 111420 : const double waitingWidth = myElement == SUMO_TAG_CONTAINER_STOP
160 111420 : ? SUMO_const_waitingContainerWidth
161 : : SUMO_const_waitingPersonWidth;
162 111420 : if (it != myWaitingTransportables.end() && it->second >= 0) {
163 36059 : return myEndPos - (0.5 + (it->second) % getTransportablesAbreast()) * waitingWidth;
164 : } else {
165 75361 : return (myEndPos + myBegPos) / 2;
166 : }
167 : }
168 :
169 :
170 : int
171 107751 : MSStoppingPlace::getTransportablesAbreast(double length, SumoXMLTag element) {
172 107751 : return MAX2(1, (int)floor(length / (element == SUMO_TAG_CONTAINER_STOP
173 107751 : ? SUMO_const_waitingContainerWidth
174 107751 : : SUMO_const_waitingPersonWidth)));
175 : }
176 :
177 : int
178 68534 : MSStoppingPlace::getTransportablesAbreast() const {
179 68534 : return getTransportablesAbreast(myEndPos - myBegPos, myElement);
180 : }
181 :
182 : Position
183 88039 : MSStoppingPlace::getWaitPosition(MSTransportable* t) const {
184 88039 : double lanePos = getWaitingPositionOnLane(t);
185 : int row = 0;
186 : auto it = myWaitingTransportables.find(t);
187 88039 : if (it != myWaitingTransportables.end()) {
188 30801 : if (it->second >= 0) {
189 30801 : row = int(it->second / getTransportablesAbreast());
190 : } else {
191 : // invalid position, draw outside bounds
192 0 : row = 1 + myTransportableCapacity / getTransportablesAbreast();
193 : }
194 : }
195 88039 : const double lefthandSign = (MSGlobals::gLefthand ? -1 : 1);
196 88039 : return myLane.getShape().positionAtOffset(myLane.interpolateLanePosToGeometryPos(lanePos),
197 88039 : 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 127238 : MSStoppingPlace::hasSpaceForTransportable() const {
222 127238 : return myWaitingSpots.size() > 0;
223 : }
224 :
225 : bool
226 127238 : MSStoppingPlace::addTransportable(const MSTransportable* p) {
227 : int spot = -1;
228 127238 : if (!hasSpaceForTransportable()) {
229 : return false;
230 : }
231 87894 : spot = *myWaitingSpots.begin();
232 : myWaitingSpots.erase(myWaitingSpots.begin());
233 87894 : myWaitingTransportables[p] = spot;
234 87894 : return true;
235 : }
236 :
237 :
238 : void
239 193979 : MSStoppingPlace::removeTransportable(const MSTransportable* p) {
240 : auto i = myWaitingTransportables.find(p);
241 193979 : if (i != myWaitingTransportables.end()) {
242 87727 : if (i->second >= 0) {
243 87727 : myWaitingSpots.insert(i->second);
244 : }
245 : myWaitingTransportables.erase(i);
246 : }
247 193979 : }
248 :
249 :
250 : void
251 19886 : MSStoppingPlace::leaveFrom(SUMOVehicle* what) {
252 : assert(myEndPositions.find(what) != myEndPositions.end());
253 : myEndPositions.erase(myEndPositions.find(what));
254 19886 : computeLastFreePos();
255 19886 : }
256 :
257 :
258 : void
259 104675 : MSStoppingPlace::computeLastFreePos() {
260 104675 : myLastFreePos = myEndPos;
261 104675 : myLastParking = nullptr;
262 131176 : for (auto item : myEndPositions) {
263 : // vehicle might be stopped beyond myEndPos
264 26501 : if (myLastFreePos >= item.second.second || myLastFreePos == myEndPos) {
265 23743 : myLastFreePos = item.second.second;
266 23743 : if (item.first->isStoppedParking()) {
267 3969 : myLastParking = item.first;
268 : }
269 : }
270 : }
271 104675 : }
272 :
273 :
274 : double
275 62511 : MSStoppingPlace::getAccessPos(const MSEdge* edge, SumoRNG* rng) const {
276 62511 : if (edge == &myLane.getEdge()) {
277 56268 : return (myBegPos + myEndPos) / 2.;
278 : }
279 7767 : for (const auto& access : myAccessPos) {
280 6514 : if (edge == &access.lane->getEdge()) {
281 4990 : if (rng == nullptr || access.startPos == access.endPos) {
282 4232 : 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 57893 : MSStoppingPlace::getAccess(const MSEdge* edge) const {
293 61069 : for (const auto& access : myAccessPos) {
294 7311 : if (edge == &access.lane->getEdge()) {
295 : return &access;
296 : }
297 : }
298 : return nullptr;
299 : }
300 :
301 :
302 : const std::string&
303 1223 : MSStoppingPlace::getMyName() const {
304 1223 : return myName;
305 : }
306 :
307 :
308 : const RGBColor&
309 46928 : MSStoppingPlace::getColor() const {
310 46928 : return myColor;
311 : }
312 :
313 :
314 : bool
315 2261 : 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 4405 : for (const auto& access : myAccessPos) {
318 2151 : if (lane == access.lane) {
319 : return false;
320 : }
321 : }
322 2254 : if (length < 0.) {
323 1179 : const Position accPos = lane->geometryPositionAtOffset((startPos + endPos) / 2.);
324 1179 : const Position stopPos = myLane.geometryPositionAtOffset((myBegPos + myEndPos) / 2.);
325 1179 : length = accPos.distanceTo(stopPos);
326 : }
327 2254 : myAccessPos.push_back({lane, startPos, endPos, length, exit});
328 2254 : 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 50 : MSStoppingPlace::clearState() {
353 : myEndPositions.clear();
354 : myWaitingTransportables.clear();
355 50 : computeLastFreePos();
356 50 : }
357 :
358 :
359 : /****************************************************************************/
|