Eclipse SUMO - Simulation of Urban MObility
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-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 /****************************************************************************/
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>
28 #include <utils/common/RGBColor.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 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  const RGBColor& color) :
48  Named(id),
49  myElement(element),
50  myLines(lines), myLane(lane),
51  myBegPos(begPos), myEndPos(endPos),
52  myLastFreePos(endPos),
53  myLastParking(nullptr),
54  myName(name),
55  myTransportableCapacity(capacity),
56  myParkingFactor(parkingLength <= 0 ? 1 : (endPos - begPos) / parkingLength),
57  myColor(color),
58  // see MSVehicleControl defContainerType
61  for (int i = 0; i < capacity; i++) {
62  myWaitingSpots.insert(i);
63  }
64 }
65 
66 
68 
69 
70 const MSLane&
72  return myLane;
73 }
74 
75 
76 double
78  return myBegPos;
79 }
80 
81 
82 double
84  return myEndPos;
85 }
86 
90  myLane.getWidth() / 2 + 0.5);
91 }
92 
93 
94 void
95 MSStoppingPlace::enter(SUMOVehicle* veh, bool parking) {
96  double beg = veh->getPositionOnLane() + veh->getVehicleType().getMinGap();
97  double end = beg - veh->getVehicleType().getLengthWithGap() * (parking ? myParkingFactor : 1);
98  myEndPositions[veh] = std::make_pair(beg, end);
100 }
101 
102 
103 double
104 MSStoppingPlace::getLastFreePos(const SUMOVehicle& forVehicle, double /*brakePos*/) const {
105  if (getStoppedVehicleNumber() > 0) {
106  const double vehGap = forVehicle.getVehicleType().getMinGap();
107  double pos = myLastFreePos - vehGap;
108  if (myParkingFactor < 1 && myLastParking != nullptr && forVehicle.hasStops() && (forVehicle.getStops().front().pars.parking == ParkingType::ONROAD)
109  && myLastParking->remainingStopDuration() < forVehicle.getStops().front().getMinDuration(SIMSTEP)) {
110  // stop far back enough so that the previous vehicle can leave
111  pos = myLastParking->getPositionOnLane() - myLastParking->getLength() - vehGap - NUMERICAL_EPS;
112  }
113  if (forVehicle.getLane() == &myLane && forVehicle.getPositionOnLane() < myEndPos && forVehicle.getPositionOnLane() > myBegPos && forVehicle.getSpeed() <= SUMO_const_haltingSpeed) {
114  return forVehicle.getPositionOnLane();
115  }
116  if (!fits(pos, forVehicle)) {
117  // try to find a place ahead of the waiting vehicles
118  const double vehLength = forVehicle.getVehicleType().getLength();
119  std::vector<std::pair<double, std::pair<double, const SUMOVehicle*> > > spaces;
120  for (auto it : myEndPositions) {
121  spaces.push_back(std::make_pair(it.second.first, std::make_pair(it.second.second, it.first)));
122  }
123  // sorted from myEndPos towars myBegPos
124  std::sort(spaces.begin(), spaces.end());
125  std::reverse(spaces.begin(), spaces.end());
126  double prev = myEndPos;
127  for (auto it : spaces) {
128  //if (forVehicle.isSelected()) {
129  // std::cout << SIMTIME << " fitPosFor " << forVehicle.getID() << " l=" << vehLength << " prev=" << prev << " vehBeg=" << it.first << " vehEnd=" << it.second.first << " found=" << (prev - it.first >= vehLength) << "\n";
130  //}
131  if (prev - it.first + NUMERICAL_EPS >= vehLength && (
132  it.second.second->isParking()
133  || it.second.second->remainingStopDuration() > TIME2STEPS(10))) {
134  return prev;
135  }
136  prev = it.second.first - vehGap;
137  }
138  }
139  return pos;
140  }
141  return myLastFreePos;
142 }
143 
144 bool
145 MSStoppingPlace::fits(double pos, const SUMOVehicle& veh) const {
146  // always fit at the default position or if at least half the vehicle length
147  // is within the stop range (debatable)
148  return pos + POSITION_EPS >= myEndPos || (pos - myBegPos >= veh.getVehicleType().getLength() * myParkingFactor / 2);
149 }
150 
151 double
153  auto it = myWaitingTransportables.find(t);
154  const double waitingWidth = myElement == SUMO_TAG_CONTAINER_STOP
157  if (it != myWaitingTransportables.end() && it->second >= 0) {
158  return myEndPos - (0.5 + (it->second) % getTransportablesAbreast()) * waitingWidth;
159  } else {
160  return (myEndPos + myBegPos) / 2;
161  }
162 }
163 
164 
165 int
167  return MAX2(1, (int)floor(length / (element == SUMO_TAG_CONTAINER_STOP
170 }
171 
172 int
175 }
176 
177 Position
179  double lanePos = getWaitingPositionOnLane(t);
180  int row = 0;
181  auto it = myWaitingTransportables.find(t);
182  if (it != myWaitingTransportables.end()) {
183  if (it->second >= 0) {
184  row = int(it->second / getTransportablesAbreast());
185  } else {
186  // invalid position, draw outside bounds
188  }
189  }
190  const double lefthandSign = (MSGlobals::gLefthand ? -1 : 1);
192  lefthandSign * (myLane.getWidth() / 2 + row * myTransportableDepth));
193 }
194 
195 
196 double
198  auto i = myEndPositions.find(veh);
199  if (i != myEndPositions.end()) {
200  return i->second.second;
201  } else {
202  return getLastFreePos(*veh);
203  }
204 }
205 
206 std::vector<const MSTransportable*>
208  std::vector<const MSTransportable*> result;
209  for (auto item : myWaitingTransportables) {
210  result.push_back(item.first);
211  }
212  return result;
213 }
214 
215 bool
217  return myWaitingSpots.size() > 0;
218 }
219 
220 bool
222  int spot = -1;
223  if (!hasSpaceForTransportable()) {
224  return false;
225  }
226  spot = *myWaitingSpots.begin();
227  myWaitingSpots.erase(myWaitingSpots.begin());
228  myWaitingTransportables[p] = spot;
229  return true;
230 }
231 
232 
233 void
235  auto i = myWaitingTransportables.find(p);
236  if (i != myWaitingTransportables.end()) {
237  if (i->second >= 0) {
238  myWaitingSpots.insert(i->second);
239  }
240  myWaitingTransportables.erase(i);
241  }
242 }
243 
244 
245 void
247  assert(myEndPositions.find(what) != myEndPositions.end());
248  myEndPositions.erase(myEndPositions.find(what));
250 }
251 
252 
253 void
256  myLastParking = nullptr;
257  for (auto item : myEndPositions) {
258  // vehicle might be stopped beyond myEndPos
259  if (myLastFreePos >= item.second.second || myLastFreePos == myEndPos) {
260  myLastFreePos = item.second.second;
261  if (item.first->isStoppedParking()) {
262  myLastParking = item.first;
263  }
264  }
265  }
266 }
267 
268 
269 double
270 MSStoppingPlace::getAccessPos(const MSEdge* edge, SumoRNG* rng) const {
271  if (edge == &myLane.getEdge()) {
272  return (myBegPos + myEndPos) / 2.;
273  }
274  for (const auto& access : myAccessPos) {
275  if (edge == &access.lane->getEdge()) {
276  if (rng == nullptr || access.startPos == access.endPos) {
277  return access.endPos;
278  }
279  return RandHelper::rand(access.startPos, access.endPos, rng);
280  }
281  }
282  return -1.;
283 }
284 
285 
287 MSStoppingPlace::getAccess(const MSEdge* edge) const {
288  for (const auto& access : myAccessPos) {
289  if (edge == &access.lane->getEdge()) {
290  return &access;
291  }
292  }
293  return nullptr;
294 }
295 
296 
297 const std::string&
299  return myName;
300 }
301 
302 
303 const RGBColor&
305  return myColor;
306 }
307 
308 
309 bool
310 MSStoppingPlace::addAccess(MSLane* const lane, const double startPos, const double endPos, double length, const bool doors) {
311  // prevent multiple accesses on the same lane
312  for (const auto& access : myAccessPos) {
313  if (lane == access.lane) {
314  return false;
315  }
316  }
317  if (length < 0.) {
318  const Position accPos = lane->geometryPositionAtOffset((startPos + endPos) / 2.);
319  const Position stopPos = myLane.geometryPositionAtOffset((myBegPos + myEndPos) / 2.);
320  length = accPos.distanceTo(stopPos);
321  }
322  myAccessPos.push_back({lane, startPos, endPos, length, doors});
323  return true;
324 }
325 
326 
327 std::vector<const SUMOVehicle*>
329  std::vector<const SUMOVehicle*> result;
330  for (auto item : myEndPositions) {
331  result.push_back(item.first);
332  }
333  return result;
334 }
335 
336 
337 void
338 MSStoppingPlace::getWaitingPersonIDs(std::vector<std::string>& into) const {
339  for (auto item : myWaitingTransportables) {
340  into.push_back(item.first->getID());
341  }
342  std::sort(into.begin(), into.end());
343 }
344 
345 
346 void
348  myEndPositions.clear();
349  myWaitingTransportables.clear();
351 }
352 
353 
354 /****************************************************************************/
#define SIMSTEP
Definition: SUMOTime.h:61
#define TIME2STEPS(x)
Definition: SUMOTime.h:57
SumoXMLTag
Numbers representing SUMO-XML - element names.
@ SUMO_TAG_CONTAINER_STOP
A container stop.
const double SUMO_const_waitingPersonDepth
Definition: StdDefs.h:53
const double SUMO_const_haltingSpeed
the speed threshold at which vehicles are considered as halting
Definition: StdDefs.h:58
T MAX2(T a, T b)
Definition: StdDefs.h:82
const double SUMO_const_waitingContainerWidth
Definition: StdDefs.h:54
const double SUMO_const_waitingPersonWidth
Definition: StdDefs.h:52
const double SUMO_const_waitingContainerDepth
Definition: StdDefs.h:55
A road/street connecting two junctions.
Definition: MSEdge.h:77
static bool gLefthand
Whether lefthand-drive is being simulated.
Definition: MSGlobals.h:169
Representation of a lane in the micro simulation.
Definition: MSLane.h:84
MSEdge & getEdge() const
Returns the lane's edge.
Definition: MSLane.h:756
double interpolateLanePosToGeometryPos(double lanePos) const
Definition: MSLane.h:546
double getWidth() const
Returns the lane's width.
Definition: MSLane.h:627
const Position geometryPositionAtOffset(double offset, double lateralOffset=0) const
Definition: MSLane.h:552
virtual const PositionVector & getShape(bool) const
Definition: MSLane.h:294
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)
const SumoXMLTag myElement
the type of stopping place
double getWaitingPositionOnLane(MSTransportable *t) const
Returns the lane position corresponding to getWaitPosition()
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
std::vector< const MSTransportable * > getTransportables() const
Returns the tranportables waiting on this stop.
void clearState()
Remove all vehicles before quick-loading state.
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
bool fits(double pos, const SUMOVehicle &veh) const
return whether the given vehicle fits at the given position
const std::string myName
The name of the stopping place.
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)
Constructor.
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.
void enter(SUMOVehicle *veh, bool parking)
Called if a vehicle enters this stop.
double getStoppingPosition(const SUMOVehicle *veh) const
For vehicles at the stop this gives the the actual stopping position of the vehicle....
void removeTransportable(const MSTransportable *p)
Removes a transportable from this stop.
virtual ~MSStoppingPlace()
Destructor.
void computeLastFreePos()
Computes the last free position on this stop.
const RGBColor & getColor() const
virtual bool addAccess(MSLane *const lane, const double startPos, const double endPos, double length, const bool doors)
adds an access point to this stop
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
bool addTransportable(const MSTransportable *p)
adds a transportable to this stop
double myLastFreePos
The last free position at this stop (variable)
double getLastFreePos() const
const double myTransportableDepth
row depth of waiting transportables
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
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 dimension
Definition: Position.h:261
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)
Definition: RandHelper.cpp:94
virtual double getSpeed() const =0
Returns the object's current speed.
virtual const MSVehicleType & getVehicleType() const =0
Returns the object's "vehicle" type.
virtual const MSLane * getLane() const =0
Returns the lane the object is currently at.
virtual double getPositionOnLane() const =0
Get the object's position along the lane.
Representation of a vehicle.
Definition: SUMOVehicle.h:60
virtual const std::list< MSStop > & getStops() const =0
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 double getLength() const =0
Returns the vehicles's length.