Eclipse SUMO - Simulation of Urban MObility
Loading...
Searching...
No Matches
MSStoppingPlace.cpp
Go to the documentation of this file.
1/****************************************************************************/
2// Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
3// Copyright (C) 2005-2026 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/****************************************************************************/
20// A lane area vehicles can halt at
21/****************************************************************************/
22#include <config.h>
23
24#include <cassert>
25#include <map>
27#include <utils/geom/Position.h>
31#include <microsim/MSGlobals.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// ===========================================================================
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 double angle) :
50 Named(id),
51 myElement(element),
52 myLines(lines), myLane(lane),
53 myBegPos(begPos), myEndPos(endPos),
54 myLastFreePos(endPos),
55 myLastParking(nullptr),
56 myName(name),
57 myTransportableCapacity(capacity),
58 myParkingFactor(parkingLength <= 0 ? 1 : (endPos - begPos) / parkingLength),
59 myColor(color),
60 myAngle(DEG2RAD(angle)),
61 // see MSVehicleControl defContainerType
63 myTransportableWidth(getDefaultTransportableWidth(myElement)) {
65 for (int i = 0; i < capacity; i++) {
66 myWaitingSpots.insert(i);
67 }
68}
69
70
72
73
74double
81
82void
84 const std::string waitingWidth = getParameter("waitingWidth");
85 if (waitingWidth != "") {
86 try {
88 } catch (ProcessError& e) {
89 WRITE_WARNINGF("Could not load waitingWidth (m) '%' (%)", waitingWidth, e.what());
90 }
91 }
92 const std::string waitingDepth = getParameter("waitingDepth");
93 if (waitingDepth != "") {
94 try {
96 } catch (ProcessError& e) {
97 WRITE_WARNINGF("Could not load waitingDepth (m) '%' (%)", waitingWidth, e.what());
98 }
99 }
100}
101
102
103const MSLane&
105 return myLane;
106}
107
108
109double
113
114
115double
119
125
126
127void
128MSStoppingPlace::enter(SUMOVehicle* veh, const bool parking) {
129 const double beg = veh->getPositionOnLane() + veh->getVehicleType().getMinGap() * (parking ? myParkingFactor : 1);
130 const double end = beg - veh->getVehicleType().getLengthWithGap() * (parking ? myParkingFactor : 1);
131 myEndPositions[veh] = std::make_pair(beg, end);
133}
134
135
136double
137MSStoppingPlace::getLastFreePos(const SUMOVehicle& forVehicle, double /*brakePos*/) const {
138 if (getStoppedVehicleNumber() > 0) {
139 const double vehGap = forVehicle.getVehicleType().getMinGap();
140 double pos = myLastFreePos - vehGap - NUMERICAL_EPS;
141 if (myParkingFactor < 1 && myLastParking != nullptr && forVehicle.hasStops() && (forVehicle.getStops().front().pars.parking == ParkingType::ONROAD)
142 && 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 pos = MIN2(pos, myLastParking->getPositionOnLane() - myLastParking->getLength() - vehGap - NUMERICAL_EPS);
146 }
147 if (!fits(pos, forVehicle)) {
148 // try to find a place ahead of the waiting vehicles
149 const double vehLength = forVehicle.getVehicleType().getLength() * myParkingFactor;
150 std::vector<std::pair<double, std::pair<double, const SUMOVehicle*> > > spaces;
151 for (auto it : myEndPositions) {
152 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 std::sort(spaces.begin(), spaces.end());
156 std::reverse(spaces.begin(), spaces.end());
157 double prev = myEndPos;
158 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 if (prev - it.first + NUMERICAL_EPS >= vehLength && (
163 it.second.second->isParking()
164 || it.second.second->remainingStopDuration() > TIME2STEPS(10))) {
165 return prev;
166 }
167 prev = it.second.first - vehGap;
168 }
169 if (myParkingFactor < 1 && myLastParking != nullptr) {
170 // stop far back enough so that the previous vehicle can leave
171 pos = MIN2(pos, myLastParking->getPositionOnLane() - myLastParking->getLength() - vehGap - NUMERICAL_EPS);
172 }
173 }
174 return pos;
175 }
176 return myLastFreePos;
177}
178
179bool
180MSStoppingPlace::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 return pos + POSITION_EPS >= myEndPos || (pos - myBegPos >= veh.getVehicleType().getLength() * myParkingFactor / 2);
184}
185
186double
188 auto it = myWaitingTransportables.find(t);
189 if (it != myWaitingTransportables.end() && it->second >= 0) {
190 return myEndPos - (0.5 + (it->second) % getTransportablesAbreast()) * myTransportableWidth;
191 } else {
192 return (myEndPos + myBegPos) / 2;
193 }
194}
195
196
197int
199 return MAX2(1, (int)floor(length / getDefaultTransportableWidth(element)));
200}
201
202int
206
209 double lanePos = getWaitingPositionOnLane(t);
210 int row = 0;
211 auto it = myWaitingTransportables.find(t);
212 if (it != myWaitingTransportables.end()) {
213 if (it->second >= 0) {
214 row = int(it->second / getTransportablesAbreast());
215 } else {
216 // invalid position, draw outside bounds
218 }
219 }
220 const double lefthandSign = (MSGlobals::gLefthand ? -1 : 1);
222 lefthandSign * (myLane.getWidth() / 2 + row * myTransportableDepth + fabs(cos(myAngle)) * myTransportableWidth / 2));
223}
224
225
226double
228 auto i = myEndPositions.find(veh);
229 if (i != myEndPositions.end()) {
230 return i->second.second;
231 } else {
232 return getLastFreePos(*veh);
233 }
234}
235
236std::vector<const MSTransportable*>
238 std::vector<const MSTransportable*> result;
239 for (auto item : myWaitingTransportables) {
240 result.push_back(item.first);
241 }
242 return result;
243}
244
245bool
247 return myWaitingSpots.size() > 0;
248}
249
250bool
252 if (spot < 0 && !hasSpaceForTransportable()) {
253 return false;
254 }
255 if (spot < 0) {
256 spot = *myWaitingSpots.begin();
257 }
258 myWaitingSpots.erase(spot);
259 myWaitingTransportables[p] = spot;
260 return true;
261}
262
263
264void
266 auto i = myWaitingTransportables.find(p);
267 if (i != myWaitingTransportables.end()) {
268 if (i->second >= 0) {
269 myWaitingSpots.insert(i->second);
270 }
272 }
273}
274
275
276int
278 auto i = myWaitingTransportables.find(p);
279 if (i != myWaitingTransportables.end()) {
280 return i->second;
281 } else {
282 return -1;
283 }
284}
285
286
287void
289 assert(myEndPositions.find(what) != myEndPositions.end());
290 myEndPositions.erase(myEndPositions.find(what));
292}
293
294
295void
298 myLastParking = nullptr;
299 for (auto item : myEndPositions) {
300 // vehicle might be stopped beyond myEndPos
301 if (myLastFreePos >= item.second.second || myLastFreePos == myEndPos) {
302 myLastFreePos = item.second.second;
303 if (item.first->isStoppedParking()) {
304 myLastParking = item.first;
305 }
306 }
307 }
308}
309
310
311double
313 if (edge == &myLane.getEdge()) {
314 return (myBegPos + myEndPos) / 2.;
315 }
316 for (const auto& access : myAccessPos) {
317 if (edge == &access.lane->getEdge()) {
318 if (rng == nullptr || access.startPos == access.endPos) {
319 return access.endPos;
320 }
321 return RandHelper::rand(access.startPos, access.endPos, rng);
322 }
323 }
324 return -1.;
325}
326
327
330 for (const auto& access : myAccessPos) {
331 if (edge == &access.lane->getEdge()) {
332 return &access;
333 }
334 }
335 return nullptr;
336}
337
338
339const std::string&
341 return myName;
342}
343
344
345const RGBColor&
347 return myColor;
348}
349
350
351bool
352MSStoppingPlace::addAccess(MSLane* const lane, const double startPos, const double endPos, double length, const MSStoppingPlace::AccessExit exit) {
353 // prevent multiple accesses on the same lane
354 for (const auto& access : myAccessPos) {
355 if (lane == access.lane) {
356 return false;
357 }
358 }
359 if (length < 0.) {
360 const Position accPos = lane->geometryPositionAtOffset((startPos + endPos) / 2.);
361 const Position stopPos = myLane.geometryPositionAtOffset((myBegPos + myEndPos) / 2.);
362 length = accPos.distanceTo(stopPos);
363 }
364 myAccessPos.push_back({lane, startPos, endPos, length, exit});
365 return true;
366}
367
368
369std::vector<const SUMOVehicle*>
371 std::vector<const SUMOVehicle*> result;
372 for (auto item : myEndPositions) {
373 result.push_back(item.first);
374 }
375 return result;
376}
377
378
379void
380MSStoppingPlace::getWaitingPersonIDs(std::vector<std::string>& into) const {
381 for (auto item : myWaitingTransportables) {
382 into.push_back(item.first->getID());
383 }
384 std::sort(into.begin(), into.end());
385}
386
387
388void
394
395
396/****************************************************************************/
#define DEG2RAD(x)
Definition GeomHelper.h:35
#define WRITE_WARNINGF(...)
Definition MsgHandler.h:287
#define SIMSTEP
Definition SUMOTime.h:64
#define TIME2STEPS(x)
Definition SUMOTime.h:60
SumoXMLTag
Numbers representing SUMO-XML - element names.
@ SUMO_TAG_CONTAINER_STOP
A container stop.
const double SUMO_const_waitingPersonDepth
Definition StdDefs.h:57
T MIN2(T a, T b)
Definition StdDefs.h:80
T MAX2(T a, T b)
Definition StdDefs.h:86
const double SUMO_const_waitingContainerWidth
Definition StdDefs.h:58
const double SUMO_const_waitingPersonWidth
Definition StdDefs.h:56
const double SUMO_const_waitingContainerDepth
Definition StdDefs.h:59
A road/street connecting two junctions.
Definition MSEdge.h:77
static bool gLefthand
Whether lefthand-drive is being simulated.
Definition MSGlobals.h:177
Representation of a lane in the micro simulation.
Definition MSLane.h:84
double interpolateLanePosToGeometryPos(double lanePos) const
Definition MSLane.h:555
virtual const PositionVector & getShape(bool) const
Definition MSLane.h:294
MSEdge & getEdge() const
Returns the lane's edge.
Definition MSLane.h:775
double getWidth() const
Returns the lane's width.
Definition MSLane.h:646
const Position geometryPositionAtOffset(double offset, double lateralOffset=0) const
Definition MSLane.h:561
std::vector< const SUMOVehicle * > getStoppedVehicles() const
get list of vehicles waiting at this stop
int getStoppedVehicleNumber() const
Returns the number of stopped vehicles waiting on this stop.
const SUMOVehicle * myLastParking
The length of the last parking vehicle (or 0 if there is none)
int checkWaitingSpot(const MSTransportable *p) const
double getWaitingPositionOnLane(MSTransportable *t) const
Returns the lane position corresponding to getWaitPosition()
double myTransportableWidth
the with of waiting transportables
const Access * getAccess(const MSEdge *edge) const
the access on the given edge to the stop, nullptr if there is none
std::map< const MSTransportable *, int > myWaitingTransportables
Persons waiting at this stop (mapped to waiting position)
const double myBegPos
The begin position this bus stop is located at.
double getBeginLanePosition() const
Returns the begin position of this stop.
const MSLane & myLane
The lane this bus stop is located at.
bool hasSpaceForTransportable() const
whether there is still capacity for more transportables
std::map< const SUMOVehicle *, std::pair< double, double >, ComparatorNumericalIdLess > myEndPositions
A map from objects (vehicles) to the areas they acquire after entering the stop.
int getTransportablesAbreast() const
MSStoppingPlace(const std::string &id, SumoXMLTag element, const std::vector< std::string > &lines, MSLane &lane, double begPos, double endPos, const std::string name="", int capacity=0, double parkingLength=0, const RGBColor &color=RGBColor::INVISIBLE, double angle=90)
Constructor.
std::vector< const MSTransportable * > getTransportables() const
Returns the transportables waiting on this stop.
void clearState()
Remove all vehicles before quick-loading state.
virtual void finishedLoading()
perform extra processing after element has been loaded
std::set< int > myWaitingSpots
const double myParkingFactor
the scaled space capacity for parking vehicles
Position getCenterPos() const
the position in the middle of the stop shape
virtual void enter(SUMOVehicle *veh, const bool parking)
Called if a vehicle enters this stop.
bool fits(double pos, const SUMOVehicle &veh) const
return whether the given vehicle fits at the given position
double myTransportableDepth
row depth of waiting transportables
static double getDefaultTransportableWidth(SumoXMLTag element)
const std::string myName
The name of the stopping place.
std::vector< Access > myAccessPos
lanes and positions connected to this stop
const double myEndPos
The end position this bus stop is located at.
double getEndLanePosition() const
Returns the end position of this stop.
const RGBColor myColor
The color of the stopping place.
bool addTransportable(const MSTransportable *p, int spot=-1)
adds a transportable to this stop
double getStoppingPosition(const SUMOVehicle *veh) const
For vehicles at the stop this gives the actual stopping position of the vehicle. For all others the l...
void removeTransportable(const MSTransportable *p)
Removes a transportable from this stop.
virtual ~MSStoppingPlace()
Destructor.
void computeLastFreePos()
Computes the last free position on this stop.
double myAngle
The angle offset for waiting transportables.
const RGBColor & getColor() const
void getWaitingPersonIDs(std::vector< std::string > &into) const
get IDs of persons waiting at this stop
const MSLane & getLane() const
Returns the lane this stop is located at.
const int myTransportableCapacity
The number of transportables that can wait here.
const std::string & getMyName() const
Position getWaitPosition(MSTransportable *person) const
Returns the next free waiting place for pedestrians / containers.
double getAccessPos(const MSEdge *edge, SumoRNG *rng=nullptr) const
the position on the given edge which is connected to this stop, -1 on failure
virtual bool addAccess(MSLane *const lane, const double startPos, const double endPos, double length, const MSStoppingPlace::AccessExit exit)
adds an access point to this stop
static int getDefaultTransportablesAbreast(double length, SumoXMLTag element)
double myLastFreePos
The last free position at this stop (variable)
double getLastFreePos() const
virtual void leaveFrom(SUMOVehicle *what)
Called if a vehicle leaves this stop.
double getLengthWithGap() const
Get vehicle's length including the minimum gap [m].
double getMinGap() const
Get the free space in front of vehicles of this class.
double getLength() const
Get vehicle's length [m].
Base class for objects which have an id.
Definition Named.h:54
virtual const std::string getParameter(const std::string &key, const std::string defaultValue="") const
Returns the value for a given key.
A point in 2D or 3D with translation and scaling methods.
Definition Position.h:37
double distanceTo(const Position &p2) const
returns the euclidean distance in 3 dimensions
Definition Position.h:263
Position positionAtOffset(double pos, double lateralOffset=0) const
Returns the position at the given length.
static double rand(SumoRNG *rng=nullptr)
Returns a random real number in [0, 1)
virtual const MSVehicleType & getVehicleType() const =0
Returns the object's "vehicle" type.
virtual double getPositionOnLane() const =0
Get the object's position along the lane.
Representation of a vehicle.
Definition SUMOVehicle.h:63
virtual bool hasStops() const =0
Returns whether the vehicle has to stop somewhere.
virtual SUMOTime remainingStopDuration() const =0
Returns the remaining stop duration for a stopped vehicle or 0.
virtual const std::list< MSStop > & getStops() const =0
virtual double getLength() const =0
Returns the vehicles's length.
static double toDouble(const std::string &sData)
converts a string into the double value described by it by calling the char-type converter