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-2013 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  myRequestIdx(0), myRespondIdx(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  myRequestIdx(0), myRespondIdx(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 requestIdx, unsigned int respondIdx, bool isCrossing, bool isCont,
82  const std::vector<MSLink*>& foeLinks,
83  const std::vector<MSLane*>& foeLanes,
84  MSLane* internalLaneBefore) {
85  myRequestIdx = requestIdx;
86  myRespondIdx = respondIdx;
88  myAmCont = isCont;
89  myFoeLinks = foeLinks;
90  myFoeLanes = foeLanes;
91 #ifdef HAVE_INTERNAL_LANES
92  if (internalLaneBefore != 0) {
93  // this is an exit link. compute crossing points with all foeLanes
94  for (std::vector<MSLane*>::const_iterator it_lane = myFoeLanes.begin(); it_lane != myFoeLanes.end(); ++it_lane) {
95  if (myLane == (*it_lane)->getLinkCont()[0]->getLane()) {
96  // this foeLane has the same target
97  myLengthsBehindCrossing.push_back(std::make_pair(0, 0)); // dummy value, never used
98  } else {
99  std::vector<SUMOReal> intersections1 = internalLaneBefore->getShape().intersectsAtLengths2D((*it_lane)->getShape());
100  //std::cout << " number of intersections1=" << intersections1.size() << "\n";
101  if (intersections1.size() == 0) {
102  intersections1.push_back(0);
103  } else if (intersections1.size() > 1) {
104  std::sort(intersections1.begin(), intersections1.end());
105  }
106  std::vector<SUMOReal> intersections2 = (*it_lane)->getShape().intersectsAtLengths2D(internalLaneBefore->getShape());
107  //std::cout << " number of intersections2=" << intersections2.size() << "\n";
108  if (intersections2.size() == 0) {
109  intersections2.push_back(0);
110  } else if (intersections2.size() > 1) {
111  std::sort(intersections2.begin(), intersections2.end());
112  }
113  myLengthsBehindCrossing.push_back(std::make_pair(
114  internalLaneBefore->getLength() - intersections1.back(),
115  (*it_lane)->getLength() - intersections2.back()));
116  //std::cout
117  // << " intersection of " << internalLaneBefore->getID()
118  // << " totalLength=" << internalLaneBefore->getLength()
119  // << " with " << (*it_lane)->getID()
120  // << " totalLength=" << (*it_lane)->getLength()
121  // << " dist1=" << myLengthsBehindCrossing.back().first
122  // << " dist2=" << myLengthsBehindCrossing.back().second
123  // << "\n";
124  }
125  }
126  }
127 #else
128  UNUSED_PARAMETER(internalLaneBefore);
129 #endif
130 }
131 
132 
133 void
134 MSLink::setApproaching(const SUMOVehicle* approaching, const SUMOTime arrivalTime, const SUMOReal arrivalSpeed, const SUMOReal leaveSpeed,
135  const bool setRequest, const SUMOTime arrivalTimeBraking, const SUMOReal arrivalSpeedBraking, const SUMOTime waitingTime) {
136  const SUMOTime leaveTime = getLeaveTime(arrivalTime, arrivalSpeed, leaveSpeed, approaching->getVehicleType().getLengthWithGap());
137  myApproachingVehicles.insert(std::make_pair(approaching,
138  ApproachingVehicleInformation(arrivalTime, leaveTime, arrivalSpeed, leaveSpeed, setRequest,
139  arrivalTimeBraking, arrivalSpeedBraking, waitingTime)));
140 }
141 
142 
143 void
145  myBlockedFoeLinks.insert(link);
146 }
147 
148 
149 
150 bool
152  for (std::set<MSLink*>::const_iterator i = myBlockedFoeLinks.begin(); i != myBlockedFoeLinks.end(); ++i) {
153  if ((*i)->isBlockingAnyone()) {
154  return true;
155  }
156  }
157  return false;
158 }
159 
160 
161 void
163  myApproachingVehicles.erase(veh);
164 }
165 
166 
169  std::map<const SUMOVehicle*, ApproachingVehicleInformation>::const_iterator i = myApproachingVehicles.find(veh);
170  if (i != myApproachingVehicles.end()) {
171  return i->second;
172  } else {
173  return ApproachingVehicleInformation(-1000, -1000, 0, 0, false, -1000, 0, 0);
174  }
175 }
176 
177 
178 SUMOTime
179 MSLink::getLeaveTime(SUMOTime arrivalTime, SUMOReal arrivalSpeed, SUMOReal leaveSpeed, SUMOReal vehicleLength) const {
180  return arrivalTime + TIME2STEPS((getLength() + vehicleLength) / (0.5 * (arrivalSpeed + leaveSpeed)));
181 }
182 
183 
184 bool
185 MSLink::opened(SUMOTime arrivalTime, SUMOReal arrivalSpeed, SUMOReal leaveSpeed, SUMOReal vehicleLength,
186  SUMOReal impatience, SUMOReal decel, SUMOTime waitingTime,
187  std::vector<const SUMOVehicle*>* collectFoes) const {
188  if (myState == LINKSTATE_TL_RED) {
189  return false;
190  }
192  return true;
193  }
194  if ((myState == LINKSTATE_STOP || myState == LINKSTATE_ALLWAY_STOP) && waitingTime == 0) {
195  return false;
196  }
197  const SUMOTime leaveTime = getLeaveTime(arrivalTime, arrivalSpeed, leaveSpeed, vehicleLength);
198  for (std::vector<MSLink*>::const_iterator i = myFoeLinks.begin(); i != myFoeLinks.end(); ++i) {
199 #ifdef HAVE_INTERNAL
201  if ((*i)->getState() == LINKSTATE_TL_RED) {
202  continue;
203  }
204  }
205 #endif
206  if ((*i)->blockedAtTime(arrivalTime, leaveTime, arrivalSpeed, leaveSpeed, myLane == (*i)->getLane(),
207  impatience, decel, waitingTime, collectFoes)) {
208  return false;
209  }
210  }
211  return true;
212 }
213 
214 
215 bool
216 MSLink::blockedAtTime(SUMOTime arrivalTime, SUMOTime leaveTime, SUMOReal arrivalSpeed, SUMOReal leaveSpeed,
217  bool sameTargetLane, SUMOReal impatience, SUMOReal decel, SUMOTime waitingTime,
218  std::vector<const SUMOVehicle*>* collectFoes) const {
219  for (std::map<const SUMOVehicle*, ApproachingVehicleInformation>::const_iterator i = myApproachingVehicles.begin(); i != myApproachingVehicles.end(); ++i) {
220  if (!i->second.willPass) {
221  continue;
222  }
224  assert(waitingTime > 0);
225  if (waitingTime > i->second.waitingTime) {
226  continue;
227  }
228  if (waitingTime == i->second.waitingTime && arrivalTime < i->second.arrivalTime) {
229  continue;
230  }
231  }
232  const SUMOTime foeArrivalTime = (SUMOTime)((1.0 - impatience) * i->second.arrivalTime + impatience * i->second.arrivalTimeBraking);
233  if (i->second.leavingTime < arrivalTime) {
234  // ego wants to be follower
235  if (sameTargetLane && (arrivalTime - i->second.leavingTime < myLookaheadTime
236  || unsafeMergeSpeeds(i->second.leaveSpeed, arrivalSpeed,
237  i->first->getVehicleType().getCarFollowModel().getMaxDecel(), decel))) {
238  if (collectFoes == 0) {
239  return true;
240  } else {
241  collectFoes->push_back(i->first);
242  }
243  }
244  } else if (foeArrivalTime > leaveTime) {
245  // ego wants to be leader.
246  if (sameTargetLane && (foeArrivalTime - leaveTime < myLookaheadTime
247  || unsafeMergeSpeeds(leaveSpeed, i->second.arrivalSpeedBraking,
248  decel, i->first->getVehicleType().getCarFollowModel().getMaxDecel()))) {
249  if (collectFoes == 0) {
250  return true;
251  } else {
252  collectFoes->push_back(i->first);
253  }
254  }
255  } else {
256  // even without considering safeHeadwayTime there is already a conflict
257  if (collectFoes == 0) {
258  return true;
259  } else {
260  collectFoes->push_back(i->first);
261  }
262  }
263  }
264  return false;
265 }
266 
267 
268 bool
270  MSVehicle* veh = lane->getLastVehicle();
271  SUMOReal distLeft = 0;
272  if (veh == 0) {
273  veh = lane->getPartialOccupator();
274  distLeft = lane->getLength() - lane->getPartialOccupatorEnd();
275  } else {
276  distLeft = lane->getLength() - veh->getPositionOnLane() + veh->getVehicleType().getLength();
277  }
278  if (veh == 0) {
279  return false;
280  } else {
281  assert(distLeft > 0);
282  // can we be sure that the vehicle leaves this lane in the next step?
283  bool result = distLeft > (veh->getSpeed() - veh->getCarFollowModel().getMaxDecel());
284  return result;
285  }
286 }
287 
288 
289 bool
290 MSLink::hasApproachingFoe(SUMOTime arrivalTime, SUMOTime leaveTime, SUMOReal speed, SUMOReal decel) const {
291  for (std::vector<MSLink*>::const_iterator i = myFoeLinks.begin(); i != myFoeLinks.end(); ++i) {
292  if ((*i)->blockedAtTime(arrivalTime, leaveTime, speed, speed, myLane == (*i)->getLane(), 0, decel, 0)) {
293  return true;
294  }
295  }
296  for (std::vector<MSLane*>::const_iterator i = myFoeLanes.begin(); i != myFoeLanes.end(); ++i) {
297  if ((*i)->getVehicleNumber() > 0 || (*i)->getPartialOccupator() != 0) {
298  return true;
299  }
300  }
301  return false;
302 }
303 
304 
307  return myDirection;
308 }
309 
310 
311 void
313  myState = state;
314 }
315 
316 
317 MSLane*
319  return myLane;
320 }
321 
322 
323 void
324 MSLink::writeApproaching(OutputDevice& od, const std::string fromLaneID) const {
325  if (myApproachingVehicles.size() > 0) {
326  od.openTag("link");
327  od.writeAttr(SUMO_ATTR_FROM, fromLaneID);
328 #ifdef HAVE_INTERNAL_LANES
329  const std::string via = getViaLane() == 0 ? "" : getViaLane()->getID();
330 #else
331  const std::string via = "";
332 #endif
333  od.writeAttr(SUMO_ATTR_VIA, via);
334  od.writeAttr(SUMO_ATTR_TO, getLane() == 0 ? "" : getLane()->getID());
335  std::vector<std::pair<SUMOTime, const SUMOVehicle*> > toSort; // stabilize output
336  for (std::map<const SUMOVehicle*, ApproachingVehicleInformation>::const_iterator it = myApproachingVehicles.begin(); it != myApproachingVehicles.end(); ++it) {
337  toSort.push_back(std::make_pair(it->second.arrivalTime, it->first));
338  }
339  std::sort(toSort.begin(), toSort.end());
340  for (std::vector<std::pair<SUMOTime, const SUMOVehicle*> >::const_iterator it = toSort.begin(); it != toSort.end(); ++it) {
341  od.openTag("approaching");
342  const ApproachingVehicleInformation& avi = myApproachingVehicles.find(it->second)->second;
343  od.writeAttr(SUMO_ATTR_ID, it->second->getID());
344  od.writeAttr("arrivalTime", time2string(avi.arrivalTime));
345  od.writeAttr("leaveTime", time2string(avi.leavingTime));
346  od.writeAttr("arrivalSpeed", toString(avi.arrivalSpeed));
347  od.writeAttr("leaveSpeed", toString(avi.leaveSpeed));
348  od.writeAttr("willPass", toString(avi.willPass));
349  od.closeTag();
350  }
351  od.closeTag();
352  }
353 }
354 
355 
356 #ifdef HAVE_INTERNAL_LANES
357 MSLane*
358 MSLink::getViaLane() const {
359  return myJunctionInlane;
360 }
361 
362 
364 MSLink::getLeaderInfo(SUMOReal dist, SUMOReal minGap) const {
365  LinkLeaders result;
366  if (MSGlobals::gUsingInternalLanes && myJunctionInlane == 0 &&
367  getLane()->getEdge().getPurpose() != MSEdge::EDGEFUNCTION_INTERNAL) {
368  //std::cout << " getLeaderInfo link=" << getViaLaneOrLane()->getID() << "\n";
369  // this is an exit link
370  for (size_t i = 0; i < myFoeLanes.size(); ++i) {
371  MSLane* foeLane = myFoeLanes[i];
372  // distance from the querying vehicle to the crossing point with foeLane
373  const SUMOReal distToCrossing = dist - myLengthsBehindCrossing[i].first;
374  //std::cout << " distToCrossing=" << distToCrossing << " foeLane=" << foeLane->getID() << "\n";
375  if (distToCrossing < 0) {
376  continue; // vehicle is behind the crossing point, continue with next foe lane
377  }
378  const SUMOReal foeDistToCrossing = foeLane->getLength() - myLengthsBehindCrossing[i].second;
379  // it is not sufficient to return the last vehicle on the foeLane because ego might be its leader
380  // therefore we return all vehicles on the lane
381  //
382  // special care must be taken for continuation lanes. (next lane is also internal)
383  // vehicles on these lanes should always block (gap = -1)
384  const bool contLane = (foeLane->getLinkCont()[0]->getViaLaneOrLane()->getEdge().getPurpose() == MSEdge::EDGEFUNCTION_INTERNAL);
385  const bool sameTarget = (myLane == foeLane->getLinkCont()[0]->getLane());
386  // vehicles on cont. lanes or on internal lanes with the same target as this link can never be ignored
387  const bool cannotIgnore = contLane || sameTarget;
388  const MSLane::VehCont& vehicles = foeLane->getVehiclesSecure();
389  foeLane->releaseVehicles();
390  for (MSLane::VehCont::const_iterator it_veh = vehicles.begin(); it_veh != vehicles.end(); ++it_veh) {
391  MSVehicle* leader = *it_veh;
392  if (cannotIgnore || leader->getWaitingTime() < MSGlobals::gIgnoreJunctionBlocker) {
393  // compute distance between vehicles on the the superimposition of both lanes
394  // where the crossing point is the common point
395  SUMOReal gap;
396  if (contLane) {
397  gap = -1; // always break for vehicles which are on a continuation lane
398  } else {
399  const SUMOReal leaderBack = leader->getPositionOnLane() - leader->getVehicleType().getLength();
400  const SUMOReal leaderBackDist = foeDistToCrossing - leaderBack;
401  //std::cout << " distToCrossing=" << distToCrossing << " leader backDist=" << leaderBackDist << "\n";
402  if (leaderBackDist < 0) {
403  // leader is completely past the crossing point
404  assert(!sameTarget);
405  continue; // next vehicle
406  }
407  gap = distToCrossing - leaderBackDist - (sameTarget ? minGap : 0);
408  }
409  result.push_back(std::make_pair(leader, gap));
410  }
411 
412  }
413  MSVehicle* leader = foeLane->getPartialOccupator();
414  if (leader != 0) {
415  if (cannotIgnore || leader->getWaitingTime() < MSGlobals::gIgnoreJunctionBlocker) {
416  // compute distance between vehicles on the the superimposition of both lanes
417  // where the crossing point is the common point
418  SUMOReal gap;
419  if (contLane) {
420  gap = -1; // always break for vehicles which are on a continuation lane
421  } else {
422  const SUMOReal leaderBackDist = foeDistToCrossing - foeLane->getPartialOccupatorEnd();
423  //std::cout << " distToCrossing=" << distToCrossing << " leader (partialOccupator) backDist=" << leaderBackDist << "\n";
424  if (leaderBackDist < 0) {
425  // leader is completely past the crossing point
426  assert(!sameTarget);
427  continue; // next lane
428  }
429  gap = distToCrossing - leaderBackDist - (sameTarget ? minGap : 0);
430  }
431  result.push_back(std::make_pair(leader, gap));
432  }
433  }
434  }
435  }
436  return result;
437 }
438 #endif
439 
440 
441 MSLane*
443 #ifdef HAVE_INTERNAL_LANES
444  if (myJunctionInlane != 0) {
445  return myJunctionInlane;
446  }
447 #endif
448  return myLane;
449 }
450 
451 
452 unsigned int
454  return myRespondIdx;
455 }
456 
457 
458 
459 /****************************************************************************/
460 
OutputDevice & writeAttr(const SumoXMLAttr attr, const T &val)
writes a named attribute
Definition: OutputDevice.h:254
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&#39;s car following model definition.
Definition: MSVehicle.h:510
SUMOReal getLengthWithGap() const
Get vehicle&#39;s length including the minimum gap [m].
SUMOTime getWaitingTime() const
Returns the SUMOTime waited (speed was lesser than 0.1m/s)
Definition: MSVehicle.h:341
This is an uncontrolled, minor link, has to stop.
SUMOReal getLength() const
Returns the lane&#39;s length.
Definition: MSLane.h:365
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&#39;s length [m].
SUMOReal getPositionOnLane() const
Get the vehicle&#39;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:36
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&#39;s end.
Definition: MSLane.h:261
LinkDirection
The different directions a link between two lanes may take (or a stream between two edges)...
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&#39;s maximum deceleration [m/s^2].
Definition: MSCFModel.h:165
virtual MSVehicle * getLastVehicle() const
returns the last vehicle
Definition: MSLane.cpp:915
std::string toString(const T &t, std::streamsize accuracy=OUTPUT_ACCURACY)
Definition: ToString.h:51
The link has red light (must brake)
const MSVehicleType & getVehicleType() const
Returns the vehicle&#39;s type definition.
Definition: MSBaseVehicle.h:94
SUMOReal getSpeed() const
Returns the vehicle&#39;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&#39;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:981
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&#39;s type.