Eclipse SUMO - Simulation of Urban MObility
Loading...
Searching...
No Matches
MSLCM_LC2013.cpp
Go to the documentation of this file.
1/****************************************************************************/
2// Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
3// Copyright (C) 2001-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/****************************************************************************/
24// A lane change model developed by J. Erdmann
25// based on the model of D. Krajzewicz developed between 2004 and 2011 (MSLCM_DK2004)
26/****************************************************************************/
27#include <config.h>
28
29#include <iostream>
35#include <microsim/MSEdge.h>
36#include <microsim/MSLane.h>
37#include <microsim/MSLink.h>
39#include <microsim/MSNet.h>
40#include <microsim/MSStop.h>
41#include "MSLCHelper.h"
42#include "MSLCM_LC2013.h"
43
44
45// ===========================================================================
46// variable definitions
47// ===========================================================================
48#define LOOK_FORWARD 10.
49
50#define JAM_FACTOR 1.
51
52#define LCA_RIGHT_IMPATIENCE -1.
53#define CUT_IN_LEFT_SPEED_THRESHOLD 27.
54
55#define LOOK_AHEAD_MIN_SPEED 0.0
56#define LOOK_AHEAD_SPEED_MEMORY 0.9
57
58#define HELP_DECEL_FACTOR 1.0
59
60#define HELP_OVERTAKE (10.0 / 3.6)
61#define MIN_FALLBEHIND (7.0 / 3.6)
62
63#define RELGAIN_NORMALIZATION_MIN_SPEED 10.0
64#define URGENCY 2.0
65#define OPPOSITE_URGENCY 5.0
66
67#define KEEP_RIGHT_TIME 5.0 // the number of seconds after which a vehicle should move to the right lane
68
69#define KEEP_RIGHT_HEADWAY 2.0
70#define MAX_ONRAMP_LENGTH 200.
71#define TURN_LANE_DIST 200.0 // the distance at which a lane leading elsewhere is considered to be a turn-lane that must be avoided
72
73#define LC_RESOLUTION_SPEED_LAT 0.5 // the lateral speed (in m/s) for a standing vehicle which was unable to finish a continuous LC in time (in case mySpeedLatStanding==0), see #3771
74
75#define REACT_TO_STOPPED_DISTANCE 100
76#define BLOCKER_IS_BLOCKED_TIME_THRESHOLD 5 // the time after which a blocking neighbor is treated similar to a stopped vehicle
77
78#define HYST_PRECISION 10000000
79
80// ===========================================================================
81// debug defines
82// ===========================================================================
83//#define DEBUG_CONSTRUCTOR
84//#define DEBUG_PATCH_SPEED
85//#define DEBUG_INFORMED
86//#define DEBUG_INFORMER
87//#define DEBUG_WANTS_CHANGE
88//#define DEBUG_SLOW_DOWN
89//#define DEBUG_COOPERATE
90//#define DEBUG_SAVE_BLOCKER_LENGTH
91
92//#define DEBUG_COND (myVehicle.getID() == "ego")
93#define DEBUG_COND (myVehicle.isSelected())
94//#define DEBUG_COND (true)
95
96// ===========================================================================
97// member method definitions
98// ===========================================================================
101 mySpeedGainProbabilityLeft(0),
102 mySpeedGainProbabilityRight(0),
103 myKeepRightProbability(0),
104 myLeadingBlockerLength(0),
105 myLeftSpace(0),
106 myLookAheadSpeed(LOOK_AHEAD_MIN_SPEED),
107 myDontBrake(false),
108 myStrategicParam(v.getVehicleType().getParameter().getLCParam(SUMO_ATTR_LCA_STRATEGIC_PARAM, 1)),
109 myCooperativeParam(v.getVehicleType().getParameter().getLCParam(SUMO_ATTR_LCA_COOPERATIVE_PARAM, 1)),
110 mySpeedGainParam(v.getVehicleType().getParameter().getLCParam(SUMO_ATTR_LCA_SPEEDGAIN_PARAM, 1)),
111 myKeepRightParam(v.getVehicleType().getParameter().getLCParam(SUMO_ATTR_LCA_KEEPRIGHT_PARAM, 1)),
112 myOppositeParam(v.getVehicleType().getParameter().getLCParam(SUMO_ATTR_LCA_OPPOSITE_PARAM, 1)),
113 myLookaheadLeft(v.getVehicleType().getParameter().getLCParam(SUMO_ATTR_LCA_LOOKAHEADLEFT, 2.0)),
114 mySpeedGainRight(v.getVehicleType().getParameter().getLCParam(SUMO_ATTR_LCA_SPEEDGAINRIGHT, 0.1)),
115 mySpeedGainLookahead(v.getVehicleType().getParameter().getLCParam(SUMO_ATTR_LCA_SPEEDGAIN_LOOKAHEAD, 0)),
116 mySpeedGainRemainTime(v.getVehicleType().getParameter().getLCParam(SUMO_ATTR_LCA_SPEEDGAIN_REMAIN_TIME, 20)),
117 mySpeedGainUrgency(v.getVehicleType().getParameter().getLCParam(SUMO_ATTR_LCA_SPEEDGAIN_URGENCY, 50)),
118 myRoundaboutBonus(v.getVehicleType().getParameter().getLCParam(SUMO_ATTR_LCA_COOPERATIVE_ROUNDABOUT, myCooperativeParam)),
119 myCooperativeSpeed(v.getVehicleType().getParameter().getLCParam(SUMO_ATTR_LCA_COOPERATIVE_SPEED, myCooperativeParam)),
120 myKeepRightAcceptanceTime(v.getVehicleType().getParameter().getLCParam(SUMO_ATTR_LCA_KEEPRIGHT_ACCEPTANCE_TIME, -1)),
121 myOvertakeDeltaSpeedFactor(v.getVehicleType().getParameter().getLCParam(SUMO_ATTR_LCA_OVERTAKE_DELTASPEED_FACTOR, 0)),
122 myExperimentalParam1(v.getVehicleType().getParameter().getLCParam(SUMO_ATTR_LCA_EXPERIMENTAL1, 0)) {
124#ifdef DEBUG_CONSTRUCTOR
125 if (DEBUG_COND) {
126 std::cout << SIMTIME
127 << " create lcModel veh=" << myVehicle.getID()
128 << " lcStrategic=" << myStrategicParam
129 << " lcCooperative=" << myCooperativeParam
130 << " lcSpeedGain=" << mySpeedGainParam
131 << " lcKeepRight=" << myKeepRightParam
132 << "\n";
133 }
134#endif
135}
136
140
141
142void
144 if (mySpeedGainParam <= 0) {
145 myChangeProbThresholdRight = std::numeric_limits<long long int>::max();
146 myChangeProbThresholdLeft = std::numeric_limits<long long int>::max();
147 } else {
150 }
151}
152
153
154bool
156 return DEBUG_COND;
157}
158
159
160int
162 int laneOffset,
164 int blocked,
165 const std::pair<MSVehicle*, double>& leader,
166 const std::pair<MSVehicle*, double>& follower,
167 const std::pair<MSVehicle*, double>& neighLead,
168 const std::pair<MSVehicle*, double>& neighFollow,
169 const MSLane& neighLane,
170 const std::vector<MSVehicle::LaneQ>& preb,
171 MSVehicle** lastBlocked,
172 MSVehicle** firstBlocked) {
173
174#ifdef DEBUG_WANTS_CHANGE
175 if (DEBUG_COND) {
176 std::cout << "\nWANTS_CHANGE\n" << SIMTIME
177 << std::setprecision(gPrecision)
178 << " veh=" << myVehicle.getID()
179 << " lane=" << myVehicle.getLane()->getID()
180 << " pos=" << myVehicle.getPositionOnLane()
181 << " posLat=" << myVehicle.getLateralPositionOnLane()
182 << " speed=" << myVehicle.getSpeed()
183 << " considerChangeTo=" << (laneOffset == -1 ? "right" : "left")
184 << "\n";
185 }
186#endif
187
188 const int result = _wantsChange(laneOffset, msgPass, blocked, leader, follower, neighLead, neighFollow, neighLane, preb, *lastBlocked, *firstBlocked);
189
190#ifdef DEBUG_WANTS_CHANGE
191 if (DEBUG_COND) {
192 std::cout << SIMTIME << " veh=" << myVehicle.getID() << " result=" << toString((LaneChangeAction)result) << " blocked=" << toString((LaneChangeAction)blocked) << "\n\n\n";
193 }
194#endif
195
196 return result;
197}
198
199
200double
201MSLCM_LC2013::patchSpeed(const double min, const double wanted, const double max, const MSCFModel& cfModel) {
202
203#ifdef DEBUG_PATCH_SPEED
204 if (DEBUG_COND) {
205 std::cout << "\nPATCH_SPEED\n"
206 << SIMTIME
207 << " veh=" << myVehicle.getID()
208 << " lane=" << myVehicle.getLane()->getID()
209 << " pos=" << myVehicle.getPositionOnLane()
210 << " v=" << myVehicle.getSpeed()
211 << " min=" << min
212 << " wanted=" << wanted
213 << " max=" << max
214 << "\n";
215 }
216#endif
217
218 // negative min speed may be passed when using ballistic updated
219 const double newSpeed = _patchSpeed(MAX2(min, 0.0), wanted, max, cfModel);
220
221#ifdef DEBUG_PATCH_SPEED
222 if (DEBUG_COND) {
223 const std::string patched = (wanted != newSpeed ? " patched=" + toString(newSpeed) : "");
224 std::cout << patched
225 << "\n";
226 }
227#endif
228
229 return newSpeed;
230}
231
232
233double
234MSLCM_LC2013::_patchSpeed(double min, const double wanted, double max, const MSCFModel& cfModel) {
235 int state = myOwnState;
236#ifdef DEBUG_PATCH_SPEED
237 if (DEBUG_COND) {
238 std::cout
239 << "\n" << SIMTIME << std::setprecision(gPrecision)
240 << " patchSpeed state=" << toString((LaneChangeAction)state) << " myLCAccelerationAdvices=" << toString(myLCAccelerationAdvices)
241 << "\n speed=" << myVehicle.getSpeed() << " min=" << min << " wanted=" << wanted
242 << "\n myLeadingBlockerLength=" << myLeadingBlockerLength
243 << "\n";
244 }
245#endif
246
247 // letting vehicles merge in at the end of the lane in case of counter-lane change, step#2
248 double nVSafe = wanted;
249 bool gotOne = false;
250 // if we want to change and have a blocking leader and there is enough room for him in front of us
251 if (myLeadingBlockerLength != 0) {
252 double space = myLeftSpace - myLeadingBlockerLength - POSITION_EPS;
253#ifdef DEBUG_PATCH_SPEED
254 if (DEBUG_COND) {
255 std::cout << SIMTIME << " veh=" << myVehicle.getID() << " myLeftSpace=" << myLeftSpace << " myLeadingBlockerLength=" << myLeadingBlockerLength << " space=" << space << "\n";
256 }
257#endif
258 if (space > 0 && (myVehicle.getLane()->isNormal() || myVehicle.getCurrentEdge()->isRoundabout())) {
259 // compute speed for decelerating towards a place which allows the blocking leader to merge in in front
262 max = MIN2(max, MAX2(safe, vMinEmergency));
263 // if we are approaching this place
264 if (safe < wanted) {
265 // return this speed as the speed to use
266 if (safe < min) {
267 if (safe >= vMinEmergency) {
268 // permit harder braking if needed and helpful
269 min = MAX2(vMinEmergency, safe);
270 }
271 }
272#ifdef DEBUG_PATCH_SPEED
273 if (DEBUG_COND) {
274 std::cout << SIMTIME << " veh=" << myVehicle.getID() << " slowing down for leading blocker, safe=" << safe << (safe + NUMERICAL_EPS < min ? " (not enough)" : "") << "\n";
275 }
276#endif
277 nVSafe = MAX2(min, safe);
278 gotOne = true;
279 }
280 }
281 }
282
283 const double coopWeight = MAX2(0.0, MIN2(1.0, myCooperativeSpeed));
284 for (auto i : myLCAccelerationAdvices) {
285 double a = i.first;
286 double v = myVehicle.getSpeed() + ACCEL2SPEED(a);
287
288 if (v >= min && v <= max && (MSGlobals::gSemiImplicitEulerUpdate
289 // ballistic update: (negative speeds may appear, e.g. min<0, v<0), BUT:
290 // XXX: LaneChanging returns -1 to indicate no restrictions, which leads to probs here (Leo), refs. #2577
291 // As a quick fix, we just dismiss cases where v=-1
292 // VERY rarely (whenever a requested help-acceleration is really indicated by v=-1)
293 // this can lead to failing lane-change attempts, though)
294 || v != -1)) {
295 if (i.second) {
296 // own advice, no scaling needed
297 nVSafe = MIN2(v, nVSafe);
298 } else {
299 nVSafe = MIN2(v * coopWeight + (1 - coopWeight) * wanted, nVSafe);
300 }
301 gotOne = true;
302#ifdef DEBUG_PATCH_SPEED
303 if (DEBUG_COND) {
304 std::cout << SIMTIME << " veh=" << myVehicle.getID() << " got nVSafe=" << nVSafe << " isOwn: " << i.second << " rawV=" << v << "\n";
305 }
306#endif
307 } else {
308 if (v < min) {
309#ifdef DEBUG_PATCH_SPEED
310 if (DEBUG_COND) {
311 std::cout << SIMTIME << " veh=" << myVehicle.getID() << " ignoring low nVSafe=" << v << " min=" << min << "\n";
312 }
313#endif
314 } else {
315#ifdef DEBUG_PATCH_SPEED
316 if (DEBUG_COND) {
317 std::cout << SIMTIME << " veh=" << myVehicle.getID() << " ignoring high nVSafe=" << v << " max=" << max << "\n";
318 }
319#endif
320 }
321 }
322 }
323 // myDontBrake is used in counter-lane-change situations with relief connection
324 if (gotOne && !myDontBrake) {
325#ifdef DEBUG_PATCH_SPEED
326 if (DEBUG_COND) {
327 std::cout << SIMTIME << " veh=" << myVehicle.getID() << " got vSafe\n";
328 }
329#endif
330 return nVSafe;
331 }
332
333 // check whether the vehicle is blocked
334 if ((state & LCA_WANTS_LANECHANGE) != 0 && (state & LCA_BLOCKED) != 0) {
335 if ((state & LCA_STRATEGIC) != 0) {
336 // necessary decelerations are controlled via vSafe. If there are
337 // none it means we should speed up
338#ifdef DEBUG_PATCH_SPEED
339 if (DEBUG_COND) {
340 std::cout << SIMTIME << " veh=" << myVehicle.getID() << " LCA_WANTS_LANECHANGE (strat, no vSafe)\n";
341 }
342#endif
343 return (max + wanted) / 2.0;
344 } else if ((state & LCA_COOPERATIVE) != 0) {
345 // only minor adjustments in speed should be done
346 if ((state & LCA_BLOCKED_BY_LEADER) != 0) {
347#ifdef DEBUG_PATCH_SPEED
348 if (DEBUG_COND) {
349 std::cout << SIMTIME << " veh=" << myVehicle.getID() << " LCA_BLOCKED_BY_LEADER (coop)\n";
350 }
351#endif
352 if (wanted >= 0.) {
353 return (MAX2(0., min) + wanted) / 2.0;
354 } else {
355 return wanted;
356 }
357 }
358 if ((state & LCA_BLOCKED_BY_FOLLOWER) != 0) {
359#ifdef DEBUG_PATCH_SPEED
360 if (DEBUG_COND) {
361 std::cout << SIMTIME << " veh=" << myVehicle.getID() << " LCA_BLOCKED_BY_FOLLOWER (coop)\n";
362 }
363#endif
364 return (max + wanted) / 2.0;
365 }
366 //} else { // VARIANT_16
367 // // only accelerations should be performed
368 // if ((state & LCA_BLOCKED_BY_FOLLOWER) != 0) {
369 // if (gDebugFlag2) std::cout << SIMTIME << " veh=" << myVehicle.getID() << " LCA_BLOCKED_BY_FOLLOWER\n";
370 // return (max + wanted) / 2.0;
371 // }
372 }
373 }
374
375 /*
376 // decelerate if being a blocking follower
377 // (and does not have to change lanes)
378 if ((state & LCA_AMBLOCKINGFOLLOWER) != 0) {
379 if (fabs(max - myVehicle.getCarFollowModel().maxNextSpeed(myVehicle.getSpeed(), &myVehicle)) < 0.001 && min == 0) { // !!! was standing
380 if (gDebugFlag2) std::cout << SIMTIME << " veh=" << myVehicle.getID() << " LCA_AMBLOCKINGFOLLOWER (standing)\n";
381 return 0;
382 }
383 if (gDebugFlag2) std::cout << SIMTIME << " veh=" << myVehicle.getID() << " LCA_AMBLOCKINGFOLLOWER\n";
384
385 //return min; // VARIANT_3 (brakeStrong)
386 return (min + wanted) / 2.0;
387 }
388 if ((state & LCA_AMBACKBLOCKER) != 0) {
389 if (max <= myVehicle.getCarFollowModel().maxNextSpeed(myVehicle.getSpeed(), &myVehicle) && min == 0) { // !!! was standing
390 if (gDebugFlag2) std::cout << SIMTIME << " veh=" << myVehicle.getID() << " LCA_AMBACKBLOCKER (standing)\n";
391 //return min; VARIANT_9 (backBlockVSafe)
392 return nVSafe;
393 }
394 }
395 if ((state & LCA_AMBACKBLOCKER_STANDING) != 0) {
396 if (gDebugFlag2) std::cout << SIMTIME << " veh=" << myVehicle.getID() << " LCA_AMBACKBLOCKER_STANDING\n";
397 //return min;
398 return nVSafe;
399 }
400 */
401
402 // accelerate if being a blocking leader or blocking follower not able to brake
403 // (and does not have to change lanes)
404 if ((state & LCA_AMBLOCKINGLEADER) != 0 && myCooperativeSpeed >= 0) {
405#ifdef DEBUG_PATCH_SPEED
406 if (DEBUG_COND) {
407 std::cout << SIMTIME << " veh=" << myVehicle.getID() << " LCA_AMBLOCKINGLEADER\n";
408 }
409#endif
410 return (max + wanted) / 2.0;
411 }
412
413 if ((state & LCA_AMBLOCKINGFOLLOWER_DONTBRAKE) != 0) {
414#ifdef DEBUG_PATCH_SPEED
415 if (DEBUG_COND) {
416 std::cout << SIMTIME << " veh=" << myVehicle.getID() << " LCA_AMBLOCKINGFOLLOWER_DONTBRAKE\n";
417 }
418#endif
419 /*
420 // VARIANT_4 (dontbrake)
421 if (max <= myVehicle.getCarFollowModel().maxNextSpeed(myVehicle.getSpeed(), &myVehicle) && min == 0) { // !!! was standing
422 return wanted;
423 }
424 return (min + wanted) / 2.0;
425 */
426 }
428 // remove chaning information if on a road with a single lane
429 changed();
430 }
431 return wanted;
432}
433
434
435void*
436MSLCM_LC2013::inform(void* info, MSVehicle* sender) {
437 UNUSED_PARAMETER(sender);
438 Info* pinfo = (Info*)info;
439 assert(pinfo->first >= 0 || !MSGlobals::gSemiImplicitEulerUpdate);
440 addLCSpeedAdvice(pinfo->first, false);
441 myOwnState |= pinfo->second;
442#ifdef DEBUG_INFORMED
443 if (DEBUG_COND) {
444 std::cout << SIMTIME
445 << " veh=" << myVehicle.getID()
446 << " informedBy=" << sender->getID()
447 << " info=" << pinfo->second
448 << " vSafe=" << pinfo->first
449 << "\n";
450 }
451#endif
452 delete pinfo;
453 return (void*) true;
454}
455
456double
457MSLCM_LC2013::overtakeDistance(const MSVehicle* follower, const MSVehicle* leader, const double gap, double followerSpeed, double leaderSpeed) {
458 followerSpeed = followerSpeed == INVALID_SPEED ? follower->getSpeed() : followerSpeed;
459 leaderSpeed = leaderSpeed == INVALID_SPEED ? leader->getSpeed() : leaderSpeed;
460 double overtakeDist = (gap // drive to back of leader
461 + leader->getVehicleType().getLengthWithGap() // drive to front of leader
462 + follower->getVehicleType().getLength() // follower back reaches leader front
463 + leader->getCarFollowModel().getSecureGap( // save gap to leader
464 leader, follower, leaderSpeed, followerSpeed, follower->getCarFollowModel().getMaxDecel()));
465 return MAX2(overtakeDist, 0.);
466}
467
468
469double
471 int blocked,
472 int dir,
473 const std::pair<MSVehicle*, double>& neighLead,
474 double remainingSeconds) {
475 double plannedSpeed = myVehicle.getSpeed();
476 if (!isOpposite()) {
477 plannedSpeed = MIN2(plannedSpeed,
479 }
480 for (auto i : myLCAccelerationAdvices) {
481 const double a = i.first;
483 plannedSpeed = MIN2(plannedSpeed, myVehicle.getSpeed() + ACCEL2SPEED(a));
484 }
485 }
486#ifdef DEBUG_INFORMER
487 if (DEBUG_COND) {
488 std::cout << "\nINFORM_LEADER"
489 << "\nspeed=" << myVehicle.getSpeed() << " planned=" << plannedSpeed << "\n";
490 }
491#endif
492
493 const MSVehicle* const nv = neighLead.first;
494 if (nv == nullptr) {
495 // not overtaking
496 return plannedSpeed;
497 }
498 const double neighNextSpeed = nv->getSpeed() - ACCEL2SPEED(MAX2(1.0, -nv->getAcceleration()));
499 double neighNextGap;
501 neighNextGap = neighLead.second + SPEED2DIST(neighNextSpeed - plannedSpeed);
502 } else {
503 neighNextGap = neighLead.second + SPEED2DIST((nv->getSpeed() + neighNextSpeed) / 2) - SPEED2DIST((myVehicle.getSpeed() + plannedSpeed) / 2);
504 }
505 if ((blocked & LCA_BLOCKED_BY_LEADER) != 0) {
507 //std::cout << SIMTIME << " ego=" << myVehicle.getID() << " ignoresDivergentBlockingLeader=" << nv->getID() << "\n";
508 return plannedSpeed;
509 }
510#ifdef DEBUG_INFORMER
511 if (DEBUG_COND) {
512 std::cout << " blocked by leader nv=" << nv->getID() << " nvSpeed=" << nv->getSpeed() << " needGap="
514 }
515#endif
516 // decide whether we want to overtake the leader or follow it
517 double overtakeTime;
518 const double overtakeDist = overtakeDistance(&myVehicle, nv, neighLead.second);
519 const double dv = plannedSpeed - nv->getSpeed();
520
522 overtakeTime = overtakeDist / dv;
524 && !isOpposite()
526 // -> set overtakeTime to indicate possibility of overtaking (only if there is enough space)
527 overtakeTime = remainingSeconds - 1;
528 } else {
529 // -> set overtakeTime to something indicating impossibility of overtaking
530 overtakeTime = remainingSeconds + 1;
531 }
532
533#ifdef DEBUG_INFORMER
534 if (DEBUG_COND) {
535 std::cout << SIMTIME << " informLeader() of " << myVehicle.getID()
536 << "\nnv = " << nv->getID()
537 << "\nplannedSpeed = " << plannedSpeed
538 << "\nleaderSpeed = " << nv->getSpeed()
539 << "\nmyLeftSpace = " << myLeftSpace
540 << "\nremainingSeconds = " << remainingSeconds
541 << "\novertakeDist = " << overtakeDist
542 << "\novertakeTime = " << overtakeTime
543 << std::endl;
544 }
545#endif
546
548 // overtaking on the right on an uncongested highway is forbidden (noOvertakeLCLeft)
549 || (dir == LCA_MLEFT && avoidOvertakeRight(neighLead.first))
550 // not enough space to overtake?
552 // using brakeGap() without headway seems adequate in a situation where the obstacle (the lane end) is not moving [XXX implemented in branch ticket860, can be used in general if desired, refs. #2575] (Leo).
554 // not enough time to overtake? (skipped for a stopped leader [currently only for ballistic update XXX: check if appropriate for euler, too, refs. #2575] to ensure that it can be overtaken if only enough space is exists) (Leo)
555 || (remainingSeconds < overtakeTime && (MSGlobals::gSemiImplicitEulerUpdate || !nv->isStopped())))
556 // opposite driving and must overtake
557 && (!neighLead.first->isStopped() || (isOpposite() && neighLead.second >= 0))) {
558 // cannot overtake
559 msgPass.informNeighLeader(new Info(std::numeric_limits<double>::max(), dir | LCA_AMBLOCKINGLEADER), &myVehicle);
560 // slow down smoothly to follow leader
561 // account for minor decelerations by the leader (dawdling)
563 getCarFollowModel().followSpeed(&myVehicle, myVehicle.getSpeed(), neighNextGap, neighNextSpeed, nv->getCarFollowModel().getMaxDecel()),
564 // avoid changing on intersection
566 if (targetSpeed < myVehicle.getSpeed()) {
567 // slow down smoothly to follow leader
568 const double decel = remainingSeconds == 0. ? myVehicle.getCarFollowModel().getMaxDecel() :
570 MAX2(MIN_FALLBEHIND, (myVehicle.getSpeed() - targetSpeed) / remainingSeconds));
571 const double nextSpeed = MIN2(plannedSpeed, MAX2(0.0, myVehicle.getSpeed() - ACCEL2SPEED(decel)));
572#ifdef DEBUG_INFORMER
573 if (DEBUG_COND) {
574 std::cout << SIMTIME
575 << " cannot overtake leader nv=" << nv->getID()
576 << " dv=" << dv
577 << " myLookAheadSpeed=" << myLookAheadSpeed
578 << " myLeftSpace=" << myLeftSpace
579 << " overtakeDist=" << overtakeDist
580 << " overtakeTime=" << overtakeTime
581 << " remainingSeconds=" << remainingSeconds
582 << " currentGap=" << neighLead.second
583 << " brakeGap=" << myVehicle.getCarFollowModel().brakeGap(myVehicle.getSpeed(), getCarFollowModel().getMaxDecel(), 0.)
584 << " neighNextSpeed=" << neighNextSpeed
585 << " neighNextGap=" << neighNextGap
586 << " targetSpeed=" << targetSpeed
587 << " nextSpeed=" << nextSpeed
588 << "\n";
589 }
590#endif
591 addLCSpeedAdvice(nextSpeed);
592 return nextSpeed;
593 } else {
594 // leader is fast enough anyway
595#ifdef DEBUG_INFORMER
596 if (DEBUG_COND) {
597 std::cout << SIMTIME
598 << " cannot overtake fast leader nv=" << nv->getID()
599 << " dv=" << dv
600 << " myLookAheadSpeed=" << myLookAheadSpeed
601 << " myLeftSpace=" << myLeftSpace
602 << " overtakeDist=" << overtakeDist
603 << " myLeadingBlockerLength=" << myLeadingBlockerLength
604 << " overtakeTime=" << overtakeTime
605 << " remainingSeconds=" << remainingSeconds
606 << " currentGap=" << neighLead.second
607 << " neighNextSpeed=" << neighNextSpeed
608 << " neighNextGap=" << neighNextGap
609 << " targetSpeed=" << targetSpeed
610 << "\n";
611 }
612#endif
613 addLCSpeedAdvice(targetSpeed);
614 return plannedSpeed;
615 }
616 } else {
617 // overtaking, leader should not accelerate
618#ifdef DEBUG_INFORMER
619 if (DEBUG_COND) {
620 std::cout << SIMTIME
621 << " wants to overtake leader nv=" << nv->getID()
622 << " dv=" << dv
623 << " overtakeDist=" << overtakeDist
624 << " remainingSeconds=" << remainingSeconds
625 << " overtakeTime=" << overtakeTime
626 << " currentGap=" << neighLead.second
628 << "\n";
629 }
630#endif
631 // no need to pass a message if the neighbor is waiting/stuck anyway (but sending it would risk deadlock)
633 msgPass.informNeighLeader(new Info(nv->getSpeed(), dir | LCA_AMBLOCKINGLEADER), &myVehicle);
634 }
635 return -1; // XXX: using -1 is ambiguous for the ballistic update! Currently this is being catched in patchSpeed() (Leo), consider returning INVALID_SPEED, refs. #2577
636 }
637 } else { // (remainUnblocked)
638 // we are not blocked now. make sure we stay far enough from the leader
639 const double targetSpeed = MAX2(
641 getCarFollowModel().followSpeed(&myVehicle, myVehicle.getSpeed(), neighNextGap, neighNextSpeed, nv->getCarFollowModel().getMaxDecel()));
642 addLCSpeedAdvice(targetSpeed);
643#ifdef DEBUG_INFORMER
644 if (DEBUG_COND) {
645 std::cout << " not blocked by leader nv=" << nv->getID()
646 << " nvSpeed=" << nv->getSpeed()
647 << " gap=" << neighLead.second
648 << " neighNextSpeed=" << neighNextSpeed
649 << " neighNextGap=" << neighNextGap
651 << " targetSpeed=" << targetSpeed
652 << "\n";
653 }
654#endif
655 return MIN2(targetSpeed, plannedSpeed);
656 }
657}
658
659void
661 int blocked,
662 int dir,
663 const std::pair<MSVehicle*, double>& neighFollow,
664 double remainingSeconds,
665 double plannedSpeed) {
666
667 MSVehicle* nv = neighFollow.first;
668 const double plannedAccel = SPEED2ACCEL(MAX2(MIN2(getCarFollowModel().getMaxAccel(), plannedSpeed - myVehicle.getSpeed()), -getCarFollowModel().getMaxDecel()));
669
670#ifdef DEBUG_INFORMER
671 if (DEBUG_COND) {
672 std::cout << "\nINFORM_FOLLOWER"
673 << "\nspeed=" << myVehicle.getSpeed() << " planned=" << plannedSpeed << "\n";
674 }
675
676#endif
677 if ((blocked & LCA_BLOCKED_BY_FOLLOWER) != 0 && nv != nullptr) {
679 //std::cout << SIMTIME << " ego=" << myVehicle.getID() << " ignoresDivergentBlockingFollower=" << nv->getID() << "\n";
680 return;
681 }
682#ifdef DEBUG_INFORMER
683 if (DEBUG_COND) {
684 std::cout << " blocked by follower nv=" << nv->getID() << " nvSpeed=" << nv->getSpeed() << " needGap="
685 << nv->getCarFollowModel().getSecureGap(nv, &myVehicle, nv->getSpeed(), myVehicle.getSpeed(), myVehicle.getCarFollowModel().getMaxDecel()) << " planned=" << plannedSpeed << "\n";
686 }
687#endif
688
689 // are we fast enough to cut in without any help?
690 if (MAX2(plannedSpeed, 0.) - nv->getSpeed() >= HELP_OVERTAKE) {
691 const double neededGap = nv->getCarFollowModel().getSecureGap(nv, &myVehicle, nv->getSpeed(), plannedSpeed, myVehicle.getCarFollowModel().getMaxDecel());
692 if ((neededGap - neighFollow.second) / remainingSeconds < (MAX2(plannedSpeed, 0.) - nv->getSpeed())) {
693#ifdef DEBUG_INFORMER
694 if (DEBUG_COND) {
695 std::cout << " wants to cut in before nv=" << nv->getID() << " without any help." << "\nneededGap = " << neededGap << "\n";
696 }
697#endif
698 // follower might even accelerate but not to much
699 // XXX: I don't understand this. The needed gap was determined for nv->getSpeed(), not for (plannedSpeed - HELP_OVERTAKE)?! (Leo), refs. #2578
700 msgPass.informNeighFollower(new Info(MAX2(plannedSpeed, 0.) - HELP_OVERTAKE, dir | LCA_AMBLOCKINGFOLLOWER), &myVehicle);
701 return;
702 }
703 }
704
705 // decide whether we will request help to cut in before the follower or allow to be overtaken
706
707 // PARAMETERS
708 // assume other vehicle will assume the equivalent of 1 second of
709 // maximum deceleration to help us (will probably be spread over
710 // multiple seconds)
711 // -----------
712 const double helpDecel = nv->getCarFollowModel().getMaxDecel() * HELP_DECEL_FACTOR;
713
714 // follower's new speed in next step
715 double neighNewSpeed;
716 // follower's new speed after 1s.
717 double neighNewSpeed1s;
718 // velocity difference, gap after follower-deceleration
719 double dv, decelGap;
720
722 // euler
723 neighNewSpeed = MAX2(0., nv->getSpeed() - ACCEL2SPEED(helpDecel));
724 neighNewSpeed1s = MAX2(0., nv->getSpeed() - helpDecel); // TODO: consider introduction of a configurable anticipationTime here (see far below in the !blocked part). Refs. #2578
725 // change in the gap between ego and blocker over 1 second (not STEP!)
726 // XXX: though here it is calculated as if it were one step!? (Leo) Refs. #2578
727 dv = plannedSpeed - neighNewSpeed1s; // XXX: what is this quantity (if TS!=1)?
728 // new gap between follower and self in case the follower does brake for 1s
729 // XXX: if the step-length is not 1s., this is not the gap after 1s. deceleration!
730 // And this formula overestimates the real gap. Isn't that problematic? (Leo)
731 // Below, it seems that decelGap > secureGap is taken to indicate the possibility
732 // to cut in within the next time-step. However, this is not the case, if TS<1s.,
733 // since decelGap is (not exactly, though!) the gap after 1s. Refs. #2578
734 decelGap = neighFollow.second + dv;
735 } else {
736 // ballistic
737 // negative newSpeed-extrapolation possible, if stop lies within the next time-step
738 // XXX: this code should work for the euler case as well, since gapExtrapolation() takes
739 // care of this, but for TS!=1 we will have different behavior (see previous remark) Refs. #2578
740 neighNewSpeed = nv->getSpeed() - ACCEL2SPEED(helpDecel);
741 neighNewSpeed1s = nv->getSpeed() - helpDecel;
742
743 dv = myVehicle.getSpeed() - nv->getSpeed(); // current velocity difference
744 decelGap = getCarFollowModel().gapExtrapolation(1., neighFollow.second, myVehicle.getSpeed(),
745 nv->getSpeed(), plannedAccel, -helpDecel, myVehicle.getMaxSpeedOnLane(), nv->getMaxSpeedOnLane());
746 }
747
748 const double secureGap = nv->getCarFollowModel().getSecureGap(nv, &myVehicle, MAX2(neighNewSpeed1s, 0.),
749 MAX2(plannedSpeed, 0.), myVehicle.getCarFollowModel().getMaxDecel());
750
751 const double onRampThreshold = myVehicle.getLane()->getSpeedLimit() * 0.8 * myExperimentalParam1 * (1 - myVehicle.getImpatience());
752
753#ifdef DEBUG_INFORMER
754 if (DEBUG_COND) {
755 std::cout << SIMTIME
756 << " speed=" << myVehicle.getSpeed()
757 << " plannedSpeed=" << plannedSpeed
758 << " threshold=" << onRampThreshold
759 << " neighNewSpeed=" << neighNewSpeed
760 << " neighNewSpeed1s=" << neighNewSpeed1s
761 << " dv=" << dv
762 << " gap=" << neighFollow.second
763 << " decelGap=" << decelGap
764 << " secureGap=" << secureGap
765 << "\n";
766 }
767#endif
768 // prevent vehicles on an on ramp stopping the main flow
769 if (dir == LCA_MLEFT
771 && neighNewSpeed1s < onRampThreshold) {
772 return;
773 }
774
775 if (decelGap > 0 && decelGap >= secureGap) {
776 // XXX: This does not assure that the leader can cut in in the next step if TS < 1 (see above)
777 // this seems to be supposed in the following (euler code)...?! (Leo) Refs. #2578
778
779 // if the blocking follower brakes it could help
780 // how hard does it actually need to be?
781 // to be safe in the next step the following equation has to hold for the follower's vsafe:
782 // vsafe <= followSpeed(gap=currentGap - SPEED2DIST(vsafe), ...)
783 double vsafe, vsafe1;
784
786 // euler
787 // we compute an upper bound on vsafe by doing the computation twice
788 vsafe1 = MAX2(neighNewSpeed, nv->getCarFollowModel().followSpeed(
789 nv, nv->getSpeed(), neighFollow.second + SPEED2DIST(plannedSpeed), plannedSpeed, getCarFollowModel().getMaxDecel()));
790 vsafe = MAX2(neighNewSpeed, nv->getCarFollowModel().followSpeed(
791 nv, nv->getSpeed(), neighFollow.second + SPEED2DIST(plannedSpeed - vsafe1), plannedSpeed, getCarFollowModel().getMaxDecel()));
792 //assert(vsafe <= vsafe1); assertion does not hold for models with randomness in followSpeed (W99)
793 } else {
794 // ballistic
795
796 // XXX: This block should actually do as well for euler update (TODO: test!), refs #2575
797 // we compute an upper bound on vsafe
798 // next step's gap without help deceleration (nv's speed assumed constant)
799 double nextGap = getCarFollowModel().gapExtrapolation(TS,
800 neighFollow.second, myVehicle.getSpeed(),
801 nv->getSpeed(), plannedAccel, 0,
803#ifdef DEBUG_INFORMER
804 if (DEBUG_COND) {
805 std::cout << "nextGap=" << nextGap << " (without help decel) \n";
806 }
807#endif
808
809 // NOTE: the second argument of MIN2() can get larger than nv->getSpeed()
810 vsafe1 = MIN2(nv->getSpeed(), MAX2(neighNewSpeed,
812 nv->getSpeed(), nextGap,
813 MAX2(0., plannedSpeed),
814 getCarFollowModel().getMaxDecel())));
815
816
817 // next step's gap with possibly less than maximal help deceleration (in case vsafe1 > neighNewSpeed)
818 double decel2 = SPEED2ACCEL(nv->getSpeed() - vsafe1);
820 neighFollow.second, myVehicle.getSpeed(),
821 nv->getSpeed(), plannedAccel, -decel2,
823
824 // vsafe = MAX(neighNewSpeed, safe speed assuming next_gap)
825 // Thus, the gap resulting from vsafe is larger or equal to next_gap
826 // in contrast to the euler case, where nv's follow speed doesn't depend on the actual speed,
827 // we need to assure, that nv doesn't accelerate
828 vsafe = MIN2(nv->getSpeed(), MAX2(neighNewSpeed,
830 nv->getSpeed(), nextGap,
831 MAX2(0., plannedSpeed),
832 getCarFollowModel().getMaxDecel())));
833
834 assert(vsafe >= vsafe1 - NUMERICAL_EPS);
835
836#ifdef DEBUG_INFORMER
837 if (DEBUG_COND) {
838 std::cout << "nextGap=" << nextGap
839 << " (with vsafe1 and help decel) \nvsafe1=" << vsafe1
840 << " vsafe=" << vsafe
841 << "\n";
842 }
843#endif
844
845 // For subsecond simulation, this might not lead to secure gaps for a long time,
846 // we seek to establish a secure gap as soon as possible
847 double nextSecureGap = nv->getCarFollowModel().getSecureGap(nv, &myVehicle, vsafe, plannedSpeed, getCarFollowModel().getMaxDecel());
848
849 if (nextGap < nextSecureGap) {
850 // establish a secureGap as soon as possible
851 vsafe = neighNewSpeed;
852 }
853
854#ifdef DEBUG_INFORMER
855 if (DEBUG_COND) {
856 std::cout << "nextGap=" << nextGap
857 << " minNextSecureGap=" << nextSecureGap
858 << " vsafe=" << vsafe << "\n";
859 }
860#endif
861
862 }
863 msgPass.informNeighFollower(
864 new Info(vsafe, dir | LCA_AMBLOCKINGFOLLOWER), &myVehicle);
865
866#ifdef DEBUG_INFORMER
867 if (DEBUG_COND) {
868 std::cout << " wants to cut in before nv=" << nv->getID()
869 << " vsafe1=" << vsafe1 << " vsafe=" << vsafe
870 << " newSecGap="
871 << nv->getCarFollowModel().getSecureGap(nv, &myVehicle, vsafe,
872 plannedSpeed,
874 << "\n";
875 }
876#endif
877 } else if ((MSGlobals::gSemiImplicitEulerUpdate && dv > 0 && dv * remainingSeconds > (secureGap - decelGap + POSITION_EPS))
878 || (!MSGlobals::gSemiImplicitEulerUpdate && dv > 0 && dv * (remainingSeconds - 1) > secureGap - decelGap + POSITION_EPS)
879 ) {
880
881 // XXX: Alternative formulation (encapsulating differences of euler and ballistic) TODO: test, refs. #2575
882 // double eventualGap = getCarFollowModel().gapExtrapolation(remainingSeconds - 1., decelGap, plannedSpeed, neighNewSpeed1s);
883 // } else if (eventualGap > secureGap + POSITION_EPS) {
884
885
886 // NOTE: This case corresponds to the situation, where some time is left to perform the lc
887 // For the ballistic case this is interpreted as follows:
888 // If the follower breaks with helpDecel for one second, this vehicle maintains the plannedSpeed,
889 // and both continue with their speeds for remainingSeconds seconds the gap will suffice for a laneChange
890 // For the euler case we had the following comment:
891 // 'decelerating once is sufficient to open up a large enough gap in time', but:
892 // XXX: 1) Decelerating *once* does not necessarily lead to the gap decelGap! (if TS<1s.) (Leo)
893 // 2) Probably, the if() for euler should test for dv * (remainingSeconds-1) > ..., too ?!, refs. #2578
894 msgPass.informNeighFollower(new Info(neighNewSpeed, dir | LCA_AMBLOCKINGFOLLOWER), &myVehicle);
895#ifdef DEBUG_INFORMER
896 if (DEBUG_COND) {
897 std::cout << " wants to cut in before nv=" << nv->getID() << " (eventually)\n";
898 }
899#endif
900 } else if (dir == LCA_MRIGHT && nv->getLaneChangeModel().avoidOvertakeRight(&myVehicle)) {
901 // XXX: check if this requires a special treatment for the ballistic update, refs. #2575
902 const double vhelp = MAX2(neighNewSpeed, HELP_OVERTAKE);
903 msgPass.informNeighFollower(new Info(vhelp, dir | LCA_AMBLOCKINGFOLLOWER), &myVehicle);
904#ifdef DEBUG_INFORMER
905 if (DEBUG_COND) {
906 std::cout << " wants to cut in before nv=" << nv->getID() << " (nv cannot overtake right)\n";
907 }
908#endif
909 } else {
910 double vhelp = MAX2(nv->getSpeed(), myVehicle.getSpeed() + HELP_OVERTAKE);
911 //if (dir == LCA_MRIGHT && myVehicle.getWaitingSeconds() > LCA_RIGHT_IMPATIENCE &&
912 // nv->getSpeed() > myVehicle.getSpeed()) {
913 if (nv->getSpeed() > myVehicle.getSpeed() &&
914 ((dir == LCA_MRIGHT && myVehicle.getWaitingSeconds() > LCA_RIGHT_IMPATIENCE) // NOTE: it might be considered to use myVehicle.getAccumulatedWaitingSeconds() > LCA_RIGHT_IMPATIENCE instead (Leo). Refs. #2578
915 || (dir == LCA_MLEFT && plannedSpeed > CUT_IN_LEFT_SPEED_THRESHOLD) // VARIANT_22 (slowDownLeft)
916 // XXX this is a hack to determine whether the vehicles is on an on-ramp. This information should be retrieved from the network itself
918 )) {
919 // let the follower slow down to increase the likelihood that later vehicles will be slow enough to help
920 // follower should still be fast enough to open a gap
921 // XXX: The probability for that success would be larger if the slow down of the appropriate following vehicle
922 // would take place without the immediate follower slowing down. We might consider to model reactions of
923 // vehicles that are not immediate followers. (Leo) -> see ticket #2532
924 vhelp = MAX2(neighNewSpeed, myVehicle.getSpeed() + HELP_OVERTAKE);
925#ifdef DEBUG_INFORMER
926 if (DEBUG_COND) {
927 // NOTE: the condition labeled "VARIANT_22" seems to imply that this could as well concern the *left* follower?! (Leo)
928 // Further, vhelp might be larger than nv->getSpeed(), so the request issued below is not to slow down!? (see below) Refs. #2578
929 std::cout << " wants right follower to slow down a bit\n";
930 }
931#endif
933 // euler
934 if ((nv->getSpeed() - myVehicle.getSpeed()) / helpDecel < remainingSeconds) {
935
936#ifdef DEBUG_INFORMER
937 if (DEBUG_COND) {
938 // NOTE: the condition labeled "VARIANT_22" seems to imply that this could as well concern the *left* follower?! Refs. #2578
939 std::cout << " wants to cut in before right follower nv=" << nv->getID() << " (eventually)\n";
940 }
941#endif
942 // XXX: I don't understand. This vhelp might be larger than nv->getSpeed() but the above condition seems to rely
943 // on the reasoning that if nv breaks with helpDecel for remaining Seconds, nv will be so slow, that this
944 // vehicle will be able to cut in. But nv might have overtaken this vehicle already (or am I missing sth?). (Leo)
945 // Ad: To my impression, the intention behind allowing larger speeds for the blocking follower is to prevent a
946 // situation, where an overlapping follower keeps blocking the ego vehicle. Refs. #2578
947 msgPass.informNeighFollower(new Info(vhelp, dir | LCA_AMBLOCKINGFOLLOWER), &myVehicle);
948 return;
949 }
950 } else {
951
952 // ballistic (this block is a bit different to the logic in the euler part, but in general suited to work on euler as well.. must be tested <- TODO, refs. #2575)
953 // estimate gap after remainingSeconds.
954 // Assumptions:
955 // (A1) leader continues with currentSpeed. (XXX: That might be wrong: Think of accelerating on an on-ramp or of a congested region ahead!)
956 // (A2) follower breaks with helpDecel.
957 const double gapAfterRemainingSecs = getCarFollowModel().gapExtrapolation(
958 remainingSeconds, neighFollow.second, myVehicle.getSpeed(), nv->getSpeed(), 0, -helpDecel, myVehicle.getMaxSpeedOnLane(), nv->getMaxSpeedOnLane());
959 const double secureGapAfterRemainingSecs = nv->getCarFollowModel().getSecureGap(nv, &myVehicle,
960 MAX2(nv->getSpeed() - remainingSeconds * helpDecel, 0.), myVehicle.getSpeed(), myVehicle.getCarFollowModel().getMaxDecel());
961 if (gapAfterRemainingSecs >= secureGapAfterRemainingSecs) { // XXX: here it would be wise to check whether there is enough space for eventual braking if the maneuver doesn't succeed
962#ifdef DEBUG_INFORMER
963 if (DEBUG_COND) {
964 std::cout << " wants to cut in before follower nv=" << nv->getID() << " (eventually)\n";
965 }
966#endif
967 // NOTE: ballistic uses neighNewSpeed instead of vhelp, see my note above. (Leo)
968 // TODO: recheck if this might cause suboptimal behaviour in some LC-situations. Refs. #2578
969 msgPass.informNeighFollower(new Info(neighNewSpeed, dir | LCA_AMBLOCKINGFOLLOWER), &myVehicle);
970 return;
971 }
972 }
973
974
975 }
976
977#ifdef DEBUG_INFORMER
978 if (DEBUG_COND) {
979 std::cout << SIMTIME
980 << " veh=" << myVehicle.getID()
981 << " informs follower " << nv->getID()
982 << " vhelp=" << vhelp
983 << "\n";
984 }
985#endif
986
987 msgPass.informNeighFollower(new Info(vhelp, dir | LCA_AMBLOCKINGFOLLOWER), &myVehicle);
988 // This follower is supposed to overtake us. Slow down smoothly to allow this.
989 const double overtakeDist = overtakeDistance(nv, &myVehicle, neighFollow.second, vhelp, plannedSpeed);
990 // speed difference to create a sufficiently large gap
991 const double needDV = overtakeDist / remainingSeconds;
992 // make sure the deceleration is not to strong (XXX: should be assured in finalizeSpeed -> TODO: remove the MAX2 if agreed) -> prob with possibly non-existing maximal deceleration for som CF Models(?) Refs. #2578
994
995#ifdef DEBUG_INFORMER
996 if (DEBUG_COND) {
997 std::cout << SIMTIME
998 << " veh=" << myVehicle.getID()
999 << " wants to be overtaken by=" << nv->getID()
1000 << " overtakeDist=" << overtakeDist
1001 << " vneigh=" << nv->getSpeed()
1002 << " vhelp=" << vhelp
1003 << " needDV=" << needDV
1004 << " vsafe=" << myLCAccelerationAdvices.back().first
1005 << "\n";
1006 }
1007#endif
1008 }
1009 } else if (neighFollow.first != nullptr && (blocked & LCA_BLOCKED_BY_LEADER)) {
1010 // we are not blocked by the follower now, make sure it remains that way
1011 const double vsafe = MSLCHelper::getSpeedPreservingSecureGap(myVehicle, *neighFollow.first, neighFollow.second, plannedSpeed);
1012 msgPass.informNeighFollower(new Info(vsafe, dir), &myVehicle);
1013
1014#ifdef DEBUG_INFORMER
1015 if (DEBUG_COND) {
1016 std::cout << " wants to cut in before non-blocking follower nv=" << nv->getID() << "\n";
1017 }
1018#endif
1019 }
1020}
1021
1022
1023void
1026 // keep information about strategic change direction
1027 if (!isChangingLanes()) {
1029 }
1031 myLeftSpace = 0;
1033 myDontBrake = false;
1034 // truncate to work around numerical instability between different builds
1035 if (mySigma > 0 && !isChangingLanes()) {
1036 // disturb lateral position directly
1037 const double maxDist = SPEED2DIST(myVehicle.getVehicleType().getMaxSpeedLat());
1038 const double oldPosLat = myVehicle.getLateralPositionOnLane();
1039 const double overlap = myVehicle.getLateralOverlap();
1040 double scaledDelta;
1041 if (overlap > 0) {
1042 // return to within lane boundary
1043 scaledDelta = MIN2(overlap, maxDist);
1045 scaledDelta *= -1;
1046 }
1047 } else {
1048 // random drift
1049 double deltaPosLat = OUProcess::step(oldPosLat,
1051 MAX2(NUMERICAL_EPS, (1 - mySigma) * 100), mySigma) - oldPosLat;
1052 deltaPosLat = MAX2(MIN2(deltaPosLat, maxDist), -maxDist);
1053 scaledDelta = deltaPosLat * myVehicle.getSpeed() / myVehicle.getLane()->getSpeedLimit();
1054 }
1055 myVehicle.setLateralPositionOnLane(oldPosLat + scaledDelta);
1056 setSpeedLat(DIST2SPEED(scaledDelta));
1057 } else {
1058 resetSpeedLat();
1059 }
1060}
1061
1062
1063void
1065 myOwnState = 0;
1069 if (myVehicle.getBestLaneOffset() == 0) {
1070 // if we are not yet on our best lane there might still be unseen blockers
1071 // (during patchSpeed)
1073 myLeftSpace = 0;
1074 }
1077 myDontBrake = false;
1079}
1080
1081
1082void
1094
1095
1096int
1098 int laneOffset,
1100 int blocked,
1101 const std::pair<MSVehicle*, double>& leader,
1102 const std::pair<MSVehicle*, double>& follower,
1103 const std::pair<MSVehicle*, double>& neighLead,
1104 const std::pair<MSVehicle*, double>& neighFollow,
1105 const MSLane& neighLane,
1106 const std::vector<MSVehicle::LaneQ>& preb,
1107 MSVehicle* lastBlocked,
1108 MSVehicle* firstBlocked) {
1109 assert(laneOffset == 1 || laneOffset == -1);
1110 const SUMOTime currentTime = MSNet::getInstance()->getCurrentTimeStep();
1111 // compute bestLaneOffset
1112 MSVehicle::LaneQ curr, neigh, best;
1113 int bestLaneOffset = 0;
1114 // What do these "dists" mean? Please comment. (Leo) Ad: I now think the following:
1115 // currentDist is the distance that the vehicle can go on its route without having to
1116 // change lanes from the current lane. neighDist as currentDist for the considered target lane (i.e., neigh)
1117 // If this is true I suggest to put this into the docu of wantsChange()
1118 double currentDist = 0;
1119 double neighDist = 0;
1120 int currIdx = 0;
1121 const bool checkOpposite = &neighLane.getEdge() != &myVehicle.getLane()->getEdge();
1122 const MSLane* prebLane = myVehicle.getLane();
1123 if (prebLane->getEdge().isInternal()) {
1124 // internal edges are not kept inside the bestLanes structure
1125 if (isOpposite()) {
1126 prebLane = prebLane->getNormalPredecessorLane();
1127 } else {
1128 prebLane = prebLane->getLinkCont()[0]->getLane();
1129 }
1130 }
1131 // special case: vehicle considers changing to the opposite direction edge
1132 const int prebOffset = laneOffset;
1133 for (int p = 0; p < (int) preb.size(); ++p) {
1134 //if (DEBUG_COND) {
1135 // std::cout << " p=" << p << " prebLane=" << prebLane->getID() << " preb.p=" << preb[p].lane->getID() << "\n";
1136 //}
1137 if (preb[p].lane == prebLane && p + laneOffset >= 0) {
1138 assert(p + prebOffset < (int)preb.size());
1139 curr = preb[p];
1140 neigh = preb[p + prebOffset];
1141 currentDist = curr.length;
1142 neighDist = neigh.length;
1143 bestLaneOffset = curr.bestLaneOffset;
1144 if (bestLaneOffset == 0 && preb[p + prebOffset].bestLaneOffset == 0 && !checkOpposite) {
1145#ifdef DEBUG_WANTS_CHANGE
1146 if (DEBUG_COND) {
1147 std::cout << STEPS2TIME(currentTime)
1148 << " veh=" << myVehicle.getID()
1149 << " bestLaneOffsetOld=" << bestLaneOffset
1150 << " bestLaneOffsetNew=" << laneOffset
1151 << "\n";
1152 }
1153#endif
1154 bestLaneOffset = prebOffset;
1155 }
1156 best = preb[p + bestLaneOffset];
1157 currIdx = p;
1158 break;
1159 }
1160 }
1161 assert(curr.lane != nullptr);
1162 assert(neigh.lane != nullptr);
1163 assert(best.lane != nullptr);
1164 // direction specific constants
1165 const bool right = (laneOffset == -1);
1166 const double posOnLane = getForwardPos();
1167 double driveToNextStop = -std::numeric_limits<double>::max();
1168 if (myVehicle.nextStopDist() < std::numeric_limits<double>::max()
1170 // vehicle can always drive up to stop distance
1171 // @note this information is dynamic and thus not available in updateBestLanes()
1172 // @note: nextStopDist was compute before the vehicle moved
1173 driveToNextStop = myVehicle.nextStopDist();
1174 const double stopPos = posOnLane + myVehicle.nextStopDist() - myVehicle.getLastStepDist();
1175#ifdef DEBUG_WANTS_CHANGE
1176 if (DEBUG_COND) {
1177 std::cout << SIMTIME << std::setprecision(gPrecision) << " veh=" << myVehicle.getID()
1178 << " stopDist=" << myVehicle.nextStopDist()
1179 << " lastDist=" << myVehicle.getLastStepDist()
1180 << " stopPos=" << stopPos
1181 << " currentDist=" << currentDist
1182 << " neighDist=" << neighDist
1183 << "\n";
1184 }
1185#endif
1186 currentDist = MAX2(currentDist, stopPos);
1187 neighDist = MAX2(neighDist, stopPos);
1188 }
1189 const int lca = (right ? LCA_RIGHT : LCA_LEFT);
1190 const int myLca = (right ? LCA_MRIGHT : LCA_MLEFT);
1191 const int lcaCounter = (right ? LCA_LEFT : LCA_RIGHT);
1192 bool changeToBest = (right && bestLaneOffset < 0) || (!right && bestLaneOffset > 0);
1193 // keep information about being a leader/follower
1194 int ret = (myOwnState & 0xffff0000);
1195 int req = 0; // the request to change or stay
1196
1197 ret = slowDownForBlocked(lastBlocked, ret);
1198 if (lastBlocked != firstBlocked) {
1199 ret = slowDownForBlocked(firstBlocked, ret);
1200 }
1201
1202#ifdef DEBUG_WANTS_CHANGE
1203 if (DEBUG_COND) {
1204 std::cout << SIMTIME
1205 << " veh=" << myVehicle.getID()
1206 << " _wantsChange state=" << myOwnState
1207 << " myLCAccelerationAdvices=" << toString(myLCAccelerationAdvices)
1208 << " firstBlocked=" << Named::getIDSecure(firstBlocked)
1209 << " lastBlocked=" << Named::getIDSecure(lastBlocked)
1210 << " leader=" << Named::getIDSecure(leader.first)
1211 << " leaderGap=" << leader.second
1212 << " follower=" << Named::getIDSecure(follower.first)
1213 << " followerGap=" << follower.second
1214 << " neighLead=" << Named::getIDSecure(neighLead.first)
1215 << " neighLeadGap=" << neighLead.second
1216 << " neighFollow=" << Named::getIDSecure(neighFollow.first)
1217 << " neighFollowGap=" << neighFollow.second
1218 << "\n";
1219 }
1220#endif
1221
1222 // we try to estimate the distance which is necessary to get on a lane
1223 // we have to get on in order to keep our route
1224 // we assume we need something that depends on our velocity
1225 // and compare this with the free space on our wished lane
1226 //
1227 // if the free space is somehow(<-?) less than the space we need, we should
1228 // definitely try to get to the desired lane
1229 //
1230 // this rule forces our vehicle to change the lane if a lane changing is necessary soon
1231
1232
1233 // we do not want the lookahead distance to change all the time so we let it decay slowly
1234 // (in contrast, growth is applied instantaneously)
1237 } else {
1238 // memory decay factor for this action step
1239 const double memoryFactor = 1. - (1. - LOOK_AHEAD_SPEED_MEMORY) * myVehicle.getActionStepLengthSecs();
1240 assert(memoryFactor > 0.);
1242 (memoryFactor * myLookAheadSpeed + (1 - memoryFactor) * myVehicle.getSpeed()));
1243 }
1244 double laDist = myLookAheadSpeed * LOOK_FORWARD * myStrategicParam * (right ? 1 : myLookaheadLeft);
1245 laDist += myVehicle.getVehicleType().getLengthWithGap() * 2.;
1246 const bool hasStoppedLeader = leader.first != 0 && leader.first->isStopped() && leader.second < (currentDist - posOnLane);
1247 const bool hasBidiLeader = myVehicle.getLane()->getBidiLane() != nullptr && MSLCHelper::isBidiLeader(leader.first, curr.bestContinuations);
1248 const bool hasBidiNeighLeader = neighLane.getBidiLane() != nullptr && MSLCHelper::isBidiLeader(neighLead.first, neigh.bestContinuations);
1249
1250 if (bestLaneOffset == 0 && hasBidiLeader) {
1251 // getting out of the way is enough to clear the blockage
1252 laDist = 0;
1253 } else if (bestLaneOffset == 0 && hasStoppedLeader) {
1254 // react to a stopped leader on the current lane
1255 // The value of laDist is doubled below for the check whether the lc-maneuver can be taken out
1256 // on the remaining distance (because the vehicle has to change back and forth). Therefore multiply with 0.5.
1257 laDist = 0.5 * (myVehicle.getVehicleType().getLengthWithGap()
1258 + leader.first->getVehicleType().getLengthWithGap()
1259 + leader.second);
1260 } else if (bestLaneOffset == laneOffset && neighLead.first != 0 && (neighLead.first->isStopped() || hasBidiNeighLeader) && neighLead.second < (currentDist - posOnLane)) {
1261 // react to a stopped leader on the target lane (if it is the bestLane)
1262 if (isOpposite()) {
1263 // always allow changing back
1265 + neighLead.first->getVehicleType().getLengthWithGap()
1266 + neighLead.second);
1267 } else if (!hasStoppedLeader &&
1268 ((neighLead.second + myVehicle.getVehicleType().getLengthWithGap() + neighLead.first->getVehicleType().getLengthWithGap()) < (currentDist - posOnLane)
1269 || hasBidiNeighLeader)) {
1270 // do not change to the target lane until passing the stopped vehicle
1271 // (unless the vehicle blocks our intended stopping position, then we have to wait anyway)
1272 changeToBest = false;
1273 }
1274 }
1275 if (myStrategicParam < 0) {
1276 laDist = -1e3; // never perform strategic change
1277 }
1278
1279 // free space that is available for changing
1280 //const double neighSpeed = (neighLead.first != 0 ? neighLead.first->getSpeed() :
1281 // neighFollow.first != 0 ? neighFollow.first->getSpeed() :
1282 // best.lane->getSpeedLimit());
1283 // @note: while this lets vehicles change earlier into the correct direction
1284 // it also makes the vehicles more "selfish" and prevents changes which are necessary to help others
1285
1286
1287
1288 // Next we assign to roundabout edges a larger distance than to normal edges
1289 // in order to decrease sense of lc urgency and induce higher usage of inner roundabout lanes.
1290 const double roundaboutBonus = MSLCHelper::getRoundaboutDistBonus(myVehicle, myRoundaboutBonus, curr, neigh, best);
1291 currentDist += roundaboutBonus;
1292 neighDist += roundaboutBonus;
1293
1294 const double usableDist = MAX2(currentDist - posOnLane - best.occupation * JAM_FACTOR, driveToNextStop);
1295 //- (best.lane->getVehicleNumber() * neighSpeed)); // VARIANT 9 jfSpeed
1296 const double maxJam = MAX2(preb[currIdx + prebOffset].occupation, preb[currIdx].occupation);
1297 const double vMax = myVehicle.getLane()->getVehicleMaxSpeed(&myVehicle);
1298 const double neighVMax = neighLane.getVehicleMaxSpeed(&myVehicle);
1299 // upper bound which will be restricted successively
1300 double thisLaneVSafe = vMax;
1301 const bool checkOverTakeRight = avoidOvertakeRight(neighLead.first, true);
1302
1303 double neighLeftPlace = MAX2(0.0, neighDist - posOnLane - maxJam);
1304 if (neighLead.first != 0 && neighLead.first->isStopped()) {
1305 neighLeftPlace = MIN2(neighLeftPlace, neighLead.second);
1306 }
1307
1308#ifdef DEBUG_WANTS_CHANGE
1309 if (DEBUG_COND) {
1310 std::cout << STEPS2TIME(currentTime)
1311 << " veh=" << myVehicle.getID()
1312 << " laSpeed=" << myLookAheadSpeed
1313 << " laDist=" << laDist
1314 << " currentDist=" << currentDist
1315 << " usableDist=" << usableDist
1316 << " bestLaneOffset=" << bestLaneOffset
1317 << " best.occupation=" << best.occupation
1318 << " best.length=" << best.length
1319 << "\n roundaboutBonus=" << roundaboutBonus
1320 << " maxJam=" << maxJam
1321 << " neighDist=" << neighDist
1322 << " neighLeftPlace=" << neighLeftPlace
1323 << (hasBidiLeader ? " bidiLeader" : "")
1324 << (hasBidiNeighLeader ? " bidiNeighLeader" : "")
1325 << "\n";
1326 }
1327#endif
1328
1329 bool changeLeftToAvoidOvertakeRight = false;
1330 if (changeToBest && bestLaneOffset == curr.bestLaneOffset
1331 && currentDistDisallows(usableDist, bestLaneOffset, laDist)) {
1333 ret = ret | lca | LCA_STRATEGIC | LCA_URGENT;
1334 } else {
1335 // VARIANT_20 (noOvertakeRight)
1336 if (neighLead.first != 0 && checkOverTakeRight && !right) {
1337 // check for slower leader on the left. we should not overtake but
1338 // rather move left ourselves (unless congested)
1339 const MSVehicle* nv = neighLead.first;
1340 double deltaV = 0.;
1341 double vSafe = 0.;
1342 if (canOvertakeRight(nv, neighLead.second, vMax - neighLane.getVehicleMaxSpeed(nv), HELP_OVERTAKE, vSafe, deltaV)) {
1344 vSafe = MAX2(vSafe, nv->getSpeed());
1345 }
1346 thisLaneVSafe = MIN2(thisLaneVSafe, vSafe);
1347 addLCSpeedAdvice(vSafe);
1348 // only generate impulse for overtaking left shortly before braking would be necessary
1349 const double deltaGapFuture = deltaV * 8;
1350 const double vSafeFuture = getCarFollowModel().followSpeed(
1351 &myVehicle, myVehicle.getSpeed(), neighLead.second - deltaGapFuture, nv->getSpeed(), nv->getCarFollowModel().getMaxDecel());
1352 if (vSafeFuture < vSafe) {
1353 const double relativeGain = deltaV / MAX2(vMax,
1355 mySpeedGainProbabilityLeft += (long long int)(myVehicle.getActionStepLengthSecs() * relativeGain * HYST_PRECISION);
1356 changeLeftToAvoidOvertakeRight = true;
1357 }
1358#ifdef DEBUG_WANTS_CHANGE
1359 if (DEBUG_COND) {
1360 std::cout << STEPS2TIME(currentTime)
1361 << " avoid overtaking on the right nv=" << nv->getID()
1362 << " deltaV=" << deltaV
1363 << " nvSpeed=" << nv->getSpeed()
1364 << " speedGainL=" << mySpeedGainProbabilityLeft / HYST_PRECISION
1365 << " speedGainR=" << mySpeedGainProbabilityRight / HYST_PRECISION
1366 << " planned acceleration =" << myLCAccelerationAdvices.back().first
1367 << "\n";
1368 }
1369#endif
1370 }
1371 }
1372 const bool currFreeUntilNeighEnd = leader.first == nullptr || neighDist - posOnLane <= leader.second;
1373 const double overtakeDist = (leader.first == 0 || hasBidiLeader ? -1 :
1374 leader.second + myVehicle.getVehicleType().getLength() + leader.first->getVehicleType().getLengthWithGap());
1375 const double overtakeDist2 = (neighLead.first == 0 || !neighLead.first->isStopped() ? -1 :
1376 neighLead.second + myVehicle.getVehicleType().getLength() + neighLead.first->getVehicleType().getLengthWithGap());
1377 if (leader.first != 0 && (leader.first->isStopped() || hasBidiLeader) && leader.second < REACT_TO_STOPPED_DISTANCE
1378 // current destination leaves enough space to overtake the leader
1379 && MIN2(neighDist, currentDist) - posOnLane > overtakeDist
1380 // maybe do not overtake on the right at high speed
1381 && (!checkOverTakeRight || !right)
1382 && myStrategicParam >= 0
1383 && (neighLead.first == 0 || !neighLead.first->isStopped()
1384 // neighboring stopped vehicle leaves enough space to overtake leader
1385 || neighLead.second > overtakeDist
1386 // if we cannot pass neighLead before reaching leader we must find another free lane
1387 || (overtakeDist2 > leader.second && hasFreeLane(laneOffset, neighLead)))) {
1388 // avoid becoming stuck behind a stopped leader
1389 currentDist = myVehicle.getPositionOnLane() + leader.second;
1390#ifdef DEBUG_WANTS_CHANGE
1391 if (DEBUG_COND) {
1392 std::cout << " veh=" << myVehicle.getID() << " overtake stopped leader=" << leader.first->getID()
1393 << " overtakeDist=" << overtakeDist
1394 << " overtakeDist2=" << overtakeDist
1395 << " hasFreeLane=" << hasFreeLane(laneOffset, neighLead)
1396 << " remaining=" << MIN2(neighDist, currentDist) - posOnLane
1397 << "\n";
1398 }
1399#endif
1400 ret = ret | lca | LCA_STRATEGIC | LCA_URGENT;
1401 } else if (!changeToBest && currentDistDisallows(neighLeftPlace, abs(bestLaneOffset) + 2, laDist) && !hasBidiLeader) {
1402 // the opposite lane-changing direction should be done than the one examined herein
1403 // we'll check whether we assume we could change anyhow and get back in time...
1404 //
1405 // this rule prevents the vehicle from moving in opposite direction of the best lane
1406 // unless the way till the end where the vehicle has to be on the best lane
1407 // is long enough
1408#ifdef DEBUG_WANTS_CHANGE
1409 if (DEBUG_COND) {
1410 std::cout << " veh=" << myVehicle.getID() << " could not change back and forth in time (1) neighLeftPlace=" << neighLeftPlace << "\n";
1411 }
1412#endif
1413 ret = ret | LCA_STAY | LCA_STRATEGIC;
1414 } else if (bestLaneOffset == 0 && (neighLeftPlace * 2. < laDist)) {
1415 // the current lane is the best and a lane-changing would cause a situation
1416 // of which we assume we will not be able to return to the lane we have to be on.
1417 // this rule prevents the vehicle from leaving the current, best lane when it is
1418 // close to this lane's end
1419#ifdef DEBUG_WANTS_CHANGE
1420 if (DEBUG_COND) {
1421 std::cout << " veh=" << myVehicle.getID() << " could not change back and forth in time (2) neighLeftPlace=" << neighLeftPlace << "\n";
1422 }
1423#endif
1424 ret = ret | LCA_STAY | LCA_STRATEGIC;
1425 } else if (bestLaneOffset == 0
1426 && (leader.first == 0 || !leader.first->isStopped())
1427 && !hasBidiLeader
1428 && neigh.bestContinuations.back()->getLinkCont().size() != 0
1429 && roundaboutBonus == 0
1430 && !checkOpposite
1431 && ((myStrategicParam >= 0 && neighDist < TURN_LANE_DIST)
1432 // lane changing cannot possibly help
1433 || (myStrategicParam < 0 && currFreeUntilNeighEnd))
1434 ) {
1435 // VARIANT_21 (stayOnBest)
1436 // we do not want to leave the best lane for a lane which leads elsewhere
1437 // unless our leader is stopped or we are approaching a roundabout
1438#ifdef DEBUG_WANTS_CHANGE
1439 if (DEBUG_COND) {
1440 std::cout << " veh=" << myVehicle.getID() << " does not want to leave the bestLane (neighDist=" << neighDist << ")\n";
1441 }
1442#endif
1443 ret = ret | LCA_STAY | LCA_STRATEGIC;
1444 }
1445 }
1446 // check for overriding TraCI requests
1447#ifdef DEBUG_WANTS_CHANGE
1448 if (DEBUG_COND) {
1449 std::cout << STEPS2TIME(currentTime) << " veh=" << myVehicle.getID() << " ret=" << toString((LaneChangeAction)ret);
1450 }
1451#endif
1452 // store state before canceling
1453 getCanceledState(laneOffset) |= ret | blocked;
1455 if ((ret & lcaCounter) != 0) {
1456 // we are not interested in traci requests for the opposite direction here
1457 ret &= ~(LCA_TRACI | lcaCounter | LCA_URGENT);
1458 }
1459#ifdef DEBUG_WANTS_CHANGE
1460 if (DEBUG_COND) {
1461 std::cout << " retAfterInfluence=" << toString((LaneChangeAction)ret) << "\n";
1462 }
1463#endif
1464
1465 if ((ret & LCA_STAY) != 0) {
1466 // remove TraCI flags because it should not be included in "state-without-traci"
1467 ret = getCanceledState(laneOffset);
1468 return ret;
1469 }
1470 if ((ret & LCA_URGENT) != 0) {
1471 // prepare urgent lane change maneuver
1472 // save the left space
1473 myLeftSpace = currentDist - posOnLane;
1474 if (changeToBest && abs(bestLaneOffset) > 1 && myVehicle.getNumRemainingEdges() > 1) {
1475 // there might be a vehicle which needs to counter-lane-change one lane further and we cannot see it yet
1476 myLeadingBlockerLength = MAX2(getExtraReservation(bestLaneOffset, neighDist - currentDist), myLeadingBlockerLength);
1477#ifdef DEBUG_SAVE_BLOCKER_LENGTH
1478 if (DEBUG_COND) {
1479 std::cout << " reserving space for unseen blockers myLeadingBlockerLength=" << myLeadingBlockerLength << "\n";
1480 }
1481#endif
1482 }
1483
1484 // letting vehicles merge in at the end of the lane in case of counter-lane change, step#1
1485 // if there is a leader and he wants to change to the opposite direction
1486 const bool canContinue = curr.bestContinuations.size() > 1;
1487 bool canReserve = MSLCHelper::updateBlockerLength(myVehicle, neighLead.first, lcaCounter, myLeftSpace - POSITION_EPS, canContinue, myLeadingBlockerLength);
1488 if (firstBlocked != neighLead.first) {
1489 canReserve &= MSLCHelper::updateBlockerLength(myVehicle, firstBlocked, lcaCounter, myLeftSpace - POSITION_EPS, canContinue, myLeadingBlockerLength);
1490 }
1491#ifdef DEBUG_SAVE_BLOCKER_LENGTH
1492 if (DEBUG_COND) {
1493 std::cout << SIMTIME << " canReserve=" << canReserve << " canContinue=" << canContinue << "\n";
1494 }
1495#endif
1496 if (!canReserve && !isOpposite()) {
1497 // we have a low-priority relief connection
1498 // std::cout << SIMTIME << " veh=" << myVehicle.getID() << " cannotReserve for blockers\n";
1499 myDontBrake = canContinue;
1500 }
1501
1502 const int remainingLanes = MAX2(1, abs(bestLaneOffset));
1503 const double urgency = isOpposite() ? OPPOSITE_URGENCY : URGENCY;
1504 const double remainingSeconds = ((ret & LCA_TRACI) == 0 ?
1505 //MAX2(STEPS2TIME(TS), (myLeftSpace-myLeadingBlockerLength) / MAX2(myLookAheadSpeed, NUMERICAL_EPS) / remainingLanes / urgency) :
1506 MAX2(STEPS2TIME(TS), myLeftSpace / MAX2(myLookAheadSpeed, NUMERICAL_EPS) / remainingLanes / urgency) :
1508 if (!hasBidiNeighLeader) {
1509 const double plannedSpeed = informLeader(msgPass, blocked, myLca, neighLead, remainingSeconds);
1510 // NOTE: for the ballistic update case negative speeds may indicate a stop request,
1511 // while informLeader returns -1 in that case. Refs. #2577
1512 if (plannedSpeed >= 0 || (!MSGlobals::gSemiImplicitEulerUpdate && plannedSpeed != -1)) {
1513 // maybe we need to deal with a blocking follower
1514 const bool hasBidiNeighFollower = neighLane.getBidiLane() != nullptr && MSLCHelper::isBidiFollower(&myVehicle, neighFollow.first);
1515 if (!hasBidiNeighFollower) {
1516 informFollower(msgPass, blocked, myLca, neighFollow, remainingSeconds, plannedSpeed);
1517 }
1518 }
1519#ifdef DEBUG_WANTS_CHANGE
1520 if (DEBUG_COND) {
1521 std::cout << STEPS2TIME(currentTime)
1522 << " veh=" << myVehicle.getID()
1523 << " myLeftSpace=" << myLeftSpace
1524 << " remainingSeconds=" << remainingSeconds
1525 << " plannedSpeed=" << plannedSpeed
1526 << "\n";
1527 }
1528#endif
1529 } else {
1530#ifdef DEBUG_WANTS_CHANGE
1531 if (DEBUG_COND) {
1532 std::cout << STEPS2TIME(currentTime)
1533 << " veh=" << myVehicle.getID()
1534 << " myLeftSpace=" << myLeftSpace
1535 << " remainingSeconds=" << remainingSeconds
1536 << " hasBidiNeighLeader\n";
1537 }
1538#endif
1539 }
1540
1541
1542 // remove TraCI flags because it should not be included in "state-without-traci"
1543 ret = getCanceledState(laneOffset);
1544 return ret;
1545 }
1546
1547 // we wish to anticipate future speeds. This is difficult when the leading
1548 // vehicles are still accelerating so we resort to comparing speeds for the near future (1s) in this case
1549 const bool acceleratingLeader = (neighLead.first != 0 && neighLead.first->getAcceleration() > 0)
1550 || (leader.first != 0 && leader.first->getAcceleration() > 0);
1551 double neighLaneVSafe = MIN2(neighVMax, anticipateFollowSpeed(neighLead, neighDist, neighVMax, acceleratingLeader));
1552 thisLaneVSafe = MIN2(thisLaneVSafe, anticipateFollowSpeed(leader, currentDist, vMax, acceleratingLeader));
1553 //std::cout << SIMTIME << " veh=" << myVehicle.getID() << " thisLaneVSafe=" << thisLaneVSafe << " neighLaneVSafe=" << neighLaneVSafe << "\n";
1554
1555
1556 // a high inconvenience prevents cooperative changes and the following things are inconvenient:
1557 // - a desire to change in the opposite direction for speedGain
1558 // - low anticipated speed on the neighboring lane
1559 // - high occupancy on the neighboring lane while in a roundabout
1560
1561 double inconvenience = laneOffset < 0
1564
1565 const double relSpeedDiff = thisLaneVSafe == 0 ? 0 : (thisLaneVSafe - neighLaneVSafe) / MAX2(thisLaneVSafe, neighLaneVSafe);
1566 inconvenience = MAX2(relSpeedDiff, inconvenience);
1567 inconvenience = MIN2(1.0, inconvenience);
1568
1569 const bool speedGainInconvenient = inconvenience > myCooperativeParam;
1570 const bool neighOccupancyInconvenient = neigh.lane->getBruttoOccupancy() > curr.lane->getBruttoOccupancy();
1571#ifdef DEBUG_WANTS_CHANGE
1572 if (DEBUG_COND) {
1573 std::cout << STEPS2TIME(currentTime)
1574 << " veh=" << myVehicle.getID()
1575 << " speedGainL=" << mySpeedGainProbabilityLeft / HYST_PRECISION
1576 << " speedGainR=" << mySpeedGainProbabilityRight / HYST_PRECISION
1577 << " neighSpeedFactor=" << (thisLaneVSafe / neighLaneVSafe - 1)
1578 << " inconvenience=" << inconvenience
1579 << " speedInconv=" << speedGainInconvenient
1580 << " occInconv=" << neighOccupancyInconvenient
1581 << "\n";
1582 }
1583#endif
1584
1585 // VARIANT_15
1586 if (roundaboutBonus > 0) {
1587
1588#ifdef DEBUG_WANTS_CHANGE
1589 if (DEBUG_COND) {
1590 std::cout << STEPS2TIME(currentTime)
1591 << " veh=" << myVehicle.getID()
1592 << " roundaboutBonus=" << roundaboutBonus
1593 << " myLeftSpace=" << myLeftSpace
1594 << "\n";
1595 }
1596#endif
1597 // try to use the inner lanes of a roundabout to increase throughput
1598 // unless we are approaching the exit
1599 if (lca == LCA_LEFT) {
1600 // if inconvenience is not too high, request collaborative change (currently only for ballistic update)
1601 // TODO: test this for euler update! Refs. #2575
1602 if (MSGlobals::gSemiImplicitEulerUpdate || !neighOccupancyInconvenient) {
1603// if(MSGlobals::gSemiImplicitEulerUpdate || !speedGainInconvenient){
1604 req = ret | lca | LCA_COOPERATIVE;
1605 }
1606 } else {
1607 // if inconvenience is not too high, request collaborative change (currently only for ballistic update)
1608 if (MSGlobals::gSemiImplicitEulerUpdate || neighOccupancyInconvenient) {
1609// if(MSGlobals::gSemiImplicitEulerUpdate || speedGainInconvenient){
1610 req = ret | LCA_STAY | LCA_COOPERATIVE;
1611 }
1612 }
1613 if (!cancelRequest(req, laneOffset)) {
1614 return ret | req;
1615 }
1616 }
1617
1618 // let's also regard the case where the vehicle is driving on a highway...
1619 // in this case, we do not want to get to the dead-end of an on-ramp
1620 if (right) {
1621 if (bestLaneOffset == 0 && myVehicle.getLane()->getSpeedLimit() > 80. / 3.6 && myLookAheadSpeed > SUMO_const_haltingSpeed) {
1622#ifdef DEBUG_WANTS_CHANGE
1623 if (DEBUG_COND) {
1624 std::cout << " veh=" << myVehicle.getID() << " does not want to get stranded on the on-ramp of a highway\n";
1625 }
1626#endif
1627 req = ret | LCA_STAY | LCA_STRATEGIC;
1628 if (!cancelRequest(req, laneOffset)) {
1629 return ret | req;
1630 }
1631 }
1632 }
1633 // --------
1634
1635 // -------- make place on current lane if blocking follower
1636 //if (amBlockingFollowerPlusNB()) {
1637 // std::cout << myVehicle.getID() << ", " << currentDistAllows(neighDist, bestLaneOffset, laDist)
1638 // << " neighDist=" << neighDist
1639 // << " currentDist=" << currentDist
1640 // << "\n";
1641 //}
1642
1644 && (!speedGainInconvenient)
1645 && ((myOwnState & myLca) != 0) // VARIANT_6 : counterNoHelp
1646 && (changeToBest || currentDistAllows(neighDist, abs(bestLaneOffset) + 1, laDist))) {
1647
1648 // VARIANT_2 (nbWhenChangingToHelp)
1649#ifdef DEBUG_COOPERATE
1650 if (DEBUG_COND) {
1651 std::cout << STEPS2TIME(currentTime)
1652 << " veh=" << myVehicle.getID()
1653 << " wantsChangeToHelp=" << (right ? "right" : "left")
1654 << " state=" << myOwnState
1655 << (((myOwnState & myLca) == 0) ? " (counter)" : "")
1656 << "\n";
1657 }
1658#endif
1659 req = ret | lca | LCA_COOPERATIVE | LCA_URGENT ;//| LCA_CHANGE_TO_HELP;
1660 if (!cancelRequest(req, laneOffset)) {
1661 if ((blocked & LCA_BLOCKED_BY_LEFT_FOLLOWER) && !right && mySpeedGainProbabilityLeft > (long long int)(mySpeedGainUrgency * HYST_PRECISION)) {
1662 MSVehicle* nv = neighFollow.first;
1663 const bool hasBidiNeighFollower = neighLane.getBidiLane() != nullptr && MSLCHelper::isBidiFollower(&myVehicle, nv);
1664 if (nv != nullptr && !hasBidiNeighFollower) {
1665 const double helpSpeed = MAX2(nv->getCarFollowModel().minNextSpeed(nv->getSpeed(), nv), myVehicle.getSpeed() - 1);
1666 msgPass.informNeighFollower(new Info(helpSpeed, myLca | LCA_AMBLOCKINGFOLLOWER), &myVehicle);
1667 }
1668 }
1669 return ret | req;
1670 }
1671 }
1672
1673 // --------
1674
1675
1678 //if ((blocked & LCA_BLOCKED) != 0) {
1679 // return ret;
1680 //}
1682
1683 // -------- higher speed
1684 //if ((congested(neighLead.first) && neighLead.second < 20) || predInteraction(leader.first)) { //!!!
1685 // return ret;
1686 //}
1687
1688 if (neighLane.getEdge().getPersons().size() > 0) {
1689 // react to pedestrians
1690 adaptSpeedToPedestrians(myVehicle.getLane(), thisLaneVSafe);
1691 adaptSpeedToPedestrians(&neighLane, neighLaneVSafe);
1692 }
1693
1694 const double relativeGain = (neighLaneVSafe - thisLaneVSafe) / MAX2(neighLaneVSafe,
1696
1697#ifdef DEBUG_WANTS_CHANGE
1698 if (DEBUG_COND) {
1699 std::cout << STEPS2TIME(currentTime)
1700 << " veh=" << myVehicle.getID()
1701 << " currentDist=" << currentDist
1702 << " neighDist=" << neighDist
1703 << " thisVSafe=" << thisLaneVSafe
1704 << " neighVSafe=" << neighLaneVSafe
1705 << " relGain=" << toString(relativeGain, 8)
1706 << "\n";
1707 }
1708#endif
1709
1710 if (right) {
1711 // ONLY FOR CHANGING TO THE RIGHT
1712 if (thisLaneVSafe - 5 / 3.6 > neighLaneVSafe) {
1713 // ok, the current lane is faster than the right one...
1715 //myKeepRightProbability /= 2.0;
1716 } else {
1717 // ok, the current lane is not (much) faster than the right one
1718 mySpeedGainProbabilityRight += (long long int)(myVehicle.getActionStepLengthSecs() * relativeGain * HYST_PRECISION);
1719
1720 // honor the obligation to keep right (Rechtsfahrgebot)
1721 const double roadSpeedFactor = vMax / myVehicle.getLane()->getSpeedLimit(); // differse from speedFactor if vMax < speedLimit
1722 double acceptanceTime;
1723 if (myKeepRightAcceptanceTime == -1) {
1724 // legacy behavior: scale acceptance time with current speed and
1725 // use old hard-coded constant
1726 acceptanceTime = 7 * roadSpeedFactor * MAX2(1.0, myVehicle.getSpeed());
1727 } else {
1728 acceptanceTime = myKeepRightAcceptanceTime * roadSpeedFactor;
1729 if (follower.first != nullptr && follower.second < 2 * follower.first->getCarFollowModel().brakeGap(follower.first->getSpeed())) {
1730 // reduce acceptanceTime if the follower vehicle is faster or wants to drive faster
1731 if (follower.first->getSpeed() >= myVehicle.getSpeed()) {
1732 acceptanceTime *= MAX2(1.0, myVehicle.getSpeed()) / MAX2(1.0, follower.first->getSpeed());
1733 const double fRSF = follower.first->getLane()->getVehicleMaxSpeed(follower.first) / follower.first->getLane()->getSpeedLimit();
1734 if (fRSF > roadSpeedFactor) {
1735 acceptanceTime /= fRSF;
1736 }
1737 }
1738 }
1739 }
1740 double fullSpeedGap = MAX2(0., neighDist - myVehicle.getCarFollowModel().brakeGap(vMax));
1741 double fullSpeedDrivingSeconds = MIN2(acceptanceTime, fullSpeedGap / vMax);
1742 if (neighLead.first != 0 && neighLead.first->getSpeed() < vMax) {
1743 fullSpeedGap = MAX2(0., MIN2(fullSpeedGap,
1744 neighLead.second - myVehicle.getCarFollowModel().getSecureGap(&myVehicle, neighLead.first,
1745 vMax, neighLead.first->getSpeed(), neighLead.first->getCarFollowModel().getMaxDecel())));
1746 fullSpeedDrivingSeconds = MIN2(fullSpeedDrivingSeconds, fullSpeedGap / (vMax - neighLead.first->getSpeed()));
1747 }
1748 // stay on the current lane if we cannot overtake a slow leader on the right
1749 if (checkOverTakeRight && leader.first != 0
1750 && leader.first->getLane()->getVehicleMaxSpeed(leader.first) < vMax) {
1751 fullSpeedGap = MIN2(fullSpeedGap, leader.second);
1752 fullSpeedDrivingSeconds = MIN2(fullSpeedDrivingSeconds, fullSpeedGap / (vMax - leader.first->getSpeed()));
1753 }
1754
1755 const double deltaProb = (myChangeProbThresholdRight == std::numeric_limits<long long int>::max()) ? 0 :
1756 ((double)myChangeProbThresholdRight * (fullSpeedDrivingSeconds / acceptanceTime) / KEEP_RIGHT_TIME);
1757 myKeepRightProbability -= (long long int)(myVehicle.getActionStepLengthSecs() * deltaProb);
1758
1759 //std::cout << STEPS2TIME(currentTime)
1760 // << " veh=" << myVehicle.getID()
1761 // << " acceptanceTime=" << acceptanceTime
1762 // << " fullSpeedDrivingSeconds=" << fullSpeedDrivingSeconds
1763 // << " dProb=" << deltaProb
1764 // << " myKeepRightProbability=" << myKeepRightProbability
1765 // << "\n";
1766
1767#ifdef DEBUG_WANTS_CHANGE
1768 if (DEBUG_COND) {
1769 std::cout << STEPS2TIME(currentTime)
1770 << " veh=" << myVehicle.getID()
1771 << " vMax=" << vMax
1772 << " neighDist=" << neighDist
1773 << " brakeGap=" << myVehicle.getCarFollowModel().brakeGap(myVehicle.getSpeed())
1774 << " leaderSpeed=" << (neighLead.first == 0 ? -1 : neighLead.first->getSpeed())
1775 << " secGap=" << (neighLead.first == 0 ? -1 : myVehicle.getCarFollowModel().getSecureGap(&myVehicle, neighLead.first,
1776 myVehicle.getSpeed(), neighLead.first->getSpeed(), neighLead.first->getCarFollowModel().getMaxDecel()))
1777 << " acceptanceTime=" << acceptanceTime
1778 << " fullSpeedGap=" << fullSpeedGap
1779 << " fullSpeedDrivingSeconds=" << fullSpeedDrivingSeconds
1780 << " dProb=" << deltaProb / HYST_PRECISION
1781 << " myKeepRightProbability=" << myKeepRightProbability / HYST_PRECISION
1782 << "\n";
1783 }
1784#endif
1785 if ((long long int)((double)myKeepRightProbability * myKeepRightParam) < -myChangeProbThresholdRight) {
1786 req = ret | lca | LCA_KEEPRIGHT;
1787 if (!cancelRequest(req, laneOffset)) {
1788 return ret | req;
1789 }
1790 }
1791 }
1792
1793#ifdef DEBUG_WANTS_CHANGE
1794 if (DEBUG_COND) {
1795 std::cout << STEPS2TIME(currentTime)
1796 << " veh=" << myVehicle.getID()
1797 << " speed=" << myVehicle.getSpeed()
1798 << " speedGainL=" << mySpeedGainProbabilityLeft / HYST_PRECISION
1799 << " speedGainR=" << mySpeedGainProbabilityRight / HYST_PRECISION
1800 << " thisLaneVSafe=" << thisLaneVSafe
1801 << " neighLaneVSafe=" << neighLaneVSafe
1802 << " relativeGain=" << relativeGain
1803 << " blocked=" << blocked
1804 << "\n";
1805 }
1806#endif
1807
1809 && neighDist / MAX2(.1, myVehicle.getSpeed()) > mySpeedGainRemainTime) { //./MAX2( .1, myVehicle.getSpeed())) { // -.1
1810 req = ret | lca | LCA_SPEEDGAIN;
1812 req |= LCA_URGENT;
1813 }
1814 if (!cancelRequest(req, laneOffset)) {
1815 return ret | req;
1816 }
1817 }
1818 } else {
1819 // ONLY FOR CHANGING TO THE LEFT
1820 if (thisLaneVSafe > neighLaneVSafe) {
1821 // this lane is better
1823 } else if (thisLaneVSafe == neighLaneVSafe) {
1825 } else {
1826 mySpeedGainProbabilityLeft += (long long int)(myVehicle.getActionStepLengthSecs() * relativeGain * HYST_PRECISION);
1827 }
1828 // VARIANT_19 (stayRight)
1829 //if (neighFollow.first != 0) {
1830 // MSVehicle* nv = neighFollow.first;
1831 // const double secGap = nv->getCarFollowModel().getSecureGap(nv, &myVehicle, nv->getSpeed(), myVehicle.getSpeed(), myVehicle.getCarFollowModel().getMaxDecel());
1832 // if (neighFollow.second < secGap * KEEP_RIGHT_HEADWAY) {
1833 // // do not change left if it would inconvenience faster followers
1834 // return ret | LCA_STAY | LCA_SPEEDGAIN;
1835 // }
1836 //}
1837
1838#ifdef DEBUG_WANTS_CHANGE
1839 if (DEBUG_COND) {
1840 std::cout << STEPS2TIME(currentTime)
1841 << " veh=" << myVehicle.getID()
1842 << " speed=" << myVehicle.getSpeed()
1843 << " speedGainL=" << mySpeedGainProbabilityLeft / HYST_PRECISION
1844 << " speedGainR=" << mySpeedGainProbabilityRight / HYST_PRECISION
1845 << " thisLaneVSafe=" << thisLaneVSafe
1846 << " neighLaneVSafe=" << neighLaneVSafe
1847 << " relativeGain=" << relativeGain
1848 << " blocked=" << blocked
1849 << "\n";
1850 }
1851#endif
1852
1854 && (relativeGain > NUMERICAL_EPS || changeLeftToAvoidOvertakeRight)
1855 && neighDist / MAX2(.1, myVehicle.getSpeed()) > mySpeedGainRemainTime) { // .1
1856 req = ret | lca | LCA_SPEEDGAIN;
1858 req |= LCA_URGENT;
1859 }
1860 if (!cancelRequest(req, laneOffset)) {
1861 if ((req & LCA_URGENT) && (blocked & LCA_BLOCKED_BY_LEFT_FOLLOWER)) {
1862 MSVehicle* nv = neighFollow.first;
1863 const bool hasBidiNeighFollower = neighLane.getBidiLane() != nullptr && MSLCHelper::isBidiFollower(&myVehicle, nv);
1864 if (nv != nullptr && !hasBidiNeighFollower) {
1865 const double helpSpeed = MAX2(nv->getCarFollowModel().minNextSpeed(nv->getSpeed(), nv), myVehicle.getSpeed() - 1);
1866 msgPass.informNeighFollower(new Info(helpSpeed, myLca | LCA_AMBLOCKINGFOLLOWER), &myVehicle);
1867 }
1868 }
1869 return ret | req;
1870 }
1871 }
1872 }
1873 // --------
1874 if (changeToBest && bestLaneOffset == curr.bestLaneOffset
1875 && myStrategicParam >= 0
1876 && relativeGain >= 0
1878 // change towards the correct lane, speedwise it does not hurt
1879 req = ret | lca | LCA_STRATEGIC;
1880 if (!cancelRequest(req, laneOffset)) {
1881 return ret | req;
1882 }
1883 }
1884#ifdef DEBUG_WANTS_CHANGE
1885 if (DEBUG_COND) {
1886 std::cout << STEPS2TIME(currentTime)
1887 << " veh=" << myVehicle.getID()
1888 << " speedGainL=" << mySpeedGainProbabilityLeft / HYST_PRECISION
1889 << " speedGainR=" << mySpeedGainProbabilityRight / HYST_PRECISION
1890 << " myKeepRightProbability=" << myKeepRightProbability / HYST_PRECISION
1891 << " thisLaneVSafe=" << thisLaneVSafe
1892 << " neighLaneVSafe=" << neighLaneVSafe
1893 << "\n";
1894 }
1895#endif
1896
1897 return ret;
1898}
1899
1900
1901double
1902MSLCM_LC2013::anticipateFollowSpeed(const std::pair<MSVehicle*, double>& leaderDist, double dist, double vMax, bool acceleratingLeader) {
1903 const MSVehicle* leader = leaderDist.first;
1904 const double gap = leaderDist.second;
1905 double futureSpeed;
1906 if (acceleratingLeader) {
1907 // XXX see #6562
1908 const double maxSpeed1s = (myVehicle.getSpeed() + myVehicle.getCarFollowModel().getMaxAccel()
1910 if (leader == nullptr) {
1911 if (hasBlueLight()) {
1912 // can continue from any lane if necessary
1913 futureSpeed = vMax;
1914 } else {
1915 futureSpeed = getCarFollowModel().followSpeed(&myVehicle, maxSpeed1s, dist, 0, 0);
1916 }
1917 } else {
1918 futureSpeed = getCarFollowModel().followSpeed(&myVehicle, maxSpeed1s, gap, leader->getSpeed(), leader->getCarFollowModel().getMaxDecel());
1919 }
1920 } else {
1921 // onInsertion = true because the vehicle has already moved
1922 if (leader == nullptr) {
1923 if (hasBlueLight()) {
1924 // can continue from any lane if necessary
1925 futureSpeed = vMax;
1926 } else {
1927 futureSpeed = getCarFollowModel().maximumSafeStopSpeed(dist, getCarFollowModel().getMaxDecel(), myVehicle.getSpeed(), true);
1928 }
1929 } else {
1930 futureSpeed = getCarFollowModel().maximumSafeFollowSpeed(gap, myVehicle.getSpeed(), leader->getSpeed(), leader->getCarFollowModel().getMaxDecel(), true);
1931 }
1932 }
1933 futureSpeed = MIN2(vMax, futureSpeed);
1934 if (leader != nullptr && gap > 0 && mySpeedGainLookahead > 0) {
1935 const double futureLeaderSpeed = acceleratingLeader ? leader->getLane()->getVehicleMaxSpeed(leader) : leader->getSpeed();
1936 const double deltaV = vMax - futureLeaderSpeed;
1937 if (deltaV > 0 && gap > 0) {
1938 const double secGap = getCarFollowModel().getSecureGap(&myVehicle, leader, futureSpeed, leader->getSpeed(), getCarFollowModel().getMaxDecel());
1939 const double fullSpeedGap = gap - secGap;
1940 if (fullSpeedGap / deltaV < mySpeedGainLookahead) {
1941 // anticipate future braking by computing the average
1942 // speed over the next few seconds
1943 const double gapClosingTime = MAX2(0.0, fullSpeedGap / deltaV);
1944 const double foreCastTime = mySpeedGainLookahead * 2;
1945 //if (DEBUG_COND) std::cout << SIMTIME << " veh=" << myVehicle.getID() << " leader=" << leader->getID() << " gap=" << gap << " deltaV=" << deltaV << " futureSpeed=" << futureSpeed << " futureLeaderSpeed=" << futureLeaderSpeed;
1946 futureSpeed = MIN2(futureSpeed, (gapClosingTime * futureSpeed + (foreCastTime - gapClosingTime) * futureLeaderSpeed) / foreCastTime);
1947 //if (DEBUG_COND) std::cout << " newFutureSpeed=" << futureSpeed << "\n";
1948 }
1949 }
1950 }
1951 return futureSpeed;
1952}
1953
1954
1955int
1957 // if this vehicle is blocking someone in front, we maybe decelerate to let him in
1958 if (blocked != nullptr) {
1960#ifdef DEBUG_SLOW_DOWN
1961 if (DEBUG_COND) {
1962 std::cout << SIMTIME
1963 << " veh=" << myVehicle.getID()
1964 << " blocked=" << Named::getIDSecure(blocked)
1965 << " gap=" << gap
1966 << "\n";
1967 }
1968#endif
1969 if (gap > POSITION_EPS) {
1970 //const bool blockedWantsUrgentRight = (((*blocked)->getLaneChangeModel().getOwnState() & LCA_RIGHT != 0)
1971 // && ((*blocked)->getLaneChangeModel().getOwnState() & LCA_URGENT != 0));
1972
1974 //|| blockedWantsUrgentRight // VARIANT_10 (helpblockedRight)
1975 ) {
1976 if (blocked->getSpeed() < SUMO_const_haltingSpeed) {
1978 } else {
1979 state |= LCA_AMBACKBLOCKER;
1980 }
1981 addLCSpeedAdvice(getCarFollowModel().followSpeed(
1983 gap - POSITION_EPS, blocked->getSpeed(),
1984 blocked->getCarFollowModel().getMaxDecel()), false);
1985
1986 //(*blocked) = 0; // VARIANT_14 (furtherBlock)
1987#ifdef DEBUG_SLOW_DOWN
1988 if (DEBUG_COND) {
1989 std::cout << SIMTIME
1990 << " veh=" << myVehicle.getID()
1991 << " slowing down for"
1992 << " blocked=" << Named::getIDSecure(blocked)
1993 << " helpSpeed=" << myLCAccelerationAdvices.back().first
1994 << "\n";
1995 }
1996#endif
1997 } /*else if ((*blocked)->getWaitingSeconds() > 30 && gap > myVehicle.getBrakeGap()) {
1998 // experimental else-branch...
1999
2000 state |= LCA_AMBACKBLOCKER;
2001 addLCSpeedAdvice(getCarFollowModel().followSpeed(
2002 &myVehicle, myVehicle.getSpeed(),
2003 (gap - POSITION_EPS), (*blocked)->getSpeed(),
2004 (*blocked)->getCarFollowModel().getMaxDecel()));
2005 } */
2006 }
2007 }
2008 return state;
2009}
2010
2011
2012void
2014 if (lane->hasPedestrians()) {
2015#ifdef DEBUG_WANTS_CHANGE
2016 if (DEBUG_COND) {
2017 std::cout << SIMTIME << " adapt to pedestrians on lane=" << lane->getID() << "\n";
2018 }
2019#endif
2023 if (leader.first != 0) {
2024 const double stopSpeed = myVehicle.getCarFollowModel().stopSpeed(&myVehicle, myVehicle.getSpeed(), leader.second - myVehicle.getVehicleType().getMinGap());
2025 v = MIN2(v, stopSpeed);
2026#ifdef DEBUG_WANTS_CHANGE
2027 if (DEBUG_COND) {
2028 std::cout << SIMTIME << " pedLeader=" << leader.first->getID() << " dist=" << leader.second << " v=" << v << "\n";
2029 }
2030#endif
2031 }
2032 }
2033}
2034
2035
2036double
2037MSLCM_LC2013::computeSpeedLat(double latDist, double& maneuverDist, bool urgent) const {
2038 double result = MSAbstractLaneChangeModel::computeSpeedLat(latDist, maneuverDist, urgent);
2039#ifdef DEBUG_WANTS_CHANGE
2040 if (DEBUG_COND) {
2041 std::cout << SIMTIME << " veh=" << myVehicle.getID() << " myLeftSpace=" << myLeftSpace << " latDist=" << latDist << " maneuverDist=" << maneuverDist << " result=" << result << "\n";
2042 }
2043#endif
2044 if (myLeftSpace > POSITION_EPS || !urgent) {
2046 if (isChangingLanes()) {
2047 speedBound = MAX2(LC_RESOLUTION_SPEED_LAT, speedBound);
2048 }
2049 result = MAX2(-speedBound, MIN2(speedBound, result));
2050 }
2051 return result;
2052}
2053
2054
2055double
2057 return 1 / myAssertive;
2058}
2059
2060double
2062 return myOppositeParam <= 0 ? std::numeric_limits<double>::max() : 1 / myOppositeParam;
2063}
2064
2065bool
2066MSLCM_LC2013::saveBlockerLength(double length, double foeLeftSpace) {
2067 const bool canReserve = MSLCHelper::canSaveBlockerLength(myVehicle, length, myLeftSpace);
2068 if (!isOpposite() && (canReserve || myLeftSpace > foeLeftSpace)) {
2070#ifdef DEBUG_SAVE_BLOCKER_LENGTH
2071 if (DEBUG_COND) {
2072 std::cout << SIMTIME << " saveBlockerLength veh=" << myVehicle.getID() << " canReserve=" << canReserve << " myLeftSpace=" << myLeftSpace << " foeLeftSpace=" << foeLeftSpace << "\n";
2073 }
2074#endif
2075 if (myLeftSpace == 0 && foeLeftSpace < 0) {
2076 // called from opposite overtaking, myLeftSpace must be initialized
2078 }
2079 return true;
2080 } else {
2081 return false;
2082 }
2083}
2084
2085
2086bool
2087MSLCM_LC2013::hasFreeLane(int laneOffset, const std::pair<MSVehicle*, double>& neighLeadStopped) const {
2088 if (neighLeadStopped.first == nullptr) {
2089 return true;
2090 }
2091 int dir = (laneOffset > 0 ? 1 : -1);
2092 const MSLane* neigh = myVehicle.getLane()->getParallelLane(laneOffset);
2093 if (dir > 0 && !neigh->allowsChangingLeft(myVehicle.getVClass())) {
2094 return false;
2095 } else if (dir < 0 && !neigh->allowsChangingRight(myVehicle.getVClass())) {
2096 return false;
2097 }
2098 int nextOffset = laneOffset + dir;
2099 const MSLane* next = myVehicle.getLane()->getParallelLane(nextOffset);
2100 if (next == nullptr || !next->allowsVehicleClass(myVehicle.getVClass())) {
2101 return false;
2102 }
2103 const double overtakeDist = neighLeadStopped.second + neighLeadStopped.first->getVehicleType().getLengthWithGap() + myVehicle.getLength() + POSITION_EPS;
2104 std::pair<MSVehicle* const, double> nextLead = next->getLeader(&myVehicle, myVehicle.getPositionOnLane(), myVehicle.getBestLanesContinuation(next), overtakeDist);
2105 return nextLead.first == nullptr || nextLead.second >= overtakeDist || hasFreeLane(nextOffset, nextLead);
2106}
2107
2108
2109std::string
2110MSLCM_LC2013::getParameter(const std::string& key) const {
2112 return toString(myStrategicParam);
2113 } else if (key == toString(SUMO_ATTR_LCA_COOPERATIVE_PARAM)) {
2115 } else if (key == toString(SUMO_ATTR_LCA_SPEEDGAIN_PARAM)) {
2116 return toString(mySpeedGainParam);
2117 } else if (key == toString(SUMO_ATTR_LCA_KEEPRIGHT_PARAM)) {
2118 return toString(myKeepRightParam);
2119 } else if (key == toString(SUMO_ATTR_LCA_OPPOSITE_PARAM)) {
2120 return toString(myOppositeParam);
2121 } else if (key == toString(SUMO_ATTR_LCA_LOOKAHEADLEFT)) {
2122 return toString(myLookaheadLeft);
2123 } else if (key == toString(SUMO_ATTR_LCA_SPEEDGAINRIGHT)) {
2124 return toString(mySpeedGainRight);
2125 } else if (key == toString(SUMO_ATTR_LCA_ASSERTIVE)) {
2126 return toString(myAssertive);
2127 } else if (key == toString(SUMO_ATTR_LCA_OVERTAKE_RIGHT)) {
2129 } else if (key == toString(SUMO_ATTR_LCA_SIGMA)) {
2130 return toString(mySigma);
2135 } else if (key == toString(SUMO_ATTR_LCA_STRATEGIC_LOOKAHEAD)) {
2137 } else if (key == toString(SUMO_ATTR_LCA_SPEEDGAIN_LOOKAHEAD)) {
2139 } else if (key == toString(SUMO_ATTR_LCA_SPEEDGAIN_REMAIN_TIME)) {
2143 } else if (key == toString(SUMO_ATTR_LCA_COOPERATIVE_SPEED)) {
2145 } else if (key == toString(SUMO_ATTR_LCA_MAXSPEEDLATSTANDING)) {
2147 } else if (key == toString(SUMO_ATTR_LCA_MAXSPEEDLATFACTOR)) {
2149 } else if (key == toString(SUMO_ATTR_LCA_MAXDISTLATSTANDING)) {
2151 // access to internal state for debugging in sumo-gui (not documented since it may change at any time)
2152 } else if (key == "speedGainProbabilityRight") {
2154 } else if (key == "speedGainProbabilityLeft") {
2156 } else if (key == "keepRightProbability") {
2158 } else if (key == "lookAheadSpeed") {
2159 return toString(myLookAheadSpeed);
2160 // motivation relative to threshold
2161 } else if (key == "speedGainRP") {
2163 } else if (key == "speedGainLP") {
2165 } else if (key == "keepRightP") {
2167 }
2168 throw InvalidArgument("Parameter '" + key + "' is not supported for laneChangeModel of type '" + toString(myModel) + "'");
2169}
2170
2171
2172void
2173MSLCM_LC2013::setParameter(const std::string& key, const std::string& value) {
2174 double doubleValue;
2175 try {
2176 doubleValue = StringUtils::toDouble(value);
2177 } catch (NumberFormatException&) {
2178 throw InvalidArgument("Setting parameter '" + key + "' requires a number for laneChangeModel of type '" + toString(myModel) + "'");
2179 }
2181 myStrategicParam = doubleValue;
2182 } else if (key == toString(SUMO_ATTR_LCA_COOPERATIVE_PARAM)) {
2183 myCooperativeParam = doubleValue;
2184 } else if (key == toString(SUMO_ATTR_LCA_SPEEDGAIN_PARAM)) {
2185 mySpeedGainParam = doubleValue;
2186 } else if (key == toString(SUMO_ATTR_LCA_KEEPRIGHT_PARAM)) {
2187 myKeepRightParam = doubleValue;
2188 } else if (key == toString(SUMO_ATTR_LCA_OPPOSITE_PARAM)) {
2189 myOppositeParam = doubleValue;
2190 } else if (key == toString(SUMO_ATTR_LCA_LOOKAHEADLEFT)) {
2191 myLookaheadLeft = doubleValue;
2192 } else if (key == toString(SUMO_ATTR_LCA_SPEEDGAINRIGHT)) {
2193 mySpeedGainRight = doubleValue;
2194 } else if (key == toString(SUMO_ATTR_LCA_ASSERTIVE)) {
2195 myAssertive = doubleValue;
2196 } else if (key == toString(SUMO_ATTR_LCA_OVERTAKE_RIGHT)) {
2197 myOvertakeRightParam = doubleValue;
2198 } else if (key == toString(SUMO_ATTR_LCA_SIGMA)) {
2199 mySigma = doubleValue;
2201 myKeepRightAcceptanceTime = doubleValue;
2203 myOvertakeDeltaSpeedFactor = doubleValue;
2204 } else if (key == toString(SUMO_ATTR_LCA_STRATEGIC_LOOKAHEAD)) {
2205 myStrategicLookahead = doubleValue;
2206 } else if (key == toString(SUMO_ATTR_LCA_SPEEDGAIN_LOOKAHEAD)) {
2207 mySpeedGainLookahead = doubleValue;
2208 } else if (key == toString(SUMO_ATTR_LCA_SPEEDGAIN_REMAIN_TIME)) {
2209 mySpeedGainRemainTime = doubleValue;
2211 myRoundaboutBonus = doubleValue;
2212 } else if (key == toString(SUMO_ATTR_LCA_COOPERATIVE_SPEED)) {
2213 myCooperativeSpeed = doubleValue;
2214 } else if (key == toString(SUMO_ATTR_LCA_MAXSPEEDLATSTANDING)) {
2215 myMaxSpeedLatStanding = doubleValue;
2216 } else if (key == toString(SUMO_ATTR_LCA_MAXSPEEDLATFACTOR)) {
2217 myMaxSpeedLatFactor = doubleValue;
2218 } else if (key == toString(SUMO_ATTR_LCA_MAXDISTLATSTANDING)) {
2219 myMaxDistLatStanding = doubleValue;
2220 // access to internal state
2221 } else if (key == "speedGainProbabilityRight") {
2222 mySpeedGainProbabilityRight = (long long int)(doubleValue * HYST_PRECISION);
2223 } else if (key == "speedGainProbabilityLeft") {
2224 mySpeedGainProbabilityLeft = (long long int)(doubleValue * HYST_PRECISION);
2225 } else if (key == "keepRightProbability") {
2226 myKeepRightProbability = (long long int)(-doubleValue * HYST_PRECISION);
2227 } else if (key == "lookAheadSpeed") {
2228 myLookAheadSpeed = doubleValue;
2229 } else {
2230 throw InvalidArgument("Setting parameter '" + key + "' is not supported for laneChangeModel of type '" + toString(myModel) + "'");
2231 }
2233}
2234
2235
2236void
2239 std::vector<long long int> lcState;
2240 lcState.push_back(mySpeedGainProbabilityLeft);
2241 lcState.push_back(mySpeedGainProbabilityRight);
2242 lcState.push_back(myKeepRightProbability);
2243 lcState.push_back((long long int)(myLookAheadSpeed * HYST_PRECISION));
2244 lcState.push_back(myDontBrake);
2245 out.writeAttr(SUMO_ATTR_LCSTATE2, lcState);
2246}
2247
2248
2249void
2252 if (attrs.hasAttribute(SUMO_ATTR_LCSTATE2)) {
2253 std::istringstream bis(attrs.getString(SUMO_ATTR_LCSTATE2));
2257 long long laSpeed;
2258 bis >> laSpeed;
2259 myLookAheadSpeed = (double)laSpeed / HYST_PRECISION;
2260 bis >> myDontBrake;
2261 }
2262}
2263
2264
2265
2266/****************************************************************************/
long long int SUMOTime
Definition GUI.h:36
#define JAM_FACTOR
#define HELP_DECEL_FACTOR
#define LOOK_AHEAD_MIN_SPEED
#define LCA_RIGHT_IMPATIENCE
#define LOOK_FORWARD
#define HELP_OVERTAKE
#define REACT_TO_STOPPED_DISTANCE
#define KEEP_RIGHT_TIME
#define RELGAIN_NORMALIZATION_MIN_SPEED
#define CUT_IN_LEFT_SPEED_THRESHOLD
#define MAX_ONRAMP_LENGTH
#define OPPOSITE_URGENCY
#define MIN_FALLBEHIND
#define HYST_PRECISION
#define URGENCY
#define LOOK_AHEAD_SPEED_MEMORY
#define BLOCKER_IS_BLOCKED_TIME_THRESHOLD
#define TURN_LANE_DIST
#define LC_RESOLUTION_SPEED_LAT
#define INVALID_SPEED
std::pair< const MSPerson *, double > PersonDist
Definition MSPModel.h:41
#define STEPS2TIME(x)
Definition SUMOTime.h:58
#define SPEED2DIST(x)
Definition SUMOTime.h:48
#define ACCEL2SPEED(x)
Definition SUMOTime.h:54
#define TS
Definition SUMOTime.h:45
#define SIMTIME
Definition SUMOTime.h:65
#define DIST2SPEED(x)
Definition SUMOTime.h:50
#define SPEED2ACCEL(x)
Definition SUMOTime.h:56
LaneChangeAction
The state of a vehicle's lane-change behavior.
@ LCA_KEEPRIGHT
The action is due to the default of keeping right "Rechtsfahrgebot".
@ LCA_BLOCKED
blocked in all directions
@ LCA_URGENT
The action is urgent (to be defined by lc-model)
@ LCA_STAY
Needs to stay on the current lane.
@ LCA_BLOCKED_BY_LEADER
blocked by leader
@ LCA_AMBACKBLOCKER
@ LCA_BLOCKED_BY_LEFT_FOLLOWER
The vehicle is blocked by left follower.
@ LCA_AMBLOCKINGLEADER
@ LCA_AMBLOCKINGFOLLOWER_DONTBRAKE
@ LCA_COOPERATIVE
The action is done to help someone else.
@ LCA_LEFT
Wants go to the left.
@ LCA_STRATEGIC
The action is needed to follow the route (navigational lc)
@ LCA_AMBACKBLOCKER_STANDING
@ LCA_TRACI
The action is due to a TraCI request.
@ LCA_SPEEDGAIN
The action is due to the wish to be faster (tactical lc)
@ LCA_WANTS_LANECHANGE
lane can change
@ LCA_RIGHT
Wants go to the right.
@ LCA_BLOCKED_BY_FOLLOWER
blocker by follower
@ LCA_AMBLOCKINGFOLLOWER
@ SUMO_ATTR_LCA_COOPERATIVE_SPEED
@ SUMO_ATTR_LCSTATE2
@ SUMO_ATTR_LCA_ASSERTIVE
@ SUMO_ATTR_LCA_LOOKAHEADLEFT
@ SUMO_ATTR_LCA_SPEEDGAIN_PARAM
@ SUMO_ATTR_LCA_MAXDISTLATSTANDING
@ SUMO_ATTR_LCA_COOPERATIVE_ROUNDABOUT
@ SUMO_ATTR_LCA_SPEEDGAIN_LOOKAHEAD
@ SUMO_ATTR_LCA_MAXSPEEDLATFACTOR
@ SUMO_ATTR_LCA_MAXSPEEDLATSTANDING
@ SUMO_ATTR_LCA_KEEPRIGHT_PARAM
@ SUMO_ATTR_LCA_STRATEGIC_LOOKAHEAD
@ SUMO_ATTR_LCA_COOPERATIVE_PARAM
@ SUMO_ATTR_LCA_OPPOSITE_PARAM
@ SUMO_ATTR_LCA_SPEEDGAIN_REMAIN_TIME
@ SUMO_ATTR_LCA_OVERTAKE_DELTASPEED_FACTOR
@ SUMO_ATTR_LCA_SIGMA
@ SUMO_ATTR_LCA_OVERTAKE_RIGHT
@ SUMO_ATTR_LCA_STRATEGIC_PARAM
@ SUMO_ATTR_LCA_KEEPRIGHT_ACCEPTANCE_TIME
@ SUMO_ATTR_LCA_EXPERIMENTAL1
@ SUMO_ATTR_LCA_SPEEDGAIN_URGENCY
@ SUMO_ATTR_LCA_SPEEDGAINRIGHT
int gPrecision
the precision for floating point outputs
Definition StdDefs.cpp:27
T MIN2(T a, T b)
Definition StdDefs.h:80
const double SUMO_const_haltingSpeed
the speed threshold at which vehicles are considered as halting
Definition StdDefs.h:62
T MAX2(T a, T b)
Definition StdDefs.h:86
T MAX3(T a, T b, T c)
Definition StdDefs.h:100
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
Definition ToString.h:49
A class responsible for exchanging messages between cars involved in lane-change interaction.
void * informNeighFollower(void *info, MSVehicle *sender)
Informs the follower on the desired lane.
void * informNeighLeader(void *info, MSVehicle *sender)
Informs the leader on the desired lane.
Interface for lane-change models.
double getForwardPos() const
get vehicle position relative to the forward direction lane
virtual double getExtraReservation(int bestLaneOffset, double neighExtraDist=0) const
virtual double computeSpeedLat(double latDist, double &maneuverDist, bool urgent) const
decides the next lateral speed depending on the remaining lane change distance to be covered and upda...
int myOwnState
The current state of the vehicle.
virtual void saveState(OutputDevice &out) const
Save the state of the laneChangeModel.
bool canOvertakeRight(const MSVehicle *const nv, const double dist, const double maxSpeedDiff, const double helpOvertakeSpeed, double &vSafe, double &deltaV) const
void addLCSpeedAdvice(const double vSafe, bool ownAdvice=true)
Takes a vSafe (speed advice for speed in the next simulation step), converts it into an acceleration ...
const LaneChangeModel myModel
the type of this model
bool cancelRequest(int state, int laneOffset)
whether the influencer cancels the given request
std::vector< std::pair< double, bool > > myLCAccelerationAdvices
virtual bool avoidOvertakeRight(const MSVehicle *const neighLeader, const bool allowProb=false) const
void setSpeedLat(double speedLat)
set the lateral speed and update lateral acceleraton
const MSCFModel & getCarFollowModel() const
The vehicle's car following model.
virtual void loadState(const SUMOSAXAttributes &attrs)
Loads the state of the laneChangeModel from the given attributes.
MSVehicle & myVehicle
The vehicle this lane-changer belongs to.
bool isChangingLanes() const
return true if the vehicle currently performs a lane change maneuver
double getImpatience() const
Returns this vehicles impatience.
int getNumRemainingEdges() const
return the number of edges remaining in the route (include the current)
double getLength() const
Returns the vehicle's length.
double getWaitingSeconds() const
Returns the number of seconds waited (speed was lesser than 0.1m/s)
const MSStop & getNextStop() const
SUMOVehicleClass getVClass() const
Returns the vehicle's access class.
const MSVehicleType & getVehicleType() const
Returns the vehicle's type definition.
bool isStopped() const
Returns whether the vehicle is at a stop.
The car-following model abstraction.
Definition MSCFModel.h:57
static double gapExtrapolation(const double duration, const double currentGap, double v1, double v2, double a1=0, double a2=0, const double maxV1=std::numeric_limits< double >::max(), const double maxV2=std::numeric_limits< double >::max())
return the resulting gap if, starting with gap currentGap, two vehicles continue with constant accele...
virtual double minNextSpeedEmergency(double speed, const MSVehicle *const veh=0) const
Returns the minimum speed after emergency braking, given the current speed (depends on the numerical ...
virtual double minNextSpeed(double speed, const MSVehicle *const veh=0) const
Returns the minimum speed given the current speed (depends on the numerical update scheme and its ste...
double maximumSafeFollowSpeed(double gap, double egoSpeed, double predSpeed, double predMaxDecel, bool onInsertion=false) const
Returns the maximum safe velocity for following the given leader.
@ LANE_CHANGE
the return value is used for lane change calculations
Definition MSCFModel.h:87
virtual double getSecureGap(const MSVehicle *const veh, const MSVehicle *const, const double speed, const double leaderSpeed, const double leaderMaxDecel) const
Returns the minimum gap to reserve if the leader is braking at maximum (>=0)
double getMaxAccel() const
Get the vehicle type's maximum acceleration [m/s^2].
Definition MSCFModel.h:261
double brakeGap(const double speed) const
Returns the distance the vehicle needs to halt including driver's reaction time tau (i....
Definition MSCFModel.h:408
double maximumSafeStopSpeed(double gap, double decel, double currentSpeed, bool onInsertion=false, double headway=-1, bool relaxEmergency=true) const
Returns the maximum next velocity for stopping within gap.
double getMaxDecel() const
Get the vehicle type's maximal comfortable deceleration [m/s^2].
Definition MSCFModel.h:269
virtual double followSpeed(const MSVehicle *const veh, double speed, double gap2pred, double predSpeed, double predMaxDecel, const MSVehicle *const pred=0, const CalcReason usage=CalcReason::CURRENT) const =0
Computes the vehicle's follow speed (no dawdling)
double stopSpeed(const MSVehicle *const veh, const double speed, double gap, const CalcReason usage=CalcReason::CURRENT) const
Computes the vehicle's safe speed for approaching a non-moving obstacle (no dawdling)
Definition MSCFModel.h:173
const std::set< MSTransportable *, ComparatorNumericalIdLess > & getPersons() const
Returns this edge's persons set.
Definition MSEdge.h:204
bool hasLaneChanger() const
Definition MSEdge.h:749
bool isRoundabout() const
Definition MSEdge.h:732
bool isInternal() const
return whether this edge is an internal edge
Definition MSEdge.h:269
static bool gSemiImplicitEulerUpdate
Definition MSGlobals.h:53
static bool isBidiFollower(const MSVehicle *ego, const MSVehicle *follower)
static bool canSaveBlockerLength(const MSVehicle &veh, double requested, double leftSpace)
static double getSpeedPreservingSecureGap(const MSVehicle &leader, const MSVehicle &follower, double currentGap, double leaderPlannedSpeed)
static double getRoundaboutDistBonus(const MSVehicle &veh, double bonusParam, const MSVehicle::LaneQ &curr, const MSVehicle::LaneQ &neigh, const MSVehicle::LaneQ &best)
static bool isBidiLeader(const MSVehicle *leader, const std::vector< MSLane * > &cont)
static bool updateBlockerLength(const MSVehicle &veh, MSVehicle *blocker, int lcaCounter, double leftSpace, bool reliefConnection, double &leadingBlockerLength)
static bool divergentRoute(const MSVehicle &v1, const MSVehicle &v2)
return whether the vehicles are on the same junction but on divergent paths
bool currentDistAllows(double dist, int laneOffset, double lookForwardDist)
int wantsChange(int laneOffset, MSAbstractLaneChangeModel::MSLCMessager &msgPass, int blocked, const std::pair< MSVehicle *, double > &leader, const std::pair< MSVehicle *, double > &follower, const std::pair< MSVehicle *, double > &neighLead, const std::pair< MSVehicle *, double > &neighFollow, const MSLane &neighLane, const std::vector< MSVehicle::LaneQ > &preb, MSVehicle **lastBlocked, MSVehicle **firstBlocked) override
Called to examine whether the vehicle wants to change using the given laneOffset. This method gets th...
void informFollower(MSAbstractLaneChangeModel::MSLCMessager &msgPass, int blocked, int dir, const std::pair< MSVehicle *, double > &neighFollow, double remainingSeconds, double plannedSpeed)
decide whether we will try cut in before the follower or allow to be overtaken
long long int myKeepRightProbability
double computeSpeedLat(double latDist, double &maneuverDist, bool urgent) const override
decides the next lateral speed (for continuous lane changing)
double myOvertakeDeltaSpeedFactor
double myLookAheadSpeed
bool debugVehicle() const override
whether the current vehicles shall be debugged
double myStrategicParam
long long int mySpeedGainProbabilityRight
double myRoundaboutBonus
double mySpeedGainLookahead
const double myExperimentalParam1
double patchSpeed(const double min, const double wanted, const double max, const MSCFModel &cfModel) override
Called to adapt the speed in order to allow a lane change. It uses information on LC-related desired ...
void initDerivedParameters()
init cached parameters derived directly from model parameters
double myCooperativeParam
MSLCM_LC2013(MSVehicle &v)
double anticipateFollowSpeed(const std::pair< MSVehicle *, double > &leaderDist, double dist, double vMax, bool acceleratingLeader)
anticipate future follow speed for the given leader
std::string getParameter(const std::string &key) const override
try to retrieve the given parameter from this device. Throw exception for unsupported key
void setParameter(const std::string &key, const std::string &value) override
try to set the given parameter for this laneChangeModel. Throw exception for unsupported key
bool hasFreeLane(int laneOffset, const std::pair< MSVehicle *, double > &neighLeadStopped) const
whether there is a lane beyond laneOffset that can be used to overtake the stopped leader on the neig...
double myCooperativeSpeed
double informLeader(MSAbstractLaneChangeModel::MSLCMessager &msgPass, int blocked, int dir, const std::pair< MSVehicle *, double > &neighLead, double remainingSeconds)
double _patchSpeed(double min, const double wanted, double max, const MSCFModel &cfModel)
double mySpeedGainParam
double myLookaheadLeft
double myLeadingBlockerLength
int _wantsChange(int laneOffset, MSAbstractLaneChangeModel::MSLCMessager &msgPass, int blocked, const std::pair< MSVehicle *, double > &leader, const std::pair< MSVehicle *, double > &follower, const std::pair< MSVehicle *, double > &neighLead, const std::pair< MSVehicle *, double > &neighFollow, const MSLane &neighLane, const std::vector< MSVehicle::LaneQ > &preb, MSVehicle *lastBlocked, MSVehicle *firstBlocked)
helper function for doing the actual work
std::pair< double, int > Info
information regarding save velocity (unused) and state flags of the ego vehicle
void prepareStep() override
double getSafetyFactor() const override
return factor for modifying the safety constraints of the car-following model
double myLeftSpace
double myOppositeParam
bool amBlockingFollowerPlusNB()
double myKeepRightParam
bool currentDistDisallows(double dist, int laneOffset, double lookForwardDist)
void adaptSpeedToPedestrians(const MSLane *lane, double &v)
react to pedestrians on the given lane
virtual void saveState(OutputDevice &out) const override
Save the state of the laneChangeModel.
virtual ~MSLCM_LC2013()
long long int myChangeProbThresholdRight
double getOppositeSafetyFactor() const override
return factor for modifying the safety constraints for opposite-diretction overtaking of the car-foll...
long long int mySpeedGainProbabilityLeft
a value for tracking the probability that a change to that side is beneficial
void resetState() override
double mySpeedGainRight
double myKeepRightAcceptanceTime
double mySpeedGainUrgency
int slowDownForBlocked(MSVehicle *blocked, int state)
compute useful slowdowns for blocked vehicles
bool saveBlockerLength(double length, double foeLeftSpace) override
reserve space at the end of the lane to avoid dead locks
void changed() override
double mySpeedGainRemainTime
void * inform(void *info, MSVehicle *sender) override
long long int myChangeProbThresholdLeft
virtual void loadState(const SUMOSAXAttributes &attrs) override
Loads the state of the laneChangeModel from the given attributes.
static double overtakeDistance(const MSVehicle *follower, const MSVehicle *leader, const double gap, double followerSpeed=INVALID_SPEED, double leaderSpeed=INVALID_SPEED)
Representation of a lane in the micro simulation.
Definition MSLane.h:84
std::pair< const MSPerson *, double > nextBlocking(double minPos, double minRight, double maxLeft, double stopTime=0, bool bidi=false) const
This is just a wrapper around MSPModel::nextBlocking. You should always check using hasPedestrians be...
Definition MSLane.cpp:4610
MSLane * getParallelLane(int offset, bool includeOpposite=true) const
Returns the lane with the given offset parallel to this one or 0 if it does not exist.
Definition MSLane.cpp:2887
bool isAccelLane() const
return whether this lane is an acceleration lane
Definition MSLane.h:544
double getSpeedLimit() const
Returns the lane's maximum allowed speed.
Definition MSLane.h:603
double getLength() const
Returns the lane's length.
Definition MSLane.h:617
bool allowsChangingLeft(SUMOVehicleClass vclass) const
Returns whether the given vehicle class may change left from this lane.
Definition MSLane.h:948
bool allowsVehicleClass(SUMOVehicleClass vclass) const
Definition MSLane.h:941
double getVehicleMaxSpeed(const SUMOTrafficObject *const veh) const
Returns the lane's maximum speed, given a vehicle's speed limit adaptation.
Definition MSLane.h:575
bool hasPedestrians() const
whether the lane has pedestrians on it
Definition MSLane.cpp:4603
int getIndex() const
Returns the lane's index.
Definition MSLane.h:653
double getBruttoOccupancy() const
Returns the brutto (including minGaps) occupancy of this lane during the last step.
Definition MSLane.cpp:3433
bool isNormal() const
Definition MSLane.cpp:2657
std::pair< MSVehicle *const, double > getLeader(const MSVehicle *veh, const double vehPos, const std::vector< MSLane * > &bestLaneConts, double dist=-1, bool checkTmpVehicles=false) const
Returns the immediate leader of veh and the distance to veh starting on this lane.
Definition MSLane.cpp:2956
MSLane * getBidiLane() const
retrieve bidirectional lane or nullptr
Definition MSLane.cpp:4715
MSEdge & getEdge() const
Returns the lane's edge.
Definition MSLane.h:775
const MSLane * getNormalPredecessorLane() const
get normal lane leading to this internal lane, for normal lanes, the lane itself is returned
Definition MSLane.cpp:3278
const std::vector< MSLink * > & getLinkCont() const
returns the container with all links !!!
Definition MSLane.h:735
static MSNet * getInstance()
Returns the pointer to the unique instance of MSNet (singleton).
Definition MSNet.cpp:199
SUMOTime getCurrentTimeStep() const
Returns the current simulation step.
Definition MSNet.h:334
const MSLane * lane
The lane to stop at (microsim only)
Definition MSStop.h:50
double changeRequestRemainingSeconds(const SUMOTime currentTime) const
Return the remaining number of seconds of the current laneTimeLine assuming one exists.
Representation of a vehicle in the micro simulation.
Definition MSVehicle.h:77
MSAbstractLaneChangeModel & getLaneChangeModel()
double getActionStepLengthSecs() const
Returns the vehicle's action step length in secs, i.e. the interval between two action points.
Definition MSVehicle.h:533
int influenceChangeDecision(int state)
allow TraCI to influence a lane change decision
double getMaxSpeedOnLane() const
Returns the maximal speed for the vehicle on its current lane (including speed factor and deviation,...
double nextStopDist() const
return the distance to the next stop or doubleMax if there is none.
Definition MSVehicle.h:1038
double getAcceleration() const
Returns the vehicle's acceleration in m/s (this is computed as the last step's mean acceleration in c...
Definition MSVehicle.h:514
const std::vector< MSLane * > & getBestLanesContinuation() const
Returns the best sequence of lanes to continue the route starting at myLane.
int getBestLaneOffset() const
const MSEdge * getCurrentEdge() const
Returns the edge the vehicle is currently at (possibly an internal edge or nullptr)
const MSLane * getLane() const
Returns the lane the vehicle is on.
Definition MSVehicle.h:581
double getLastStepDist() const
Get the distance the vehicle covered in the previous timestep.
Definition MSVehicle.h:381
Influencer & getInfluencer()
double getRightSideOnLane() const
Get the lateral position of the vehicles right side on the lane:
double getLateralPositionOnLane() const
Get the vehicle's lateral position on the lane.
Definition MSVehicle.h:413
double getSpeed() const
Returns the vehicle's current speed.
Definition MSVehicle.h:490
const std::vector< LaneQ > & getBestLanes() const
Returns the description of best lanes to use in order to continue the route.
const MSCFModel & getCarFollowModel() const
Returns the vehicle's car following model definition.
Definition MSVehicle.h:969
double getPositionOnLane() const
Get the vehicle's position along the lane.
Definition MSVehicle.h:374
double getLateralOverlap() const
return the amount by which the vehicle extends laterally outside it's primary lane
void setLateralPositionOnLane(double posLat)
Definition MSVehicle.h:417
double getLengthWithGap() const
Get vehicle's length including the minimum gap [m].
double getWidth() const
Get the width which vehicles of this class shall have when being drawn.
double getMinGap() const
Get the free space in front of vehicles of this class.
double getMaxSpeedLat() const
Get vehicle's maximum lateral speed [m/s].
double getLength() const
Get vehicle's length [m].
static std::string getIDSecure(const T *obj, const std::string &fallBack="NULL")
get an identifier for Named-like object which may be Null
Definition Named.h:67
const std::string & getID() const
Returns the id.
Definition Named.h:74
void step(double dt)
evolve for a time step of length dt.
Static storage of an output device and its base (abstract) implementation.
OutputDevice & writeAttr(const ATTR_TYPE &attr, const T &val, const bool isNull=false)
writes a named attribute
Encapsulated SAX-Attributes.
virtual std::string getString(int id, bool *isPresent=nullptr) const =0
Returns the string-value of the named (by its enum-value) attribute.
virtual bool hasAttribute(int id) const =0
Returns the information whether the named (by its enum-value) attribute is within the current list.
static double toDouble(const std::string &sData)
converts a string into the double value described by it by calling the char-type converter
#define UNUSED_PARAMETER(x)
#define DEBUG_COND
A structure representing the best lanes for continuing the current route starting at 'lane'.
Definition MSVehicle.h:857
double length
The overall length which may be driven when using this lane without a lane change.
Definition MSVehicle.h:861
std::vector< MSLane * > bestContinuations
Definition MSVehicle.h:877
MSLane * lane
The described lane.
Definition MSVehicle.h:859
int bestLaneOffset
The (signed) number of lanes to be crossed to get to the lane which allows to continue the drive.
Definition MSVehicle.h:869
double occupation
The overall vehicle sum on consecutive lanes which can be passed without a lane change.
Definition MSVehicle.h:865