SUMO - Simulation of Urban MObility
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
MSLink.cpp
Go to the documentation of this file.
1 /****************************************************************************/
10 // A connnection between lanes
11 /****************************************************************************/
12 // SUMO, Simulation of Urban MObility; see http://sumo-sim.org/
13 // Copyright (C) 2001-2014 DLR (http://www.dlr.de/) and contributors
14 /****************************************************************************/
15 //
16 // This file is part of SUMO.
17 // SUMO is free software: you can redistribute it and/or modify
18 // it under the terms of the GNU General Public License as published by
19 // the Free Software Foundation, either version 3 of the License, or
20 // (at your option) any later version.
21 //
22 /****************************************************************************/
23 
24 // ===========================================================================
25 // included modules
26 // ===========================================================================
27 #ifdef _MSC_VER
28 #include <windows_config.h>
29 #else
30 #include <config.h>
31 #endif
32 
33 #include <iostream>
34 #include <algorithm>
36 #include "MSNet.h"
37 #include "MSLink.h"
38 #include "MSLane.h"
39 #include "MSEdge.h"
40 #include "MSGlobals.h"
41 #include "MSVehicle.h"
42 
43 #ifdef CHECK_MEMORY_LEAKS
44 #include <foreign/nvwa/debug_new.h>
45 #endif // CHECK_MEMORY_LEAKS
46 
47 
48 // ===========================================================================
49 // static member variables
50 // ===========================================================================
52 
53 
54 // ===========================================================================
55 // member method definitions
56 // ===========================================================================
57 #ifndef HAVE_INTERNAL_LANES
59  LinkDirection dir, LinkState state,
60  SUMOReal length)
61  :
62  myLane(succLane),
63  myIndex(0),
64  myState(state), myDirection(dir), myLength(length) {}
65 #else
66 MSLink::MSLink(MSLane* succLane, MSLane* via,
67  LinkDirection dir, LinkState state, SUMOReal length)
68  :
69  myLane(succLane),
70  myIndex(0),
71  myState(state), myDirection(dir), myLength(length),
72  myJunctionInlane(via)
73 {}
74 #endif
75 
76 
78 
79 
80 void
81 MSLink::setRequestInformation(unsigned int index, bool isCrossing, bool isCont,
82  const std::vector<MSLink*>& foeLinks,
83  const std::vector<MSLane*>& foeLanes,
84  MSLane* internalLaneBefore) {
85  myIndex = index;
87  myAmCont = isCont;
88  myFoeLinks = foeLinks;
89  myFoeLanes = foeLanes;
90 #ifdef HAVE_INTERNAL_LANES
91  if (internalLaneBefore != 0) {
92  // this is an exit link. compute crossing points with all foeLanes
93  for (std::vector<MSLane*>::const_iterator it_lane = myFoeLanes.begin(); it_lane != myFoeLanes.end(); ++it_lane) {
94  if (myLane == (*it_lane)->getLinkCont()[0]->getLane()) {
95  // this foeLane has the same target
96  myLengthsBehindCrossing.push_back(std::make_pair(0, 0)); // dummy value, never used
97  } else {
98  std::vector<SUMOReal> intersections1 = internalLaneBefore->getShape().intersectsAtLengths2D((*it_lane)->getShape());
99  //std::cout << " number of intersections1=" << intersections1.size() << "\n";
100  if (intersections1.size() == 0) {
101  intersections1.push_back(0);
102  } else if (intersections1.size() > 1) {
103  std::sort(intersections1.begin(), intersections1.end());
104  }
105  std::vector<SUMOReal> intersections2 = (*it_lane)->getShape().intersectsAtLengths2D(internalLaneBefore->getShape());
106  //std::cout << " number of intersections2=" << intersections2.size() << "\n";
107  if (intersections2.size() == 0) {
108  intersections2.push_back(0);
109  } else if (intersections2.size() > 1) {
110  std::sort(intersections2.begin(), intersections2.end());
111  }
112  myLengthsBehindCrossing.push_back(std::make_pair(
113  internalLaneBefore->getLength() - intersections1.back(),
114  (*it_lane)->getLength() - intersections2.back()));
115  //std::cout
116  // << " intersection of " << internalLaneBefore->getID()
117  // << " totalLength=" << internalLaneBefore->getLength()
118  // << " with " << (*it_lane)->getID()
119  // << " totalLength=" << (*it_lane)->getLength()
120  // << " dist1=" << myLengthsBehindCrossing.back().first
121  // << " dist2=" << myLengthsBehindCrossing.back().second
122  // << "\n";
123  }
124  }
125  }
126 #else
127  UNUSED_PARAMETER(internalLaneBefore);
128 #endif
129 }
130 
131 
132 void
133 MSLink::setApproaching(const SUMOVehicle* approaching, const SUMOTime arrivalTime, const SUMOReal arrivalSpeed, const SUMOReal leaveSpeed,
134  const bool setRequest, const SUMOTime arrivalTimeBraking, const SUMOReal arrivalSpeedBraking, const SUMOTime waitingTime) {
135  const SUMOTime leaveTime = getLeaveTime(arrivalTime, arrivalSpeed, leaveSpeed, approaching->getVehicleType().getLengthWithGap());
136  myApproachingVehicles.insert(std::make_pair(approaching,
137  ApproachingVehicleInformation(arrivalTime, leaveTime, arrivalSpeed, leaveSpeed, setRequest,
138  arrivalTimeBraking, arrivalSpeedBraking, waitingTime)));
139 }
140 
141 
142 void
144  myBlockedFoeLinks.insert(link);
145 }
146 
147 
148 
149 bool
151  for (std::set<MSLink*>::const_iterator i = myBlockedFoeLinks.begin(); i != myBlockedFoeLinks.end(); ++i) {
152  if ((*i)->isBlockingAnyone()) {
153  return true;
154  }
155  }
156  return false;
157 }
158 
159 
160 void
162  myApproachingVehicles.erase(veh);
163 }
164 
165 
168  std::map<const SUMOVehicle*, ApproachingVehicleInformation>::const_iterator i = myApproachingVehicles.find(veh);
169  if (i != myApproachingVehicles.end()) {
170  return i->second;
171  } else {
172  return ApproachingVehicleInformation(-1000, -1000, 0, 0, false, -1000, 0, 0);
173  }
174 }
175 
176 
177 SUMOTime
178 MSLink::getLeaveTime(SUMOTime arrivalTime, SUMOReal arrivalSpeed, SUMOReal leaveSpeed, SUMOReal vehicleLength) const {
179  return arrivalTime + TIME2STEPS((getLength() + vehicleLength) / (0.5 * (arrivalSpeed + leaveSpeed)));
180 }
181 
182 
183 bool
184 MSLink::opened(SUMOTime arrivalTime, SUMOReal arrivalSpeed, SUMOReal leaveSpeed, SUMOReal vehicleLength,
185  SUMOReal impatience, SUMOReal decel, SUMOTime waitingTime,
186  std::vector<const SUMOVehicle*>* collectFoes) const {
187  if (myState == LINKSTATE_TL_RED) {
188  return false;
189  }
191  return true;
192  }
193  if ((myState == LINKSTATE_STOP || myState == LINKSTATE_ALLWAY_STOP) && waitingTime == 0) {
194  return false;
195  }
196  const SUMOTime leaveTime = getLeaveTime(arrivalTime, arrivalSpeed, leaveSpeed, vehicleLength);
197  for (std::vector<MSLink*>::const_iterator i = myFoeLinks.begin(); i != myFoeLinks.end(); ++i) {
198 #ifdef HAVE_INTERNAL
200  if ((*i)->getState() == LINKSTATE_TL_RED) {
201  continue;
202  }
203  }
204 #endif
205  if ((*i)->blockedAtTime(arrivalTime, leaveTime, arrivalSpeed, leaveSpeed, myLane == (*i)->getLane(),
206  impatience, decel, waitingTime, collectFoes)) {
207  return false;
208  }
209  }
210  return true;
211 }
212 
213 
214 bool
215 MSLink::blockedAtTime(SUMOTime arrivalTime, SUMOTime leaveTime, SUMOReal arrivalSpeed, SUMOReal leaveSpeed,
216  bool sameTargetLane, SUMOReal impatience, SUMOReal decel, SUMOTime waitingTime,
217  std::vector<const SUMOVehicle*>* collectFoes) const {
218  for (std::map<const SUMOVehicle*, ApproachingVehicleInformation>::const_iterator i = myApproachingVehicles.begin(); i != myApproachingVehicles.end(); ++i) {
219  if (!i->second.willPass) {
220  continue;
221  }
223  assert(waitingTime > 0);
224  if (waitingTime > i->second.waitingTime) {
225  continue;
226  }
227  if (waitingTime == i->second.waitingTime && arrivalTime < i->second.arrivalTime) {
228  continue;
229  }
230  }
231  const SUMOTime foeArrivalTime = (SUMOTime)((1.0 - impatience) * i->second.arrivalTime + impatience * i->second.arrivalTimeBraking);
232  if (i->second.leavingTime < arrivalTime) {
233  // ego wants to be follower
234  if (sameTargetLane && (arrivalTime - i->second.leavingTime < myLookaheadTime
235  || unsafeMergeSpeeds(i->second.leaveSpeed, arrivalSpeed,
236  i->first->getVehicleType().getCarFollowModel().getMaxDecel(), decel))) {
237  if (collectFoes == 0) {
238  return true;
239  } else {
240  collectFoes->push_back(i->first);
241  }
242  }
243  } else if (foeArrivalTime > leaveTime) {
244  // ego wants to be leader.
245  if (sameTargetLane && (foeArrivalTime - leaveTime < myLookaheadTime
246  || unsafeMergeSpeeds(leaveSpeed, i->second.arrivalSpeedBraking,
247  decel, i->first->getVehicleType().getCarFollowModel().getMaxDecel()))) {
248  if (collectFoes == 0) {
249  return true;
250  } else {
251  collectFoes->push_back(i->first);
252  }
253  }
254  } else {
255  // even without considering safeHeadwayTime there is already a conflict
256  if (collectFoes == 0) {
257  return true;
258  } else {
259  collectFoes->push_back(i->first);
260  }
261  }
262  }
263  return false;
264 }
265 
266 
267 bool
269  MSVehicle* veh = lane->getLastVehicle();
270  SUMOReal distLeft = 0;
271  if (veh == 0) {
272  veh = lane->getPartialOccupator();
273  distLeft = lane->getLength() - lane->getPartialOccupatorEnd();
274  } else {
275  distLeft = lane->getLength() - veh->getPositionOnLane() + veh->getVehicleType().getLength();
276  }
277  if (veh == 0) {
278  return false;
279  } else {
280  assert(distLeft > 0);
281  // can we be sure that the vehicle leaves this lane in the next step?
282  bool result = distLeft > (veh->getSpeed() - veh->getCarFollowModel().getMaxDecel());
283  return result;
284  }
285 }
286 
287 
288 bool
289 MSLink::hasApproachingFoe(SUMOTime arrivalTime, SUMOTime leaveTime, SUMOReal speed, SUMOReal decel) const {
290  for (std::vector<MSLink*>::const_iterator i = myFoeLinks.begin(); i != myFoeLinks.end(); ++i) {
291  if ((*i)->blockedAtTime(arrivalTime, leaveTime, speed, speed, myLane == (*i)->getLane(), 0, decel, 0)) {
292  return true;
293  }
294  }
295  for (std::vector<MSLane*>::const_iterator i = myFoeLanes.begin(); i != myFoeLanes.end(); ++i) {
296  if ((*i)->getVehicleNumber() > 0 || (*i)->getPartialOccupator() != 0) {
297  return true;
298  }
299  }
300  return false;
301 }
302 
303 
306  return myDirection;
307 }
308 
309 
310 void
312  myState = state;
313 }
314 
315 
316 MSLane*
318  return myLane;
319 }
320 
321 
322 bool
324 #ifdef HAVE_INTERNAL_LANES
325  if (myJunctionInlane == 0 || myAmCont) {
326  return false;
327  } else {
328  MSLane* pred = myJunctionInlane->getLogicalPredecessorLane();
330  return false;
331  } else {
332  MSLane* pred2 = pred->getLogicalPredecessorLane();
333  assert(pred2 != 0);
334  MSLink* predLink = MSLinkContHelper::getConnectingLink(*pred2, *pred);
335  assert(predLink != 0);
336  return predLink->havePriority();
337  }
338  }
339 #else
340  return false;
341 #endif
342 }
343 
344 
345 void
346 MSLink::writeApproaching(OutputDevice& od, const std::string fromLaneID) const {
347  if (myApproachingVehicles.size() > 0) {
348  od.openTag("link");
349  od.writeAttr(SUMO_ATTR_FROM, fromLaneID);
350 #ifdef HAVE_INTERNAL_LANES
351  const std::string via = getViaLane() == 0 ? "" : getViaLane()->getID();
352 #else
353  const std::string via = "";
354 #endif
355  od.writeAttr(SUMO_ATTR_VIA, via);
356  od.writeAttr(SUMO_ATTR_TO, getLane() == 0 ? "" : getLane()->getID());
357  std::vector<std::pair<SUMOTime, const SUMOVehicle*> > toSort; // stabilize output
358  for (std::map<const SUMOVehicle*, ApproachingVehicleInformation>::const_iterator it = myApproachingVehicles.begin(); it != myApproachingVehicles.end(); ++it) {
359  toSort.push_back(std::make_pair(it->second.arrivalTime, it->first));
360  }
361  std::sort(toSort.begin(), toSort.end());
362  for (std::vector<std::pair<SUMOTime, const SUMOVehicle*> >::const_iterator it = toSort.begin(); it != toSort.end(); ++it) {
363  od.openTag("approaching");
364  const ApproachingVehicleInformation& avi = myApproachingVehicles.find(it->second)->second;
365  od.writeAttr(SUMO_ATTR_ID, it->second->getID());
366  od.writeAttr(SUMO_ATTR_IMPATIENCE, it->second->getImpatience());
367  od.writeAttr("arrivalTime", time2string(avi.arrivalTime));
368  od.writeAttr("arrivalTimeBraking", time2string(avi.arrivalTimeBraking));
369  od.writeAttr("leaveTime", time2string(avi.leavingTime));
370  od.writeAttr("arrivalSpeed", toString(avi.arrivalSpeed));
371  od.writeAttr("arrivalSpeedBraking", toString(avi.arrivalSpeedBraking));
372  od.writeAttr("leaveSpeed", toString(avi.leaveSpeed));
373  od.writeAttr("willPass", toString(avi.willPass));
374  od.closeTag();
375  }
376  od.closeTag();
377  }
378 }
379 
380 
381 #ifdef HAVE_INTERNAL_LANES
382 MSLane*
383 MSLink::getViaLane() const {
384  return myJunctionInlane;
385 }
386 
387 
389 MSLink::getLeaderInfo(SUMOReal dist, SUMOReal minGap) const {
390  LinkLeaders result;
391  if (MSGlobals::gUsingInternalLanes && myJunctionInlane == 0 &&
392  getLane()->getEdge().getPurpose() != MSEdge::EDGEFUNCTION_INTERNAL) {
393  //std::cout << " getLeaderInfo link=" << getViaLaneOrLane()->getID() << "\n";
394  // this is an exit link
395  for (size_t i = 0; i < myFoeLanes.size(); ++i) {
396  MSLane* foeLane = myFoeLanes[i];
397  // distance from the querying vehicle to the crossing point with foeLane
398  const SUMOReal distToCrossing = dist - myLengthsBehindCrossing[i].first;
399  //std::cout << " distToCrossing=" << distToCrossing << " foeLane=" << foeLane->getID() << "\n";
400  if (distToCrossing < 0) {
401  continue; // vehicle is behind the crossing point, continue with next foe lane
402  }
403  const SUMOReal foeDistToCrossing = foeLane->getLength() - myLengthsBehindCrossing[i].second;
404  // it is not sufficient to return the last vehicle on the foeLane because ego might be its leader
405  // therefore we return all vehicles on the lane
406  //
407  // special care must be taken for continuation lanes. (next lane is also internal)
408  // vehicles on these lanes should always block (gap = -1)
409  const bool contLane = (foeLane->getLinkCont()[0]->getViaLaneOrLane()->getEdge().getPurpose() == MSEdge::EDGEFUNCTION_INTERNAL);
410  const bool sameTarget = (myLane == foeLane->getLinkCont()[0]->getLane());
411  // vehicles on cont. lanes or on internal lanes with the same target as this link can never be ignored
412  const bool cannotIgnore = contLane || sameTarget;
413  const MSLane::VehCont& vehicles = foeLane->getVehiclesSecure();
414  foeLane->releaseVehicles();
415  for (MSLane::VehCont::const_iterator it_veh = vehicles.begin(); it_veh != vehicles.end(); ++it_veh) {
416  MSVehicle* leader = *it_veh;
417  if (cannotIgnore || leader->getWaitingTime() < MSGlobals::gIgnoreJunctionBlocker) {
418  // compute distance between vehicles on the the superimposition of both lanes
419  // where the crossing point is the common point
420  SUMOReal gap;
421  if (contLane) {
422  gap = -1; // always break for vehicles which are on a continuation lane
423  } else {
424  const SUMOReal leaderBack = leader->getPositionOnLane() - leader->getVehicleType().getLength();
425  const SUMOReal leaderBackDist = foeDistToCrossing - leaderBack;
426  //std::cout << " distToCrossing=" << distToCrossing << " leader backDist=" << leaderBackDist << "\n";
427  if (leaderBackDist < 0) {
428  // leader is completely past the crossing point
429  assert(!sameTarget);
430  continue; // next vehicle
431  }
432  gap = distToCrossing - leaderBackDist - (sameTarget ? minGap : 0);
433  }
434  result.push_back(std::make_pair(std::make_pair(leader, gap), sameTarget ? -1 : distToCrossing));
435  }
436 
437  }
438  MSVehicle* leader = foeLane->getPartialOccupator();
439  if (leader != 0) {
440  if (cannotIgnore || leader->getWaitingTime() < MSGlobals::gIgnoreJunctionBlocker) {
441  // compute distance between vehicles on the the superimposition of both lanes
442  // where the crossing point is the common point
443  SUMOReal gap;
444  if (contLane) {
445  gap = -1; // always break for vehicles which are on a continuation lane
446  } else {
447  const SUMOReal leaderBackDist = foeDistToCrossing - foeLane->getPartialOccupatorEnd();
448  //std::cout << " distToCrossing=" << distToCrossing << " leader (partialOccupator) backDist=" << leaderBackDist << "\n";
449  if (leaderBackDist < 0) {
450  // leader is completely past the crossing point
451  assert(!sameTarget);
452  continue; // next lane
453  }
454  gap = distToCrossing - leaderBackDist - (sameTarget ? minGap : 0);
455  }
456  result.push_back(std::make_pair(std::make_pair(leader, gap), sameTarget ? -1 : distToCrossing));
457  }
458  }
459  }
460  }
461  return result;
462 }
463 #endif
464 
465 
466 MSLane*
468 #ifdef HAVE_INTERNAL_LANES
469  if (myJunctionInlane != 0) {
470  return myJunctionInlane;
471  }
472 #endif
473  return myLane;
474 }
475 
476 
477 /****************************************************************************/
478 
OutputDevice & writeAttr(const SumoXMLAttr attr, const T &val)
writes a named attribute
Definition: OutputDevice.h:256
MSEdge & getEdge() const
Returns the lane's edge.
Definition: MSLane.h:452
Representation of a vehicle in the micro simulation.
Definition: MSVehicle.h:77
virtual void releaseVehicles() const
Allows to use the container for microsimulation again.
Definition: MSLane.h:303
const MSCFModel & getCarFollowModel() const
Returns the vehicle's car following model definition.
Definition: MSVehicle.h:531
SUMOReal getLengthWithGap() const
Get vehicle's length including the minimum gap [m].
SUMOTime getWaitingTime() const
Returns the SUMOTime waited (speed was lesser than 0.1m/s)
Definition: MSVehicle.h:362
This is an uncontrolled, minor link, has to stop.
SUMOReal getLength() const
Returns the lane's length.
Definition: MSLane.h:370
std::vector< MSVehicle * > VehCont
Container for vehicles.
Definition: MSLane.h:88
std::string time2string(SUMOTime t)
Definition: SUMOTime.cpp:61
SUMOReal getLength() const
Get vehicle's length [m].
SUMOReal getPositionOnLane() const
Get the vehicle's position along the lane.
Definition: MSVehicle.h:283
#define TIME2STEPS(x)
Definition: SUMOTime.h:66
This is an uncontrolled, all-way stop link.
#define UNUSED_PARAMETER(x)
Definition: StdDefs.h:38
virtual const VehCont & getVehiclesSecure() const
Returns the vehicles container; locks it for microsimulation.
Definition: MSLane.h:296
SUMOReal getPartialOccupatorEnd() const
Returns the position of the in-lapping vehicle's end.
Definition: MSLane.h:261
LinkDirection
The different directions a link between two lanes may take (or a stream between two edges)...
MSLane * getLogicalPredecessorLane() const
Definition: MSLane.cpp:1224
Representation of a vehicle.
Definition: SUMOVehicle.h:63
LinkState
The right-of-way state of a link between two lanes used when constructing a NBTrafficLightLogic, in MSLink and GNEInternalLane.
static bool gUsingInternalLanes
Information whether the simulation regards internal lanes.
Definition: MSGlobals.h:70
SUMOReal getMaxDecel() const
Get the vehicle type's maximum deceleration [m/s^2].
Definition: MSCFModel.h:165
virtual MSVehicle * getLastVehicle() const
returns the last vehicle
Definition: MSLane.cpp:932
std::string toString(const T &t, std::streamsize accuracy=OUTPUT_ACCURACY)
Definition: ToString.h:52
EdgeBasicFunction getPurpose() const
Returns the edge type (EdgeBasicFunction)
Definition: MSEdge.h:204
The link has red light (must brake)
const MSVehicleType & getVehicleType() const
Returns the vehicle's type definition.
Definition: MSBaseVehicle.h:94
SUMOReal getSpeed() const
Returns the vehicle's current speed.
Definition: MSVehicle.h:291
int SUMOTime
Definition: SUMOTime.h:43
static SUMOTime gIgnoreJunctionBlocker
Information whether the simulation regards internal lanes.
Definition: MSGlobals.h:73
const PositionVector & getShape() const
Returns this lane's shape.
Definition: MSLane.h:323
MSVehicle * getPartialOccupator() const
Returns the vehicle which laps into this lane.
Definition: MSLane.h:253
Static storage of an output device and its base (abstract) implementation.
Definition: OutputDevice.h:70
bool closeTag()
Closes the most recently opened tag.
#define SUMOReal
Definition: config.h:215
static const bool gUseMesoSim
Definition: MSGlobals.h:98
const MSLinkCont & getLinkCont() const
returns the container with all links !!!
Definition: MSLane.cpp:998
The edge is an internal edge.
Definition: MSEdge.h:90
std::vector< SUMOReal > intersectsAtLengths2D(const PositionVector &other) const
For all intersections between this vector and other, return the 2D-length of the subvector from this ...
Representation of a lane in the micro simulation.
Definition: MSLane.h:77
OutputDevice & openTag(const std::string &xmlElement)
Opens an XML tag.
virtual const MSVehicleType & getVehicleType() const =0
Returns the vehicle's type.