SUMO - Simulation of Urban MObility
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
MSAbstractLaneChangeModel.cpp
Go to the documentation of this file.
1 /****************************************************************************/
11 // Interface for lane-change models
12 /****************************************************************************/
13 // SUMO, Simulation of Urban MObility; see http://sumo-sim.org/
14 // Copyright (C) 2001-2014 DLR (http://www.dlr.de/) and contributors
15 /****************************************************************************/
16 //
17 // This file is part of SUMO.
18 // SUMO is free software: you can redistribute it and/or modify
19 // it under the terms of the GNU General Public License as published by
20 // the Free Software Foundation, either version 3 of the License, or
21 // (at your option) any later version.
22 //
23 /****************************************************************************/
24 
25 // ===========================================================================
26 // included modules
27 // ===========================================================================
28 #ifdef _MSC_VER
29 #include <windows_config.h>
30 #else
31 #include <config.h>
32 #endif
33 
36 #include "MSLCM_DK2008.h"
37 #include "MSLCM_LC2013.h"
38 #include "MSLCM_JE2013.h"
39 #include "MSNet.h"
40 #include "MSEdge.h"
41 #include "MSLane.h"
42 #include "MSGlobals.h"
43 
44 /* -------------------------------------------------------------------------
45  * static members
46  * ----------------------------------------------------------------------- */
48 
49 /* -------------------------------------------------------------------------
50  * MSAbstractLaneChangeModel-methods
51  * ----------------------------------------------------------------------- */
52 
53 void
55  myAllowOvertakingRight = oc.getBool("lanechange.overtake-right");
56 }
57 
58 
61  switch (lcm) {
62  case LCM_DK2008:
63  return new MSLCM_DK2008(v);
64  case LCM_LC2013:
65  return new MSLCM_LC2013(v);
66  case LCM_JE2013:
67  return new MSLCM_JE2013(v);
68  default:
69  throw ProcessError("Lane change model '" + toString(lcm) + "' not implemented");
70  }
71 }
72 
73 
75  myVehicle(v),
76  myOwnState(0),
77  myLastLaneChangeOffset(0),
78  myLaneChangeCompletion(1.0),
79  myLaneChangeDirection(0),
80  myLaneChangeMidpointPassed(false),
81  myAlreadyMoved(false),
82  myShadowLane(0),
83  myHaveShadow(false),
84  myCarFollowModel(v.getCarFollowModel()) {
85 }
86 
87 
89  if (myShadowLane != 0 && myHaveShadow) {
91  }
92 }
93 
94 
95 bool
97  if (neighLeader == 0) {
98  return false;
99  }
100  // Congested situation are relevant only on highways (maxSpeed > 70km/h)
101  // and congested on German Highways means that the vehicles have speeds
102  // below 60km/h. Overtaking on the right is allowed then.
103  if ((myVehicle.getLane()->getSpeedLimit() <= 70.0 / 3.6) || (neighLeader->getLane()->getSpeedLimit() <= 70.0 / 3.6)) {
104 
105  return false;
106  }
107  if (myVehicle.congested() && neighLeader->congested()) {
108  return true;
109  }
110  return false;
111 }
112 
113 
114 bool
116  if (leader == 0) {
117  return false;
118  }
119  // let's check it on highways only
120  if (leader->getSpeed() < (80.0 / 3.6)) {
121  return false;
122  }
124  return gap < myCarFollowModel.interactionGap(&myVehicle, leader->getSpeed());
125 }
126 
127 
128 bool
130  target->enteredByLaneChange(&myVehicle);
133  myShadowLane = target;
134  myHaveShadow = true;
136  myLaneChangeDirection = direction;
138  return true;
139  } else {
141  source->leftByLaneChange(&myVehicle);
144  changed();
145  return false;
146  }
147 }
148 
149 
150 void
152  if (moved && myHaveShadow) {
153  // move shadow to next lane
156  myShadowLane = myVehicle.getLane()->getParallelLane(shadowDirection);
157  if (myShadowLane == 0) {
158  // abort lane change
159  WRITE_WARNING("Vehicle '" + myVehicle.getID() + "' could not finish continuous lane change (lane disappeared) time=" +
160  time2string(MSNet::getInstance()->getCurrentTimeStep()) + ".");
162  return;
163  }
164  myHaveShadow = true;
165  }
169  // maneuver midpoint reached, swap myLane and myShadowLane
171  MSLane* tmp = myVehicle.getLane();
174  myShadowLane = tmp;
175  if (myVehicle.fixPosition()) {
176  WRITE_WARNING("vehicle '" + myVehicle.getID() + "' set back by " + toString(myVehicle.getPositionOnLane() - myVehicle.getLane()->getLength()) +
177  "m when changing lanes on lane '" + myVehicle.getLane()->getID() + " time=" +
178  time2string(MSNet::getInstance()->getCurrentTimeStep()) + ".");
179  }
181  changed();
182  myAlreadyMoved = true;
183  }
184  // remove shadow as soon as the vehicle leaves the original lane geometrically
186  const SUMOReal sourceHalfWidth = myShadowLane->getWidth() / 2.0;
187  const SUMOReal targetHalfWidth = myVehicle.getLane()->getWidth() / 2.0;
188  if (myLaneChangeCompletion * (sourceHalfWidth + targetHalfWidth) - myVehicle.getVehicleType().getWidth() / 2.0 > sourceHalfWidth) {
190  }
191  }
192  // finish maneuver
193  if (!isChangingLanes()) {
196  }
197 }
198 
199 
200 void
202  if (myShadowLane != 0 && myHaveShadow) {
204  myHaveShadow = false;
205  }
206 }
207 
208 
209 bool
211  int ret = myVehicle.influenceChangeDecision(state);
212  return ret != state;
213 }