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#endif
676
677 // decide whether we will request help to cut in before the follower or allow to be overtaken
678 // first check whether the neighbor is even willing to help
680 // ego vehicle has not been waiting long enough to be eligible for unconditional help
682 // neighhbor not willing to help because ego is much slower
683#ifdef DEBUG_INFORMER
684 if (DEBUG_COND) {
685 std::cout << "\n nv=" << nv->getID() << " not willing to help because ego is much slower\n";
686 }
687#endif
688 return;
689 }
690 const double nvLaneMax = nv->getLane()->getVehicleMaxSpeed(nv);
691 if (nv->isSelected()) {
692 std::cout << SIMTIME << " ego=" << myVehicle.getID() << " rel=" << nv->getSpeed() / nvLaneMax << " min=" << nv->getLaneChangeModel().getCooperativeMinSpeed() << "\n";
693 }
694 if (nv->getSpeed() / nvLaneMax < nv->getLaneChangeModel().getCooperativeMinSpeed()) {
695 // neighbor not willing to help because it is already to slow and does not want to disturb the flow
696#ifdef DEBUG_INFORMER
697 if (DEBUG_COND) {
698 std::cout << "\n nv=" << nv->getID() << " not willing to help because it is already too slow\n";
699 }
700#endif
701 return;
702 }
703 }
704
705 if ((blocked & LCA_BLOCKED_BY_FOLLOWER) != 0 && nv != nullptr) {
707 //std::cout << SIMTIME << " ego=" << myVehicle.getID() << " ignoresDivergentBlockingFollower=" << nv->getID() << "\n";
708 return;
709 }
710#ifdef DEBUG_INFORMER
711 if (DEBUG_COND) {
712 std::cout << " blocked by follower nv=" << nv->getID() << " nvSpeed=" << nv->getSpeed() << " needGap="
713 << nv->getCarFollowModel().getSecureGap(nv, &myVehicle, nv->getSpeed(), myVehicle.getSpeed(), myVehicle.getCarFollowModel().getMaxDecel()) << " planned=" << plannedSpeed << "\n";
714 }
715#endif
716 // are we fast enough to cut in without any help?
717 if (MAX2(plannedSpeed, 0.) - nv->getSpeed() >= HELP_OVERTAKE) {
718 const double neededGap = nv->getCarFollowModel().getSecureGap(nv, &myVehicle, nv->getSpeed(), plannedSpeed, myVehicle.getCarFollowModel().getMaxDecel());
719 if ((neededGap - neighFollow.second) / remainingSeconds < (MAX2(plannedSpeed, 0.) - nv->getSpeed())) {
720#ifdef DEBUG_INFORMER
721 if (DEBUG_COND) {
722 std::cout << " wants to cut in before nv=" << nv->getID() << " without any help." << "\nneededGap = " << neededGap << "\n";
723 }
724#endif
725 // follower might even accelerate but not to much
726 // XXX: I don't understand this. The needed gap was determined for nv->getSpeed(), not for (plannedSpeed - HELP_OVERTAKE)?! (Leo), refs. #2578
727 msgPass.informNeighFollower(new Info(MAX2(plannedSpeed, 0.) - HELP_OVERTAKE, dir | LCA_AMBLOCKINGFOLLOWER), &myVehicle);
728 return;
729 }
730 }
731
732 // PARAMETERS
733 // assume other vehicle will assume the equivalent of 1 second of
734 // maximum deceleration to help us (will probably be spread over
735 // multiple seconds)
736 // -----------
737 const double helpDecel = nv->getCarFollowModel().getMaxDecel() * HELP_DECEL_FACTOR;
738
739 // follower's new speed in next step
740 double neighNewSpeed;
741 // follower's new speed after 1s.
742 double neighNewSpeed1s;
743 // velocity difference, gap after follower-deceleration
744 double dv, decelGap;
745
747 // euler
748 neighNewSpeed = MAX2(0., nv->getSpeed() - ACCEL2SPEED(helpDecel));
749 neighNewSpeed1s = MAX2(0., nv->getSpeed() - helpDecel); // TODO: consider introduction of a configurable anticipationTime here (see far below in the !blocked part). Refs. #2578
750 // change in the gap between ego and blocker over 1 second (not STEP!)
751 // XXX: though here it is calculated as if it were one step!? (Leo) Refs. #2578
752 dv = plannedSpeed - neighNewSpeed1s; // XXX: what is this quantity (if TS!=1)?
753 // new gap between follower and self in case the follower does brake for 1s
754 // XXX: if the step-length is not 1s., this is not the gap after 1s. deceleration!
755 // And this formula overestimates the real gap. Isn't that problematic? (Leo)
756 // Below, it seems that decelGap > secureGap is taken to indicate the possibility
757 // to cut in within the next time-step. However, this is not the case, if TS<1s.,
758 // since decelGap is (not exactly, though!) the gap after 1s. Refs. #2578
759 decelGap = neighFollow.second + dv;
760 } else {
761 // ballistic
762 // negative newSpeed-extrapolation possible, if stop lies within the next time-step
763 // XXX: this code should work for the euler case as well, since gapExtrapolation() takes
764 // care of this, but for TS!=1 we will have different behavior (see previous remark) Refs. #2578
765 neighNewSpeed = nv->getSpeed() - ACCEL2SPEED(helpDecel);
766 neighNewSpeed1s = nv->getSpeed() - helpDecel;
767
768 dv = myVehicle.getSpeed() - nv->getSpeed(); // current velocity difference
769 decelGap = getCarFollowModel().gapExtrapolation(1., neighFollow.second, myVehicle.getSpeed(),
770 nv->getSpeed(), plannedAccel, -helpDecel, myVehicle.getMaxSpeedOnLane(), nv->getMaxSpeedOnLane());
771 }
772
773 const double secureGap = nv->getCarFollowModel().getSecureGap(nv, &myVehicle, MAX2(neighNewSpeed1s, 0.),
774 MAX2(plannedSpeed, 0.), myVehicle.getCarFollowModel().getMaxDecel());
775
776 const double onRampThreshold = myVehicle.getLane()->getSpeedLimit() * 0.8 * myExperimentalParam1 * (1 - myVehicle.getImpatience());
777
778#ifdef DEBUG_INFORMER
779 if (DEBUG_COND) {
780 std::cout << SIMTIME
781 << " speed=" << myVehicle.getSpeed()
782 << " plannedSpeed=" << plannedSpeed
783 << " threshold=" << onRampThreshold
784 << " neighNewSpeed=" << neighNewSpeed
785 << " neighNewSpeed1s=" << neighNewSpeed1s
786 << " dv=" << dv
787 << " gap=" << neighFollow.second
788 << " decelGap=" << decelGap
789 << " secureGap=" << secureGap
790 << "\n";
791 }
792#endif
793 // prevent vehicles on an on ramp stopping the main flow
794 if (dir == LCA_MLEFT
796 && neighNewSpeed1s < onRampThreshold) {
797 return;
798 }
799
800 if (decelGap > 0 && decelGap >= secureGap) {
801 // XXX: This does not assure that the leader can cut in in the next step if TS < 1 (see above)
802 // this seems to be supposed in the following (euler code)...?! (Leo) Refs. #2578
803
804 // if the blocking follower brakes it could help
805 // how hard does it actually need to be?
806 // to be safe in the next step the following equation has to hold for the follower's vsafe:
807 // vsafe <= followSpeed(gap=currentGap - SPEED2DIST(vsafe), ...)
808 double vsafe, vsafe1;
809
811 // euler
812 // we compute an upper bound on vsafe by doing the computation twice
813 vsafe1 = MAX2(neighNewSpeed, nv->getCarFollowModel().followSpeed(
814 nv, nv->getSpeed(), neighFollow.second + SPEED2DIST(plannedSpeed), plannedSpeed, getCarFollowModel().getMaxDecel()));
815 vsafe = MAX2(neighNewSpeed, nv->getCarFollowModel().followSpeed(
816 nv, nv->getSpeed(), neighFollow.second + SPEED2DIST(plannedSpeed - vsafe1), plannedSpeed, getCarFollowModel().getMaxDecel()));
817 //assert(vsafe <= vsafe1); assertion does not hold for models with randomness in followSpeed (W99)
818 } else {
819 // ballistic
820
821 // XXX: This block should actually do as well for euler update (TODO: test!), refs #2575
822 // we compute an upper bound on vsafe
823 // next step's gap without help deceleration (nv's speed assumed constant)
824 double nextGap = getCarFollowModel().gapExtrapolation(TS,
825 neighFollow.second, myVehicle.getSpeed(),
826 nv->getSpeed(), plannedAccel, 0,
828#ifdef DEBUG_INFORMER
829 if (DEBUG_COND) {
830 std::cout << "nextGap=" << nextGap << " (without help decel) \n";
831 }
832#endif
833
834 // NOTE: the second argument of MIN2() can get larger than nv->getSpeed()
835 vsafe1 = MIN2(nv->getSpeed(), MAX2(neighNewSpeed,
837 nv->getSpeed(), nextGap,
838 MAX2(0., plannedSpeed),
839 getCarFollowModel().getMaxDecel())));
840
841
842 // next step's gap with possibly less than maximal help deceleration (in case vsafe1 > neighNewSpeed)
843 double decel2 = SPEED2ACCEL(nv->getSpeed() - vsafe1);
845 neighFollow.second, myVehicle.getSpeed(),
846 nv->getSpeed(), plannedAccel, -decel2,
848
849 // vsafe = MAX(neighNewSpeed, safe speed assuming next_gap)
850 // Thus, the gap resulting from vsafe is larger or equal to next_gap
851 // in contrast to the euler case, where nv's follow speed doesn't depend on the actual speed,
852 // we need to assure, that nv doesn't accelerate
853 vsafe = MIN2(nv->getSpeed(), MAX2(neighNewSpeed,
855 nv->getSpeed(), nextGap,
856 MAX2(0., plannedSpeed),
857 getCarFollowModel().getMaxDecel())));
858
859 assert(vsafe >= vsafe1 - NUMERICAL_EPS);
860
861#ifdef DEBUG_INFORMER
862 if (DEBUG_COND) {
863 std::cout << "nextGap=" << nextGap
864 << " (with vsafe1 and help decel) \nvsafe1=" << vsafe1
865 << " vsafe=" << vsafe
866 << "\n";
867 }
868#endif
869
870 // For subsecond simulation, this might not lead to secure gaps for a long time,
871 // we seek to establish a secure gap as soon as possible
872 double nextSecureGap = nv->getCarFollowModel().getSecureGap(nv, &myVehicle, vsafe, plannedSpeed, getCarFollowModel().getMaxDecel());
873
874 if (nextGap < nextSecureGap) {
875 // establish a secureGap as soon as possible
876 vsafe = neighNewSpeed;
877 }
878
879#ifdef DEBUG_INFORMER
880 if (DEBUG_COND) {
881 std::cout << "nextGap=" << nextGap
882 << " minNextSecureGap=" << nextSecureGap
883 << " vsafe=" << vsafe << "\n";
884 }
885#endif
886
887 }
888 msgPass.informNeighFollower(
889 new Info(vsafe, dir | LCA_AMBLOCKINGFOLLOWER), &myVehicle);
890
891#ifdef DEBUG_INFORMER
892 if (DEBUG_COND) {
893 std::cout << " wants to cut in before nv=" << nv->getID()
894 << " vsafe1=" << vsafe1 << " vsafe=" << vsafe
895 << " newSecGap="
896 << nv->getCarFollowModel().getSecureGap(nv, &myVehicle, vsafe,
897 plannedSpeed,
899 << "\n";
900 }
901#endif
902 } else if ((MSGlobals::gSemiImplicitEulerUpdate && dv > 0 && dv * remainingSeconds > (secureGap - decelGap + POSITION_EPS))
903 || (!MSGlobals::gSemiImplicitEulerUpdate && dv > 0 && dv * (remainingSeconds - 1) > secureGap - decelGap + POSITION_EPS)
904 ) {
905
906 // XXX: Alternative formulation (encapsulating differences of euler and ballistic) TODO: test, refs. #2575
907 // double eventualGap = getCarFollowModel().gapExtrapolation(remainingSeconds - 1., decelGap, plannedSpeed, neighNewSpeed1s);
908 // } else if (eventualGap > secureGap + POSITION_EPS) {
909
910
911 // NOTE: This case corresponds to the situation, where some time is left to perform the lc
912 // For the ballistic case this is interpreted as follows:
913 // If the follower breaks with helpDecel for one second, this vehicle maintains the plannedSpeed,
914 // and both continue with their speeds for remainingSeconds seconds the gap will suffice for a laneChange
915 // For the euler case we had the following comment:
916 // 'decelerating once is sufficient to open up a large enough gap in time', but:
917 // XXX: 1) Decelerating *once* does not necessarily lead to the gap decelGap! (if TS<1s.) (Leo)
918 // 2) Probably, the if() for euler should test for dv * (remainingSeconds-1) > ..., too ?!, refs. #2578
919 msgPass.informNeighFollower(new Info(neighNewSpeed, dir | LCA_AMBLOCKINGFOLLOWER), &myVehicle);
920#ifdef DEBUG_INFORMER
921 if (DEBUG_COND) {
922 std::cout << " wants to cut in before nv=" << nv->getID() << " (eventually)\n";
923 }
924#endif
925 } else if (dir == LCA_MRIGHT && nv->getLaneChangeModel().avoidOvertakeRight(&myVehicle)) {
926 // XXX: check if this requires a special treatment for the ballistic update, refs. #2575
927 const double vhelp = MAX2(neighNewSpeed, HELP_OVERTAKE);
928 msgPass.informNeighFollower(new Info(vhelp, dir | LCA_AMBLOCKINGFOLLOWER), &myVehicle);
929#ifdef DEBUG_INFORMER
930 if (DEBUG_COND) {
931 std::cout << " wants to cut in before nv=" << nv->getID() << " (nv cannot overtake right)\n";
932 }
933#endif
934 } else {
935 double vhelp = MAX2(nv->getSpeed(), myVehicle.getSpeed() + HELP_OVERTAKE);
936 //if (dir == LCA_MRIGHT && myVehicle.getWaitingSeconds() > LCA_RIGHT_IMPATIENCE &&
937 // nv->getSpeed() > myVehicle.getSpeed()) {
938 if (nv->getSpeed() > myVehicle.getSpeed() &&
939 ((dir == LCA_MRIGHT && myVehicle.getWaitingSeconds() > LCA_RIGHT_IMPATIENCE) // NOTE: it might be considered to use myVehicle.getAccumulatedWaitingSeconds() > LCA_RIGHT_IMPATIENCE instead (Leo). Refs. #2578
940 || (dir == LCA_MLEFT && plannedSpeed > CUT_IN_LEFT_SPEED_THRESHOLD) // VARIANT_22 (slowDownLeft)
941 // XXX this is a hack to determine whether the vehicles is on an on-ramp. This information should be retrieved from the network itself
943 )) {
944 // let the follower slow down to increase the likelihood that later vehicles will be slow enough to help
945 // follower should still be fast enough to open a gap
946 // XXX: The probability for that success would be larger if the slow down of the appropriate following vehicle
947 // would take place without the immediate follower slowing down. We might consider to model reactions of
948 // vehicles that are not immediate followers. (Leo) -> see ticket #2532
949 vhelp = MAX2(neighNewSpeed, myVehicle.getSpeed() + HELP_OVERTAKE);
950#ifdef DEBUG_INFORMER
951 if (DEBUG_COND) {
952 // NOTE: the condition labeled "VARIANT_22" seems to imply that this could as well concern the *left* follower?! (Leo)
953 // Further, vhelp might be larger than nv->getSpeed(), so the request issued below is not to slow down!? (see below) Refs. #2578
954 std::cout << " wants right follower to slow down a bit\n";
955 }
956#endif
958 // euler
959 if ((nv->getSpeed() - myVehicle.getSpeed()) / helpDecel < remainingSeconds) {
960
961#ifdef DEBUG_INFORMER
962 if (DEBUG_COND) {
963 // NOTE: the condition labeled "VARIANT_22" seems to imply that this could as well concern the *left* follower?! Refs. #2578
964 std::cout << " wants to cut in before right follower nv=" << nv->getID() << " (eventually)\n";
965 }
966#endif
967 // XXX: I don't understand. This vhelp might be larger than nv->getSpeed() but the above condition seems to rely
968 // on the reasoning that if nv breaks with helpDecel for remaining Seconds, nv will be so slow, that this
969 // vehicle will be able to cut in. But nv might have overtaken this vehicle already (or am I missing sth?). (Leo)
970 // Ad: To my impression, the intention behind allowing larger speeds for the blocking follower is to prevent a
971 // situation, where an overlapping follower keeps blocking the ego vehicle. Refs. #2578
972 msgPass.informNeighFollower(new Info(vhelp, dir | LCA_AMBLOCKINGFOLLOWER), &myVehicle);
973 return;
974 }
975 } else {
976
977 // 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)
978 // estimate gap after remainingSeconds.
979 // Assumptions:
980 // (A1) leader continues with currentSpeed. (XXX: That might be wrong: Think of accelerating on an on-ramp or of a congested region ahead!)
981 // (A2) follower breaks with helpDecel.
982 const double gapAfterRemainingSecs = getCarFollowModel().gapExtrapolation(
983 remainingSeconds, neighFollow.second, myVehicle.getSpeed(), nv->getSpeed(), 0, -helpDecel, myVehicle.getMaxSpeedOnLane(), nv->getMaxSpeedOnLane());
984 const double secureGapAfterRemainingSecs = nv->getCarFollowModel().getSecureGap(nv, &myVehicle,
985 MAX2(nv->getSpeed() - remainingSeconds * helpDecel, 0.), myVehicle.getSpeed(), myVehicle.getCarFollowModel().getMaxDecel());
986 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
987#ifdef DEBUG_INFORMER
988 if (DEBUG_COND) {
989 std::cout << " wants to cut in before follower nv=" << nv->getID() << " (eventually)\n";
990 }
991#endif
992 // NOTE: ballistic uses neighNewSpeed instead of vhelp, see my note above. (Leo)
993 // TODO: recheck if this might cause suboptimal behaviour in some LC-situations. Refs. #2578
994 msgPass.informNeighFollower(new Info(neighNewSpeed, dir | LCA_AMBLOCKINGFOLLOWER), &myVehicle);
995 return;
996 }
997 }
998
999
1000 }
1001
1002#ifdef DEBUG_INFORMER
1003 if (DEBUG_COND) {
1004 std::cout << SIMTIME
1005 << " veh=" << myVehicle.getID()
1006 << " informs follower " << nv->getID()
1007 << " vhelp=" << vhelp
1008 << "\n";
1009 }
1010#endif
1011
1012 msgPass.informNeighFollower(new Info(vhelp, dir | LCA_AMBLOCKINGFOLLOWER), &myVehicle);
1013 // This follower is supposed to overtake us. Slow down smoothly to allow this.
1014 const double overtakeDist = overtakeDistance(nv, &myVehicle, neighFollow.second, vhelp, plannedSpeed);
1015 // speed difference to create a sufficiently large gap
1016 const double needDV = overtakeDist / remainingSeconds;
1017 // 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
1019
1020#ifdef DEBUG_INFORMER
1021 if (DEBUG_COND) {
1022 std::cout << SIMTIME
1023 << " veh=" << myVehicle.getID()
1024 << " wants to be overtaken by=" << nv->getID()
1025 << " overtakeDist=" << overtakeDist
1026 << " vneigh=" << nv->getSpeed()
1027 << " vhelp=" << vhelp
1028 << " needDV=" << needDV
1029 << " vsafe=" << myLCAccelerationAdvices.back().first
1030 << "\n";
1031 }
1032#endif
1033 }
1034 } else if (neighFollow.first != nullptr && (blocked & LCA_BLOCKED_BY_LEADER)) {
1035 // we are not blocked by the follower now, make sure it remains that way
1036 const double vsafe = MSLCHelper::getSpeedPreservingSecureGap(myVehicle, *neighFollow.first, neighFollow.second, plannedSpeed);
1037 msgPass.informNeighFollower(new Info(vsafe, dir), &myVehicle);
1038
1039#ifdef DEBUG_INFORMER
1040 if (DEBUG_COND) {
1041 std::cout << " wants to cut in before non-blocking follower nv=" << nv->getID() << "\n";
1042 }
1043#endif
1044 }
1045}
1046
1047
1048void
1051 // keep information about strategic change direction
1052 if (!isChangingLanes()) {
1054 }
1056 myLeftSpace = 0;
1058 myDontBrake = false;
1059 // truncate to work around numerical instability between different builds
1060 if (mySigma > 0 && !isChangingLanes()) {
1061 // disturb lateral position directly
1062 const double maxDist = SPEED2DIST(myVehicle.getVehicleType().getMaxSpeedLat());
1063 const double oldPosLat = myVehicle.getLateralPositionOnLane();
1064 const double overlap = myVehicle.getLateralOverlap();
1065 double scaledDelta;
1066 if (overlap > 0) {
1067 // return to within lane boundary
1068 scaledDelta = MIN2(overlap, maxDist);
1070 scaledDelta *= -1;
1071 }
1072 } else {
1073 // random drift
1074 double deltaPosLat = OUProcess::step(oldPosLat,
1076 MAX2(NUMERICAL_EPS, (1 - mySigma) * 100), mySigma) - oldPosLat;
1077 deltaPosLat = MAX2(MIN2(deltaPosLat, maxDist), -maxDist);
1078 scaledDelta = deltaPosLat * myVehicle.getSpeed() / myVehicle.getLane()->getSpeedLimit();
1079 }
1080 myVehicle.setLateralPositionOnLane(oldPosLat + scaledDelta);
1081 setSpeedLat(DIST2SPEED(scaledDelta));
1082 } else {
1083 resetSpeedLat();
1084 }
1085}
1086
1087
1088void
1090 myOwnState = 0;
1094 if (myVehicle.getBestLaneOffset() == 0) {
1095 // if we are not yet on our best lane there might still be unseen blockers
1096 // (during patchSpeed)
1098 myLeftSpace = 0;
1099 }
1102 myDontBrake = false;
1104}
1105
1106
1107void
1119
1120
1121int
1123 int laneOffset,
1125 int blocked,
1126 const std::pair<MSVehicle*, double>& leader,
1127 const std::pair<MSVehicle*, double>& follower,
1128 const std::pair<MSVehicle*, double>& neighLead,
1129 const std::pair<MSVehicle*, double>& neighFollow,
1130 const MSLane& neighLane,
1131 const std::vector<MSVehicle::LaneQ>& preb,
1132 MSVehicle* lastBlocked,
1133 MSVehicle* firstBlocked) {
1134 assert(laneOffset == 1 || laneOffset == -1);
1135 const SUMOTime currentTime = MSNet::getInstance()->getCurrentTimeStep();
1136 // compute bestLaneOffset
1137 MSVehicle::LaneQ curr, neigh, best;
1138 int bestLaneOffset = 0;
1139 // What do these "dists" mean? Please comment. (Leo) Ad: I now think the following:
1140 // currentDist is the distance that the vehicle can go on its route without having to
1141 // change lanes from the current lane. neighDist as currentDist for the considered target lane (i.e., neigh)
1142 // If this is true I suggest to put this into the docu of wantsChange()
1143 double currentDist = 0;
1144 double neighDist = 0;
1145 int currIdx = 0;
1146 const bool checkOpposite = &neighLane.getEdge() != &myVehicle.getLane()->getEdge();
1147 const MSLane* prebLane = myVehicle.getLane();
1148 if (prebLane->getEdge().isInternal()) {
1149 // internal edges are not kept inside the bestLanes structure
1150 if (isOpposite()) {
1151 prebLane = prebLane->getNormalPredecessorLane();
1152 } else {
1153 prebLane = prebLane->getLinkCont()[0]->getLane();
1154 }
1155 }
1156 // special case: vehicle considers changing to the opposite direction edge
1157 const int prebOffset = laneOffset;
1158 for (int p = 0; p < (int) preb.size(); ++p) {
1159 //if (DEBUG_COND) {
1160 // std::cout << " p=" << p << " prebLane=" << prebLane->getID() << " preb.p=" << preb[p].lane->getID() << "\n";
1161 //}
1162 if (preb[p].lane == prebLane && p + laneOffset >= 0) {
1163 assert(p + prebOffset < (int)preb.size());
1164 curr = preb[p];
1165 neigh = preb[p + prebOffset];
1166 currentDist = curr.length;
1167 neighDist = neigh.length;
1168 bestLaneOffset = curr.bestLaneOffset;
1169 if (bestLaneOffset == 0 && preb[p + prebOffset].bestLaneOffset == 0 && !checkOpposite) {
1170#ifdef DEBUG_WANTS_CHANGE
1171 if (DEBUG_COND) {
1172 std::cout << STEPS2TIME(currentTime)
1173 << " veh=" << myVehicle.getID()
1174 << " bestLaneOffsetOld=" << bestLaneOffset
1175 << " bestLaneOffsetNew=" << laneOffset
1176 << "\n";
1177 }
1178#endif
1179 bestLaneOffset = prebOffset;
1180 }
1181 best = preb[p + bestLaneOffset];
1182 currIdx = p;
1183 break;
1184 }
1185 }
1186 assert(curr.lane != nullptr);
1187 assert(neigh.lane != nullptr);
1188 assert(best.lane != nullptr);
1189 // direction specific constants
1190 const bool right = (laneOffset == -1);
1191 const double posOnLane = getForwardPos();
1192 double driveToNextStop = -std::numeric_limits<double>::max();
1193 if (myVehicle.nextStopDist() < std::numeric_limits<double>::max()
1195 // vehicle can always drive up to stop distance
1196 // @note this information is dynamic and thus not available in updateBestLanes()
1197 // @note: nextStopDist was compute before the vehicle moved
1198 driveToNextStop = myVehicle.nextStopDist();
1199 const double stopPos = posOnLane + myVehicle.nextStopDist() - myVehicle.getLastStepDist();
1200#ifdef DEBUG_WANTS_CHANGE
1201 if (DEBUG_COND) {
1202 std::cout << SIMTIME << std::setprecision(gPrecision) << " veh=" << myVehicle.getID()
1203 << " stopDist=" << myVehicle.nextStopDist()
1204 << " lastDist=" << myVehicle.getLastStepDist()
1205 << " stopPos=" << stopPos
1206 << " currentDist=" << currentDist
1207 << " neighDist=" << neighDist
1208 << "\n";
1209 }
1210#endif
1211 currentDist = MAX2(currentDist, stopPos);
1212 neighDist = MAX2(neighDist, stopPos);
1213 }
1214 const int lca = (right ? LCA_RIGHT : LCA_LEFT);
1215 const int myLca = (right ? LCA_MRIGHT : LCA_MLEFT);
1216 const int lcaCounter = (right ? LCA_LEFT : LCA_RIGHT);
1217 bool changeToBest = (right && bestLaneOffset < 0) || (!right && bestLaneOffset > 0);
1218 // keep information about being a leader/follower
1219 int ret = (myOwnState & 0xffff0000);
1220 int req = 0; // the request to change or stay
1221
1222 ret = slowDownForBlocked(lastBlocked, ret);
1223 if (lastBlocked != firstBlocked) {
1224 ret = slowDownForBlocked(firstBlocked, ret);
1225 }
1226
1227#ifdef DEBUG_WANTS_CHANGE
1228 if (DEBUG_COND) {
1229 std::cout << SIMTIME
1230 << " veh=" << myVehicle.getID()
1231 << " _wantsChange state=" << myOwnState
1232 << " myLCAccelerationAdvices=" << toString(myLCAccelerationAdvices)
1233 << " firstBlocked=" << Named::getIDSecure(firstBlocked)
1234 << " lastBlocked=" << Named::getIDSecure(lastBlocked)
1235 << " leader=" << Named::getIDSecure(leader.first)
1236 << " leaderGap=" << leader.second
1237 << " follower=" << Named::getIDSecure(follower.first)
1238 << " followerGap=" << follower.second
1239 << " neighLead=" << Named::getIDSecure(neighLead.first)
1240 << " neighLeadGap=" << neighLead.second
1241 << " neighFollow=" << Named::getIDSecure(neighFollow.first)
1242 << " neighFollowGap=" << neighFollow.second
1243 << "\n";
1244 }
1245#endif
1246
1247 // we try to estimate the distance which is necessary to get on a lane
1248 // we have to get on in order to keep our route
1249 // we assume we need something that depends on our velocity
1250 // and compare this with the free space on our wished lane
1251 //
1252 // if the free space is somehow(<-?) less than the space we need, we should
1253 // definitely try to get to the desired lane
1254 //
1255 // this rule forces our vehicle to change the lane if a lane changing is necessary soon
1256
1257
1258 // we do not want the lookahead distance to change all the time so we let it decay slowly
1259 // (in contrast, growth is applied instantaneously)
1262 } else {
1263 // memory decay factor for this action step
1264 const double memoryFactor = 1. - (1. - LOOK_AHEAD_SPEED_MEMORY) * myVehicle.getActionStepLengthSecs();
1265 assert(memoryFactor > 0.);
1267 (memoryFactor * myLookAheadSpeed + (1 - memoryFactor) * myVehicle.getSpeed()));
1268 }
1269 double laDist = myLookAheadSpeed * LOOK_FORWARD * myStrategicParam * (right ? 1 : myLookaheadLeft);
1270 laDist += myVehicle.getVehicleType().getLengthWithGap() * 2.;
1271 const bool hasStoppedLeader = leader.first != 0 && leader.first->isStopped() && leader.second < (currentDist - posOnLane);
1272 const bool hasBidiLeader = myVehicle.getLane()->getBidiLane() != nullptr && MSLCHelper::isBidiLeader(leader.first, curr.bestContinuations);
1273 const bool hasBidiNeighLeader = neighLane.getBidiLane() != nullptr && MSLCHelper::isBidiLeader(neighLead.first, neigh.bestContinuations);
1274
1275 if (bestLaneOffset == 0 && hasBidiLeader) {
1276 // getting out of the way is enough to clear the blockage
1277 laDist = 0;
1278 } else if (bestLaneOffset == 0 && hasStoppedLeader) {
1279 // react to a stopped leader on the current lane
1280 // The value of laDist is doubled below for the check whether the lc-maneuver can be taken out
1281 // on the remaining distance (because the vehicle has to change back and forth). Therefore multiply with 0.5.
1282 laDist = 0.5 * (myVehicle.getVehicleType().getLengthWithGap()
1283 + leader.first->getVehicleType().getLengthWithGap()
1284 + leader.second);
1285 } else if (bestLaneOffset == laneOffset && neighLead.first != 0 && (neighLead.first->isStopped() || hasBidiNeighLeader) && neighLead.second < (currentDist - posOnLane)) {
1286 // react to a stopped leader on the target lane (if it is the bestLane)
1287 if (isOpposite()) {
1288 // always allow changing back
1290 + neighLead.first->getVehicleType().getLengthWithGap()
1291 + neighLead.second);
1292 } else if (!hasStoppedLeader &&
1293 ((neighLead.second + myVehicle.getVehicleType().getLengthWithGap() + neighLead.first->getVehicleType().getLengthWithGap()) < (currentDist - posOnLane)
1294 || hasBidiNeighLeader)) {
1295 // do not change to the target lane until passing the stopped vehicle
1296 // (unless the vehicle blocks our intended stopping position, then we have to wait anyway)
1297 changeToBest = false;
1298 }
1299 }
1300 if (myStrategicParam < 0) {
1301 laDist = -1e3; // never perform strategic change
1302 }
1303
1304 // free space that is available for changing
1305 //const double neighSpeed = (neighLead.first != 0 ? neighLead.first->getSpeed() :
1306 // neighFollow.first != 0 ? neighFollow.first->getSpeed() :
1307 // best.lane->getSpeedLimit());
1308 // @note: while this lets vehicles change earlier into the correct direction
1309 // it also makes the vehicles more "selfish" and prevents changes which are necessary to help others
1310
1311
1312
1313 // Next we assign to roundabout edges a larger distance than to normal edges
1314 // in order to decrease sense of lc urgency and induce higher usage of inner roundabout lanes.
1315 const double roundaboutBonus = MSLCHelper::getRoundaboutDistBonus(myVehicle, myRoundaboutBonus, curr, neigh, best);
1316 currentDist += roundaboutBonus;
1317 neighDist += roundaboutBonus;
1318
1319 const double usableDist = MAX2(currentDist - posOnLane - best.occupation * JAM_FACTOR, driveToNextStop);
1320 //- (best.lane->getVehicleNumber() * neighSpeed)); // VARIANT 9 jfSpeed
1321 const double maxJam = MAX2(preb[currIdx + prebOffset].occupation, preb[currIdx].occupation);
1322 const double vMax = myVehicle.getLane()->getVehicleMaxSpeed(&myVehicle);
1323 const double neighVMax = neighLane.getVehicleMaxSpeed(&myVehicle);
1324 // upper bound which will be restricted successively
1325 double thisLaneVSafe = vMax;
1326 const bool checkOverTakeRight = avoidOvertakeRight(neighLead.first, true);
1327
1328 double neighLeftPlace = MAX2(0.0, neighDist - posOnLane - maxJam);
1329 if (neighLead.first != 0 && neighLead.first->isStopped()) {
1330 neighLeftPlace = MIN2(neighLeftPlace, neighLead.second);
1331 }
1332
1333#ifdef DEBUG_WANTS_CHANGE
1334 if (DEBUG_COND) {
1335 std::cout << STEPS2TIME(currentTime)
1336 << " veh=" << myVehicle.getID()
1337 << " laSpeed=" << myLookAheadSpeed
1338 << " laDist=" << laDist
1339 << " currentDist=" << currentDist
1340 << " usableDist=" << usableDist
1341 << " bestLaneOffset=" << bestLaneOffset
1342 << " best.occupation=" << best.occupation
1343 << " best.length=" << best.length
1344 << "\n roundaboutBonus=" << roundaboutBonus
1345 << " maxJam=" << maxJam
1346 << " neighDist=" << neighDist
1347 << " neighLeftPlace=" << neighLeftPlace
1348 << (hasBidiLeader ? " bidiLeader" : "")
1349 << (hasBidiNeighLeader ? " bidiNeighLeader" : "")
1350 << "\n";
1351 }
1352#endif
1353
1354 bool changeLeftToAvoidOvertakeRight = false;
1355 if (changeToBest && bestLaneOffset == curr.bestLaneOffset
1356 && currentDistDisallows(usableDist, bestLaneOffset, laDist)) {
1358 ret = ret | lca | LCA_STRATEGIC | LCA_URGENT;
1359 } else {
1360 // VARIANT_20 (noOvertakeRight)
1361 if (neighLead.first != 0 && checkOverTakeRight && !right) {
1362 // check for slower leader on the left. we should not overtake but
1363 // rather move left ourselves (unless congested)
1364 const MSVehicle* nv = neighLead.first;
1365 double deltaV = 0.;
1366 double vSafe = 0.;
1367 if (canOvertakeRight(nv, neighLead.second, vMax - neighLane.getVehicleMaxSpeed(nv), HELP_OVERTAKE, vSafe, deltaV)) {
1369 vSafe = MAX2(vSafe, nv->getSpeed());
1370 }
1371 thisLaneVSafe = MIN2(thisLaneVSafe, vSafe);
1372 addLCSpeedAdvice(vSafe);
1373 // only generate impulse for overtaking left shortly before braking would be necessary
1374 const double deltaGapFuture = deltaV * 8;
1375 const double vSafeFuture = getCarFollowModel().followSpeed(
1376 &myVehicle, myVehicle.getSpeed(), neighLead.second - deltaGapFuture, nv->getSpeed(), nv->getCarFollowModel().getMaxDecel());
1377 if (vSafeFuture < vSafe) {
1378 const double relativeGain = deltaV / MAX2(vMax,
1380 mySpeedGainProbabilityLeft += (long long int)(myVehicle.getActionStepLengthSecs() * relativeGain * HYST_PRECISION);
1381 changeLeftToAvoidOvertakeRight = true;
1382 }
1383#ifdef DEBUG_WANTS_CHANGE
1384 if (DEBUG_COND) {
1385 std::cout << STEPS2TIME(currentTime)
1386 << " avoid overtaking on the right nv=" << nv->getID()
1387 << " deltaV=" << deltaV
1388 << " nvSpeed=" << nv->getSpeed()
1389 << " speedGainL=" << mySpeedGainProbabilityLeft / HYST_PRECISION
1390 << " speedGainR=" << mySpeedGainProbabilityRight / HYST_PRECISION
1391 << " planned acceleration =" << myLCAccelerationAdvices.back().first
1392 << "\n";
1393 }
1394#endif
1395 }
1396 }
1397 const bool currFreeUntilNeighEnd = leader.first == nullptr || neighDist - posOnLane <= leader.second;
1398 const double overtakeDist = (leader.first == 0 || hasBidiLeader ? -1 :
1399 leader.second + myVehicle.getVehicleType().getLength() + leader.first->getVehicleType().getLengthWithGap());
1400 const double overtakeDist2 = (neighLead.first == 0 || !neighLead.first->isStopped() ? -1 :
1401 neighLead.second + myVehicle.getVehicleType().getLength() + neighLead.first->getVehicleType().getLengthWithGap());
1402 if (leader.first != 0 && (leader.first->isStopped() || hasBidiLeader) && leader.second < REACT_TO_STOPPED_DISTANCE
1403 // current destination leaves enough space to overtake the leader
1404 && MIN2(neighDist, currentDist) - posOnLane > overtakeDist
1405 // maybe do not overtake on the right at high speed
1406 && (!checkOverTakeRight || !right)
1407 && myStrategicParam >= 0
1408 && (neighLead.first == 0 || !neighLead.first->isStopped()
1409 // neighboring stopped vehicle leaves enough space to overtake leader
1410 || neighLead.second > overtakeDist
1411 // if we cannot pass neighLead before reaching leader we must find another free lane
1412 || (overtakeDist2 > leader.second && hasFreeLane(laneOffset, neighLead)))) {
1413 // avoid becoming stuck behind a stopped leader
1414 currentDist = myVehicle.getPositionOnLane() + leader.second;
1415#ifdef DEBUG_WANTS_CHANGE
1416 if (DEBUG_COND) {
1417 std::cout << " veh=" << myVehicle.getID() << " overtake stopped leader=" << leader.first->getID()
1418 << " overtakeDist=" << overtakeDist
1419 << " overtakeDist2=" << overtakeDist
1420 << " hasFreeLane=" << hasFreeLane(laneOffset, neighLead)
1421 << " remaining=" << MIN2(neighDist, currentDist) - posOnLane
1422 << "\n";
1423 }
1424#endif
1425 ret = ret | lca | LCA_STRATEGIC | LCA_URGENT;
1426 } else if (!changeToBest && currentDistDisallows(neighLeftPlace, abs(bestLaneOffset) + 2, laDist) && !hasBidiLeader) {
1427 // the opposite lane-changing direction should be done than the one examined herein
1428 // we'll check whether we assume we could change anyhow and get back in time...
1429 //
1430 // this rule prevents the vehicle from moving in opposite direction of the best lane
1431 // unless the way till the end where the vehicle has to be on the best lane
1432 // is long enough
1433#ifdef DEBUG_WANTS_CHANGE
1434 if (DEBUG_COND) {
1435 std::cout << " veh=" << myVehicle.getID() << " could not change back and forth in time (1) neighLeftPlace=" << neighLeftPlace << "\n";
1436 }
1437#endif
1438 ret = ret | LCA_STAY | LCA_STRATEGIC;
1439 } else if (bestLaneOffset == 0 && (neighLeftPlace * 2. < laDist)) {
1440 // the current lane is the best and a lane-changing would cause a situation
1441 // of which we assume we will not be able to return to the lane we have to be on.
1442 // this rule prevents the vehicle from leaving the current, best lane when it is
1443 // close to this lane's end
1444#ifdef DEBUG_WANTS_CHANGE
1445 if (DEBUG_COND) {
1446 std::cout << " veh=" << myVehicle.getID() << " could not change back and forth in time (2) neighLeftPlace=" << neighLeftPlace << "\n";
1447 }
1448#endif
1449 ret = ret | LCA_STAY | LCA_STRATEGIC;
1450 } else if (bestLaneOffset == 0
1451 && (leader.first == 0 || !leader.first->isStopped())
1452 && !hasBidiLeader
1453 && neigh.bestContinuations.back()->getLinkCont().size() != 0
1454 && roundaboutBonus == 0
1455 && !checkOpposite
1456 && ((myStrategicParam >= 0 && neighDist < TURN_LANE_DIST)
1457 // lane changing cannot possibly help
1458 || (myStrategicParam < 0 && currFreeUntilNeighEnd))
1459 ) {
1460 // VARIANT_21 (stayOnBest)
1461 // we do not want to leave the best lane for a lane which leads elsewhere
1462 // unless our leader is stopped or we are approaching a roundabout
1463#ifdef DEBUG_WANTS_CHANGE
1464 if (DEBUG_COND) {
1465 std::cout << " veh=" << myVehicle.getID() << " does not want to leave the bestLane (neighDist=" << neighDist << ")\n";
1466 }
1467#endif
1468 ret = ret | LCA_STAY | LCA_STRATEGIC;
1469 }
1470 }
1471 // check for overriding TraCI requests
1472#ifdef DEBUG_WANTS_CHANGE
1473 if (DEBUG_COND) {
1474 std::cout << STEPS2TIME(currentTime) << " veh=" << myVehicle.getID() << " ret=" << toString((LaneChangeAction)ret);
1475 }
1476#endif
1477 // store state before canceling
1478 getCanceledState(laneOffset) |= ret | blocked;
1480 if ((ret & lcaCounter) != 0) {
1481 // we are not interested in traci requests for the opposite direction here
1482 ret &= ~(LCA_TRACI | lcaCounter | LCA_URGENT);
1483 }
1484#ifdef DEBUG_WANTS_CHANGE
1485 if (DEBUG_COND) {
1486 std::cout << " retAfterInfluence=" << toString((LaneChangeAction)ret) << "\n";
1487 }
1488#endif
1489
1490 if ((ret & LCA_STAY) != 0) {
1491 // remove TraCI flags because it should not be included in "state-without-traci"
1492 ret = getCanceledState(laneOffset);
1493 return ret;
1494 }
1495 if ((ret & LCA_URGENT) != 0) {
1496 // prepare urgent lane change maneuver
1497 // save the left space
1498 myLeftSpace = currentDist - posOnLane;
1499 if (changeToBest && abs(bestLaneOffset) > 1 && myVehicle.getNumRemainingEdges() > 1) {
1500 // there might be a vehicle which needs to counter-lane-change one lane further and we cannot see it yet
1501 myLeadingBlockerLength = MAX2(getExtraReservation(bestLaneOffset, neighDist - currentDist), myLeadingBlockerLength);
1502#ifdef DEBUG_SAVE_BLOCKER_LENGTH
1503 if (DEBUG_COND) {
1504 std::cout << " reserving space for unseen blockers myLeadingBlockerLength=" << myLeadingBlockerLength << "\n";
1505 }
1506#endif
1507 }
1508
1509 // letting vehicles merge in at the end of the lane in case of counter-lane change, step#1
1510 // if there is a leader and he wants to change to the opposite direction
1511 const bool canContinue = curr.bestContinuations.size() > 1;
1512 bool canReserve = MSLCHelper::updateBlockerLength(myVehicle, neighLead.first, lcaCounter, myLeftSpace - POSITION_EPS, canContinue, myLeadingBlockerLength);
1513 if (firstBlocked != neighLead.first) {
1514 canReserve &= MSLCHelper::updateBlockerLength(myVehicle, firstBlocked, lcaCounter, myLeftSpace - POSITION_EPS, canContinue, myLeadingBlockerLength);
1515 }
1516#ifdef DEBUG_SAVE_BLOCKER_LENGTH
1517 if (DEBUG_COND) {
1518 std::cout << SIMTIME << " canReserve=" << canReserve << " canContinue=" << canContinue << "\n";
1519 }
1520#endif
1521 if (!canReserve && !isOpposite()) {
1522 // we have a low-priority relief connection
1523 // std::cout << SIMTIME << " veh=" << myVehicle.getID() << " cannotReserve for blockers\n";
1524 myDontBrake = canContinue;
1525 }
1526
1527 const int remainingLanes = MAX2(1, abs(bestLaneOffset));
1528 const double urgency = isOpposite() ? OPPOSITE_URGENCY : URGENCY;
1529 const double remainingSeconds = ((ret & LCA_TRACI) == 0 ?
1530 //MAX2(STEPS2TIME(TS), (myLeftSpace-myLeadingBlockerLength) / MAX2(myLookAheadSpeed, NUMERICAL_EPS) / remainingLanes / urgency) :
1531 MAX2(STEPS2TIME(TS), myLeftSpace / MAX2(myLookAheadSpeed, NUMERICAL_EPS) / remainingLanes / urgency) :
1533 if (!hasBidiNeighLeader) {
1534 const double plannedSpeed = informLeader(msgPass, blocked, myLca, neighLead, remainingSeconds);
1535 // NOTE: for the ballistic update case negative speeds may indicate a stop request,
1536 // while informLeader returns -1 in that case. Refs. #2577
1537 if (plannedSpeed >= 0 || (!MSGlobals::gSemiImplicitEulerUpdate && plannedSpeed != -1)) {
1538 // maybe we need to deal with a blocking follower
1539 const bool hasBidiNeighFollower = neighLane.getBidiLane() != nullptr && MSLCHelper::isBidiFollower(&myVehicle, neighFollow.first);
1540 if (!hasBidiNeighFollower) {
1541 informFollower(msgPass, blocked, myLca, neighFollow, remainingSeconds, plannedSpeed);
1542 }
1543 }
1544#ifdef DEBUG_WANTS_CHANGE
1545 if (DEBUG_COND) {
1546 std::cout << STEPS2TIME(currentTime)
1547 << " veh=" << myVehicle.getID()
1548 << " myLeftSpace=" << myLeftSpace
1549 << " remainingSeconds=" << remainingSeconds
1550 << " plannedSpeed=" << plannedSpeed
1551 << "\n";
1552 }
1553#endif
1554 } else {
1555#ifdef DEBUG_WANTS_CHANGE
1556 if (DEBUG_COND) {
1557 std::cout << STEPS2TIME(currentTime)
1558 << " veh=" << myVehicle.getID()
1559 << " myLeftSpace=" << myLeftSpace
1560 << " remainingSeconds=" << remainingSeconds
1561 << " hasBidiNeighLeader\n";
1562 }
1563#endif
1564 }
1565
1566
1567 // remove TraCI flags because it should not be included in "state-without-traci"
1568 ret = getCanceledState(laneOffset);
1569 return ret;
1570 }
1571
1572 // we wish to anticipate future speeds. This is difficult when the leading
1573 // vehicles are still accelerating so we resort to comparing speeds for the near future (1s) in this case
1574 const bool acceleratingLeader = (neighLead.first != 0 && neighLead.first->getAcceleration() > 0)
1575 || (leader.first != 0 && leader.first->getAcceleration() > 0);
1576 double neighLaneVSafe = MIN2(neighVMax, anticipateFollowSpeed(neighLead, neighDist, neighVMax, acceleratingLeader));
1577 thisLaneVSafe = MIN2(thisLaneVSafe, anticipateFollowSpeed(leader, currentDist, vMax, acceleratingLeader));
1578 //std::cout << SIMTIME << " veh=" << myVehicle.getID() << " thisLaneVSafe=" << thisLaneVSafe << " neighLaneVSafe=" << neighLaneVSafe << "\n";
1579
1580
1581 // a high inconvenience prevents cooperative changes and the following things are inconvenient:
1582 // - a desire to change in the opposite direction for speedGain
1583 // - low anticipated speed on the neighboring lane
1584 // - high occupancy on the neighboring lane while in a roundabout
1585
1586 double inconvenience = laneOffset < 0
1589
1590 const double relSpeedDiff = thisLaneVSafe == 0 ? 0 : (thisLaneVSafe - neighLaneVSafe) / MAX2(thisLaneVSafe, neighLaneVSafe);
1591 inconvenience = MAX2(relSpeedDiff, inconvenience);
1592 inconvenience = MIN2(1.0, inconvenience);
1593
1594 const bool speedGainInconvenient = inconvenience > myCooperativeParam;
1595 const bool neighOccupancyInconvenient = neigh.lane->getBruttoOccupancy() > curr.lane->getBruttoOccupancy();
1596#ifdef DEBUG_WANTS_CHANGE
1597 if (DEBUG_COND) {
1598 std::cout << STEPS2TIME(currentTime)
1599 << " veh=" << myVehicle.getID()
1600 << " speedGainL=" << mySpeedGainProbabilityLeft / HYST_PRECISION
1601 << " speedGainR=" << mySpeedGainProbabilityRight / HYST_PRECISION
1602 << " neighSpeedFactor=" << (thisLaneVSafe / neighLaneVSafe - 1)
1603 << " inconvenience=" << inconvenience
1604 << " speedInconv=" << speedGainInconvenient
1605 << " occInconv=" << neighOccupancyInconvenient
1606 << "\n";
1607 }
1608#endif
1609
1610 // VARIANT_15
1611 if (roundaboutBonus > 0) {
1612
1613#ifdef DEBUG_WANTS_CHANGE
1614 if (DEBUG_COND) {
1615 std::cout << STEPS2TIME(currentTime)
1616 << " veh=" << myVehicle.getID()
1617 << " roundaboutBonus=" << roundaboutBonus
1618 << " myLeftSpace=" << myLeftSpace
1619 << "\n";
1620 }
1621#endif
1622 // try to use the inner lanes of a roundabout to increase throughput
1623 // unless we are approaching the exit
1624 if (lca == LCA_LEFT) {
1625 // if inconvenience is not too high, request collaborative change (currently only for ballistic update)
1626 // TODO: test this for euler update! Refs. #2575
1627 if (MSGlobals::gSemiImplicitEulerUpdate || !neighOccupancyInconvenient) {
1628// if(MSGlobals::gSemiImplicitEulerUpdate || !speedGainInconvenient){
1629 req = ret | lca | LCA_COOPERATIVE;
1630 }
1631 } else {
1632 // if inconvenience is not too high, request collaborative change (currently only for ballistic update)
1633 if (MSGlobals::gSemiImplicitEulerUpdate || neighOccupancyInconvenient) {
1634// if(MSGlobals::gSemiImplicitEulerUpdate || speedGainInconvenient){
1635 req = ret | LCA_STAY | LCA_COOPERATIVE;
1636 }
1637 }
1638 if (!cancelRequest(req, laneOffset)) {
1639 return ret | req;
1640 }
1641 }
1642
1643 // let's also regard the case where the vehicle is driving on a highway...
1644 // in this case, we do not want to get to the dead-end of an on-ramp
1645 if (right) {
1646 if (bestLaneOffset == 0 && myVehicle.getLane()->getSpeedLimit() > 80. / 3.6 && myLookAheadSpeed > SUMO_const_haltingSpeed) {
1647#ifdef DEBUG_WANTS_CHANGE
1648 if (DEBUG_COND) {
1649 std::cout << " veh=" << myVehicle.getID() << " does not want to get stranded on the on-ramp of a highway\n";
1650 }
1651#endif
1652 req = ret | LCA_STAY | LCA_STRATEGIC;
1653 if (!cancelRequest(req, laneOffset)) {
1654 return ret | req;
1655 }
1656 }
1657 }
1658 // --------
1659
1660 // -------- make place on current lane if blocking follower
1661 //if (amBlockingFollowerPlusNB()) {
1662 // std::cout << myVehicle.getID() << ", " << currentDistAllows(neighDist, bestLaneOffset, laDist)
1663 // << " neighDist=" << neighDist
1664 // << " currentDist=" << currentDist
1665 // << "\n";
1666 //}
1667
1669 && (!speedGainInconvenient)
1670 && ((myOwnState & myLca) != 0) // VARIANT_6 : counterNoHelp
1671 && (changeToBest || currentDistAllows(neighDist, abs(bestLaneOffset) + 1, laDist))) {
1672
1673 // VARIANT_2 (nbWhenChangingToHelp)
1674#ifdef DEBUG_COOPERATE
1675 if (DEBUG_COND) {
1676 std::cout << STEPS2TIME(currentTime)
1677 << " veh=" << myVehicle.getID()
1678 << " wantsChangeToHelp=" << (right ? "right" : "left")
1679 << " state=" << myOwnState
1680 << (((myOwnState & myLca) == 0) ? " (counter)" : "")
1681 << "\n";
1682 }
1683#endif
1684 req = ret | lca | LCA_COOPERATIVE | LCA_URGENT ;//| LCA_CHANGE_TO_HELP;
1685 if (!cancelRequest(req, laneOffset)) {
1686 if ((blocked & LCA_BLOCKED_BY_LEFT_FOLLOWER) && !right && mySpeedGainProbabilityLeft > (long long int)(mySpeedGainUrgency * HYST_PRECISION)) {
1687 MSVehicle* nv = neighFollow.first;
1688 const bool hasBidiNeighFollower = neighLane.getBidiLane() != nullptr && MSLCHelper::isBidiFollower(&myVehicle, nv);
1689 if (nv != nullptr && !hasBidiNeighFollower) {
1690 const double helpSpeed = MAX2(nv->getCarFollowModel().minNextSpeed(nv->getSpeed(), nv), myVehicle.getSpeed() - 1);
1691 msgPass.informNeighFollower(new Info(helpSpeed, myLca | LCA_AMBLOCKINGFOLLOWER), &myVehicle);
1692 }
1693 }
1694 return ret | req;
1695 }
1696 }
1697
1698 // --------
1699
1700
1703 //if ((blocked & LCA_BLOCKED) != 0) {
1704 // return ret;
1705 //}
1707
1708 // -------- higher speed
1709 //if ((congested(neighLead.first) && neighLead.second < 20) || predInteraction(leader.first)) { //!!!
1710 // return ret;
1711 //}
1712
1713 if (neighLane.getEdge().getPersons().size() > 0) {
1714 // react to pedestrians
1715 adaptSpeedToPedestrians(myVehicle.getLane(), thisLaneVSafe);
1716 adaptSpeedToPedestrians(&neighLane, neighLaneVSafe);
1717 }
1718
1719 const double relativeGain = (neighLaneVSafe - thisLaneVSafe) / MAX2(neighLaneVSafe,
1721
1722#ifdef DEBUG_WANTS_CHANGE
1723 if (DEBUG_COND) {
1724 std::cout << STEPS2TIME(currentTime)
1725 << " veh=" << myVehicle.getID()
1726 << " currentDist=" << currentDist
1727 << " neighDist=" << neighDist
1728 << " thisVSafe=" << thisLaneVSafe
1729 << " neighVSafe=" << neighLaneVSafe
1730 << " relGain=" << toString(relativeGain, 8)
1731 << "\n";
1732 }
1733#endif
1734
1735 if (right) {
1736 // ONLY FOR CHANGING TO THE RIGHT
1737 if (thisLaneVSafe - 5 / 3.6 > neighLaneVSafe) {
1738 // ok, the current lane is faster than the right one...
1740 //myKeepRightProbability /= 2.0;
1741 } else {
1742 // ok, the current lane is not (much) faster than the right one
1743 mySpeedGainProbabilityRight += (long long int)(myVehicle.getActionStepLengthSecs() * relativeGain * HYST_PRECISION);
1744
1745 // honor the obligation to keep right (Rechtsfahrgebot)
1746 const double roadSpeedFactor = vMax / myVehicle.getLane()->getSpeedLimit(); // differse from speedFactor if vMax < speedLimit
1747 double acceptanceTime;
1748 if (myKeepRightAcceptanceTime == -1) {
1749 // legacy behavior: scale acceptance time with current speed and
1750 // use old hard-coded constant
1751 acceptanceTime = 7 * roadSpeedFactor * MAX2(1.0, myVehicle.getSpeed());
1752 } else {
1753 acceptanceTime = myKeepRightAcceptanceTime * roadSpeedFactor;
1754 if (follower.first != nullptr && follower.second < 2 * follower.first->getCarFollowModel().brakeGap(follower.first->getSpeed())) {
1755 // reduce acceptanceTime if the follower vehicle is faster or wants to drive faster
1756 if (follower.first->getSpeed() >= myVehicle.getSpeed()) {
1757 acceptanceTime *= MAX2(1.0, myVehicle.getSpeed()) / MAX2(1.0, follower.first->getSpeed());
1758 const double fRSF = follower.first->getLane()->getVehicleMaxSpeed(follower.first) / follower.first->getLane()->getSpeedLimit();
1759 if (fRSF > roadSpeedFactor) {
1760 acceptanceTime /= fRSF;
1761 }
1762 }
1763 }
1764 }
1765 double fullSpeedGap = MAX2(0., neighDist - myVehicle.getCarFollowModel().brakeGap(vMax));
1766 double fullSpeedDrivingSeconds = MIN2(acceptanceTime, fullSpeedGap / vMax);
1767 if (neighLead.first != 0 && neighLead.first->getSpeed() < vMax) {
1768 fullSpeedGap = MAX2(0., MIN2(fullSpeedGap,
1769 neighLead.second - myVehicle.getCarFollowModel().getSecureGap(&myVehicle, neighLead.first,
1770 vMax, neighLead.first->getSpeed(), neighLead.first->getCarFollowModel().getMaxDecel())));
1771 fullSpeedDrivingSeconds = MIN2(fullSpeedDrivingSeconds, fullSpeedGap / (vMax - neighLead.first->getSpeed()));
1772 }
1773 // stay on the current lane if we cannot overtake a slow leader on the right
1774 if (checkOverTakeRight && leader.first != 0
1775 && leader.first->getLane()->getVehicleMaxSpeed(leader.first) < vMax) {
1776 fullSpeedGap = MIN2(fullSpeedGap, leader.second);
1777 fullSpeedDrivingSeconds = MIN2(fullSpeedDrivingSeconds, fullSpeedGap / (vMax - leader.first->getSpeed()));
1778 }
1779
1780 const double deltaProb = (myChangeProbThresholdRight == std::numeric_limits<long long int>::max()) ? 0 :
1781 ((double)myChangeProbThresholdRight * (fullSpeedDrivingSeconds / acceptanceTime) / KEEP_RIGHT_TIME);
1782 myKeepRightProbability -= (long long int)(myVehicle.getActionStepLengthSecs() * deltaProb);
1783
1784 //std::cout << STEPS2TIME(currentTime)
1785 // << " veh=" << myVehicle.getID()
1786 // << " acceptanceTime=" << acceptanceTime
1787 // << " fullSpeedDrivingSeconds=" << fullSpeedDrivingSeconds
1788 // << " dProb=" << deltaProb
1789 // << " myKeepRightProbability=" << myKeepRightProbability
1790 // << "\n";
1791
1792#ifdef DEBUG_WANTS_CHANGE
1793 if (DEBUG_COND) {
1794 std::cout << STEPS2TIME(currentTime)
1795 << " veh=" << myVehicle.getID()
1796 << " vMax=" << vMax
1797 << " neighDist=" << neighDist
1798 << " brakeGap=" << myVehicle.getCarFollowModel().brakeGap(myVehicle.getSpeed())
1799 << " leaderSpeed=" << (neighLead.first == 0 ? -1 : neighLead.first->getSpeed())
1800 << " secGap=" << (neighLead.first == 0 ? -1 : myVehicle.getCarFollowModel().getSecureGap(&myVehicle, neighLead.first,
1801 myVehicle.getSpeed(), neighLead.first->getSpeed(), neighLead.first->getCarFollowModel().getMaxDecel()))
1802 << " acceptanceTime=" << acceptanceTime
1803 << " fullSpeedGap=" << fullSpeedGap
1804 << " fullSpeedDrivingSeconds=" << fullSpeedDrivingSeconds
1805 << " dProb=" << deltaProb / HYST_PRECISION
1806 << " myKeepRightProbability=" << myKeepRightProbability / HYST_PRECISION
1807 << "\n";
1808 }
1809#endif
1810 if ((long long int)((double)myKeepRightProbability * myKeepRightParam) < -myChangeProbThresholdRight) {
1811 req = ret | lca | LCA_KEEPRIGHT;
1812 if (!cancelRequest(req, laneOffset)) {
1813 return ret | req;
1814 }
1815 }
1816 }
1817
1818#ifdef DEBUG_WANTS_CHANGE
1819 if (DEBUG_COND) {
1820 std::cout << STEPS2TIME(currentTime)
1821 << " veh=" << myVehicle.getID()
1822 << " speed=" << myVehicle.getSpeed()
1823 << " speedGainL=" << mySpeedGainProbabilityLeft / HYST_PRECISION
1824 << " speedGainR=" << mySpeedGainProbabilityRight / HYST_PRECISION
1825 << " thisLaneVSafe=" << thisLaneVSafe
1826 << " neighLaneVSafe=" << neighLaneVSafe
1827 << " relativeGain=" << relativeGain
1828 << " blocked=" << blocked
1829 << "\n";
1830 }
1831#endif
1832
1834 && neighDist / MAX2(.1, myVehicle.getSpeed()) > mySpeedGainRemainTime) { //./MAX2( .1, myVehicle.getSpeed())) { // -.1
1835 req = ret | lca | LCA_SPEEDGAIN;
1837 req |= LCA_URGENT;
1838 }
1839 if (!cancelRequest(req, laneOffset)) {
1840 return ret | req;
1841 }
1842 }
1843 } else {
1844 // ONLY FOR CHANGING TO THE LEFT
1845 if (thisLaneVSafe > neighLaneVSafe) {
1846 // this lane is better
1848 } else if (thisLaneVSafe == neighLaneVSafe) {
1850 } else {
1851 mySpeedGainProbabilityLeft += (long long int)(myVehicle.getActionStepLengthSecs() * relativeGain * HYST_PRECISION);
1852 }
1853 // VARIANT_19 (stayRight)
1854 //if (neighFollow.first != 0) {
1855 // MSVehicle* nv = neighFollow.first;
1856 // const double secGap = nv->getCarFollowModel().getSecureGap(nv, &myVehicle, nv->getSpeed(), myVehicle.getSpeed(), myVehicle.getCarFollowModel().getMaxDecel());
1857 // if (neighFollow.second < secGap * KEEP_RIGHT_HEADWAY) {
1858 // // do not change left if it would inconvenience faster followers
1859 // return ret | LCA_STAY | LCA_SPEEDGAIN;
1860 // }
1861 //}
1862
1863#ifdef DEBUG_WANTS_CHANGE
1864 if (DEBUG_COND) {
1865 std::cout << STEPS2TIME(currentTime)
1866 << " veh=" << myVehicle.getID()
1867 << " speed=" << myVehicle.getSpeed()
1868 << " speedGainL=" << mySpeedGainProbabilityLeft / HYST_PRECISION
1869 << " speedGainR=" << mySpeedGainProbabilityRight / HYST_PRECISION
1870 << " thisLaneVSafe=" << thisLaneVSafe
1871 << " neighLaneVSafe=" << neighLaneVSafe
1872 << " relativeGain=" << relativeGain
1873 << " blocked=" << blocked
1874 << "\n";
1875 }
1876#endif
1877
1879 && (relativeGain > NUMERICAL_EPS || changeLeftToAvoidOvertakeRight)
1880 && neighDist / MAX2(.1, myVehicle.getSpeed()) > mySpeedGainRemainTime) { // .1
1881 req = ret | lca | LCA_SPEEDGAIN;
1883 req |= LCA_URGENT;
1884 }
1885 if (!cancelRequest(req, laneOffset)) {
1886 if ((req & LCA_URGENT) && (blocked & LCA_BLOCKED_BY_LEFT_FOLLOWER)) {
1887 MSVehicle* nv = neighFollow.first;
1888 const bool hasBidiNeighFollower = neighLane.getBidiLane() != nullptr && MSLCHelper::isBidiFollower(&myVehicle, nv);
1889 if (nv != nullptr && !hasBidiNeighFollower) {
1890 const double helpSpeed = MAX2(nv->getCarFollowModel().minNextSpeed(nv->getSpeed(), nv), myVehicle.getSpeed() - 1);
1891 msgPass.informNeighFollower(new Info(helpSpeed, myLca | LCA_AMBLOCKINGFOLLOWER), &myVehicle);
1892 }
1893 }
1894 return ret | req;
1895 }
1896 }
1897 }
1898 // --------
1899 if (changeToBest && bestLaneOffset == curr.bestLaneOffset
1900 && myStrategicParam >= 0
1901 && relativeGain >= 0
1903 // change towards the correct lane, speedwise it does not hurt
1904 req = ret | lca | LCA_STRATEGIC;
1905 if (!cancelRequest(req, laneOffset)) {
1906 return ret | req;
1907 }
1908 }
1909#ifdef DEBUG_WANTS_CHANGE
1910 if (DEBUG_COND) {
1911 std::cout << STEPS2TIME(currentTime)
1912 << " veh=" << myVehicle.getID()
1913 << " speedGainL=" << mySpeedGainProbabilityLeft / HYST_PRECISION
1914 << " speedGainR=" << mySpeedGainProbabilityRight / HYST_PRECISION
1915 << " myKeepRightProbability=" << myKeepRightProbability / HYST_PRECISION
1916 << " thisLaneVSafe=" << thisLaneVSafe
1917 << " neighLaneVSafe=" << neighLaneVSafe
1918 << "\n";
1919 }
1920#endif
1921
1922 return ret;
1923}
1924
1925
1926double
1927MSLCM_LC2013::anticipateFollowSpeed(const std::pair<MSVehicle*, double>& leaderDist, double dist, double vMax, bool acceleratingLeader) {
1928 const MSVehicle* leader = leaderDist.first;
1929 const double gap = leaderDist.second;
1930 double futureSpeed;
1931 if (acceleratingLeader) {
1932 // XXX see #6562
1933 const double maxSpeed1s = (myVehicle.getSpeed() + myVehicle.getCarFollowModel().getMaxAccel()
1935 if (leader == nullptr) {
1936 if (hasBlueLight()) {
1937 // can continue from any lane if necessary
1938 futureSpeed = vMax;
1939 } else {
1940 futureSpeed = getCarFollowModel().followSpeed(&myVehicle, maxSpeed1s, dist, 0, 0);
1941 }
1942 } else {
1943 futureSpeed = getCarFollowModel().followSpeed(&myVehicle, maxSpeed1s, gap, leader->getSpeed(), leader->getCarFollowModel().getMaxDecel());
1944 }
1945 } else {
1946 // onInsertion = true because the vehicle has already moved
1947 if (leader == nullptr) {
1948 if (hasBlueLight()) {
1949 // can continue from any lane if necessary
1950 futureSpeed = vMax;
1951 } else {
1952 futureSpeed = getCarFollowModel().maximumSafeStopSpeed(dist, getCarFollowModel().getMaxDecel(), myVehicle.getSpeed(), true);
1953 }
1954 } else {
1955 futureSpeed = getCarFollowModel().maximumSafeFollowSpeed(gap, myVehicle.getSpeed(), leader->getSpeed(), leader->getCarFollowModel().getMaxDecel(), true);
1956 }
1957 }
1958 futureSpeed = MIN2(vMax, futureSpeed);
1959 if (leader != nullptr && gap > 0 && mySpeedGainLookahead > 0) {
1960 const double futureLeaderSpeed = acceleratingLeader ? leader->getLane()->getVehicleMaxSpeed(leader) : leader->getSpeed();
1961 const double deltaV = vMax - futureLeaderSpeed;
1962 if (deltaV > 0 && gap > 0) {
1963 const double secGap = getCarFollowModel().getSecureGap(&myVehicle, leader, futureSpeed, leader->getSpeed(), getCarFollowModel().getMaxDecel());
1964 const double fullSpeedGap = gap - secGap;
1965 if (fullSpeedGap / deltaV < mySpeedGainLookahead) {
1966 // anticipate future braking by computing the average
1967 // speed over the next few seconds
1968 const double gapClosingTime = MAX2(0.0, fullSpeedGap / deltaV);
1969 const double foreCastTime = mySpeedGainLookahead * 2;
1970 //if (DEBUG_COND) std::cout << SIMTIME << " veh=" << myVehicle.getID() << " leader=" << leader->getID() << " gap=" << gap << " deltaV=" << deltaV << " futureSpeed=" << futureSpeed << " futureLeaderSpeed=" << futureLeaderSpeed;
1971 futureSpeed = MIN2(futureSpeed, (gapClosingTime * futureSpeed + (foreCastTime - gapClosingTime) * futureLeaderSpeed) / foreCastTime);
1972 //if (DEBUG_COND) std::cout << " newFutureSpeed=" << futureSpeed << "\n";
1973 }
1974 }
1975 }
1976 return futureSpeed;
1977}
1978
1979
1980int
1982 // if this vehicle is blocking someone in front, we maybe decelerate to let him in
1983 if (blocked != nullptr) {
1985#ifdef DEBUG_SLOW_DOWN
1986 if (DEBUG_COND) {
1987 std::cout << SIMTIME
1988 << " veh=" << myVehicle.getID()
1989 << " blocked=" << Named::getIDSecure(blocked)
1990 << " gap=" << gap
1991 << "\n";
1992 }
1993#endif
1994 if (gap > POSITION_EPS) {
1995 //const bool blockedWantsUrgentRight = (((*blocked)->getLaneChangeModel().getOwnState() & LCA_RIGHT != 0)
1996 // && ((*blocked)->getLaneChangeModel().getOwnState() & LCA_URGENT != 0));
1997
1999 //|| blockedWantsUrgentRight // VARIANT_10 (helpblockedRight)
2000 ) {
2001 if (blocked->getSpeed() < SUMO_const_haltingSpeed) {
2003 } else {
2004 state |= LCA_AMBACKBLOCKER;
2005 }
2006 addLCSpeedAdvice(getCarFollowModel().followSpeed(
2008 gap - POSITION_EPS, blocked->getSpeed(),
2009 blocked->getCarFollowModel().getMaxDecel()), false);
2010
2011 //(*blocked) = 0; // VARIANT_14 (furtherBlock)
2012#ifdef DEBUG_SLOW_DOWN
2013 if (DEBUG_COND) {
2014 std::cout << SIMTIME
2015 << " veh=" << myVehicle.getID()
2016 << " slowing down for"
2017 << " blocked=" << Named::getIDSecure(blocked)
2018 << " helpSpeed=" << myLCAccelerationAdvices.back().first
2019 << "\n";
2020 }
2021#endif
2022 } /*else if ((*blocked)->getWaitingSeconds() > 30 && gap > myVehicle.getBrakeGap()) {
2023 // experimental else-branch...
2024
2025 state |= LCA_AMBACKBLOCKER;
2026 addLCSpeedAdvice(getCarFollowModel().followSpeed(
2027 &myVehicle, myVehicle.getSpeed(),
2028 (gap - POSITION_EPS), (*blocked)->getSpeed(),
2029 (*blocked)->getCarFollowModel().getMaxDecel()));
2030 } */
2031 }
2032 }
2033 return state;
2034}
2035
2036
2037void
2039 if (lane->hasPedestrians()) {
2040#ifdef DEBUG_WANTS_CHANGE
2041 if (DEBUG_COND) {
2042 std::cout << SIMTIME << " adapt to pedestrians on lane=" << lane->getID() << "\n";
2043 }
2044#endif
2048 if (leader.first != 0) {
2049 const double stopSpeed = myVehicle.getCarFollowModel().stopSpeed(&myVehicle, myVehicle.getSpeed(), leader.second - myVehicle.getVehicleType().getMinGap());
2050 v = MIN2(v, stopSpeed);
2051#ifdef DEBUG_WANTS_CHANGE
2052 if (DEBUG_COND) {
2053 std::cout << SIMTIME << " pedLeader=" << leader.first->getID() << " dist=" << leader.second << " v=" << v << "\n";
2054 }
2055#endif
2056 }
2057 }
2058}
2059
2060
2061double
2062MSLCM_LC2013::computeSpeedLat(double latDist, double& maneuverDist, bool urgent) const {
2063 double result = MSAbstractLaneChangeModel::computeSpeedLat(latDist, maneuverDist, urgent);
2064#ifdef DEBUG_WANTS_CHANGE
2065 if (DEBUG_COND) {
2066 std::cout << SIMTIME << " veh=" << myVehicle.getID() << " myLeftSpace=" << myLeftSpace << " latDist=" << latDist << " maneuverDist=" << maneuverDist << " result=" << result << "\n";
2067 }
2068#endif
2069 if (myLeftSpace > POSITION_EPS || !urgent) {
2071 if (isChangingLanes()) {
2072 speedBound = MAX2(LC_RESOLUTION_SPEED_LAT, speedBound);
2073 }
2074 result = MAX2(-speedBound, MIN2(speedBound, result));
2075 }
2076 return result;
2077}
2078
2079
2080double
2082 return 1 / myAssertive;
2083}
2084
2085double
2087 return myOppositeParam <= 0 ? std::numeric_limits<double>::max() : 1 / myOppositeParam;
2088}
2089
2090bool
2091MSLCM_LC2013::saveBlockerLength(double length, double foeLeftSpace) {
2092 const bool canReserve = MSLCHelper::canSaveBlockerLength(myVehicle, length, myLeftSpace);
2093 if (!isOpposite() && (canReserve || myLeftSpace > foeLeftSpace)) {
2095#ifdef DEBUG_SAVE_BLOCKER_LENGTH
2096 if (DEBUG_COND) {
2097 std::cout << SIMTIME << " saveBlockerLength veh=" << myVehicle.getID() << " canReserve=" << canReserve << " myLeftSpace=" << myLeftSpace << " foeLeftSpace=" << foeLeftSpace << "\n";
2098 }
2099#endif
2100 if (myLeftSpace == 0 && foeLeftSpace < 0) {
2101 // called from opposite overtaking, myLeftSpace must be initialized
2103 }
2104 return true;
2105 } else {
2106 return false;
2107 }
2108}
2109
2110
2111bool
2112MSLCM_LC2013::hasFreeLane(int laneOffset, const std::pair<MSVehicle*, double>& neighLeadStopped) const {
2113 if (neighLeadStopped.first == nullptr) {
2114 return true;
2115 }
2116 int dir = (laneOffset > 0 ? 1 : -1);
2117 const MSLane* neigh = myVehicle.getLane()->getParallelLane(laneOffset);
2118 if (dir > 0 && !neigh->allowsChangingLeft(myVehicle.getVClass())) {
2119 return false;
2120 } else if (dir < 0 && !neigh->allowsChangingRight(myVehicle.getVClass())) {
2121 return false;
2122 }
2123 int nextOffset = laneOffset + dir;
2124 const MSLane* next = myVehicle.getLane()->getParallelLane(nextOffset);
2125 if (next == nullptr || !next->allowsVehicleClass(myVehicle.getVClass())) {
2126 return false;
2127 }
2128 const double overtakeDist = neighLeadStopped.second + neighLeadStopped.first->getVehicleType().getLengthWithGap() + myVehicle.getLength() + POSITION_EPS;
2129 std::pair<MSVehicle* const, double> nextLead = next->getLeader(&myVehicle, myVehicle.getPositionOnLane(), myVehicle.getBestLanesContinuation(next), overtakeDist);
2130 return nextLead.first == nullptr || nextLead.second >= overtakeDist || hasFreeLane(nextOffset, nextLead);
2131}
2132
2133
2134std::string
2135MSLCM_LC2013::getParameter(const std::string& key) const {
2137 return toString(myStrategicParam);
2138 } else if (key == toString(SUMO_ATTR_LCA_COOPERATIVE_PARAM)) {
2140 } else if (key == toString(SUMO_ATTR_LCA_SPEEDGAIN_PARAM)) {
2141 return toString(mySpeedGainParam);
2142 } else if (key == toString(SUMO_ATTR_LCA_KEEPRIGHT_PARAM)) {
2143 return toString(myKeepRightParam);
2144 } else if (key == toString(SUMO_ATTR_LCA_OPPOSITE_PARAM)) {
2145 return toString(myOppositeParam);
2146 } else if (key == toString(SUMO_ATTR_LCA_LOOKAHEADLEFT)) {
2147 return toString(myLookaheadLeft);
2148 } else if (key == toString(SUMO_ATTR_LCA_SPEEDGAINRIGHT)) {
2149 return toString(mySpeedGainRight);
2150 } else if (key == toString(SUMO_ATTR_LCA_ASSERTIVE)) {
2151 return toString(myAssertive);
2152 } else if (key == toString(SUMO_ATTR_LCA_OVERTAKE_RIGHT)) {
2154 } else if (key == toString(SUMO_ATTR_LCA_SIGMA)) {
2155 return toString(mySigma);
2160 } else if (key == toString(SUMO_ATTR_LCA_STRATEGIC_LOOKAHEAD)) {
2162 } else if (key == toString(SUMO_ATTR_LCA_SPEEDGAIN_LOOKAHEAD)) {
2164 } else if (key == toString(SUMO_ATTR_LCA_SPEEDGAIN_REMAIN_TIME)) {
2168 } else if (key == toString(SUMO_ATTR_LCA_COOPERATIVE_SPEED)) {
2170 } else if (key == toString(SUMO_ATTR_LCA_MAXSPEEDLATSTANDING)) {
2172 } else if (key == toString(SUMO_ATTR_LCA_MAXSPEEDLATFACTOR)) {
2174 } else if (key == toString(SUMO_ATTR_LCA_MAXDISTLATSTANDING)) {
2176 // access to internal state for debugging in sumo-gui (not documented since it may change at any time)
2177 } else if (key == "speedGainProbabilityRight") {
2179 } else if (key == "speedGainProbabilityLeft") {
2181 } else if (key == "keepRightProbability") {
2183 } else if (key == "lookAheadSpeed") {
2184 return toString(myLookAheadSpeed);
2185 // motivation relative to threshold
2186 } else if (key == "speedGainRP") {
2188 } else if (key == "speedGainLP") {
2190 } else if (key == "keepRightP") {
2192 }
2193 throw InvalidArgument("Parameter '" + key + "' is not supported for laneChangeModel of type '" + toString(myModel) + "'");
2194}
2195
2196
2197void
2198MSLCM_LC2013::setParameter(const std::string& key, const std::string& value) {
2199 double doubleValue;
2200 try {
2201 doubleValue = StringUtils::toDouble(value);
2202 } catch (NumberFormatException&) {
2203 throw InvalidArgument("Setting parameter '" + key + "' requires a number for laneChangeModel of type '" + toString(myModel) + "'");
2204 }
2206 myStrategicParam = doubleValue;
2207 } else if (key == toString(SUMO_ATTR_LCA_COOPERATIVE_PARAM)) {
2208 myCooperativeParam = doubleValue;
2209 } else if (key == toString(SUMO_ATTR_LCA_SPEEDGAIN_PARAM)) {
2210 mySpeedGainParam = doubleValue;
2211 } else if (key == toString(SUMO_ATTR_LCA_KEEPRIGHT_PARAM)) {
2212 myKeepRightParam = doubleValue;
2213 } else if (key == toString(SUMO_ATTR_LCA_OPPOSITE_PARAM)) {
2214 myOppositeParam = doubleValue;
2215 } else if (key == toString(SUMO_ATTR_LCA_LOOKAHEADLEFT)) {
2216 myLookaheadLeft = doubleValue;
2217 } else if (key == toString(SUMO_ATTR_LCA_SPEEDGAINRIGHT)) {
2218 mySpeedGainRight = doubleValue;
2219 } else if (key == toString(SUMO_ATTR_LCA_ASSERTIVE)) {
2220 myAssertive = doubleValue;
2221 } else if (key == toString(SUMO_ATTR_LCA_OVERTAKE_RIGHT)) {
2222 myOvertakeRightParam = doubleValue;
2223 } else if (key == toString(SUMO_ATTR_LCA_SIGMA)) {
2224 mySigma = doubleValue;
2226 myKeepRightAcceptanceTime = doubleValue;
2228 myOvertakeDeltaSpeedFactor = doubleValue;
2229 } else if (key == toString(SUMO_ATTR_LCA_STRATEGIC_LOOKAHEAD)) {
2230 myStrategicLookahead = doubleValue;
2231 } else if (key == toString(SUMO_ATTR_LCA_SPEEDGAIN_LOOKAHEAD)) {
2232 mySpeedGainLookahead = doubleValue;
2233 } else if (key == toString(SUMO_ATTR_LCA_SPEEDGAIN_REMAIN_TIME)) {
2234 mySpeedGainRemainTime = doubleValue;
2236 myRoundaboutBonus = doubleValue;
2237 } else if (key == toString(SUMO_ATTR_LCA_COOPERATIVE_SPEED)) {
2238 myCooperativeSpeed = doubleValue;
2239 } else if (key == toString(SUMO_ATTR_LCA_MAXSPEEDLATSTANDING)) {
2240 myMaxSpeedLatStanding = doubleValue;
2241 } else if (key == toString(SUMO_ATTR_LCA_MAXSPEEDLATFACTOR)) {
2242 myMaxSpeedLatFactor = doubleValue;
2243 } else if (key == toString(SUMO_ATTR_LCA_MAXDISTLATSTANDING)) {
2244 myMaxDistLatStanding = doubleValue;
2245 // access to internal state
2246 } else if (key == "speedGainProbabilityRight") {
2247 mySpeedGainProbabilityRight = (long long int)(doubleValue * HYST_PRECISION);
2248 } else if (key == "speedGainProbabilityLeft") {
2249 mySpeedGainProbabilityLeft = (long long int)(doubleValue * HYST_PRECISION);
2250 } else if (key == "keepRightProbability") {
2251 myKeepRightProbability = (long long int)(-doubleValue * HYST_PRECISION);
2252 } else if (key == "lookAheadSpeed") {
2253 myLookAheadSpeed = doubleValue;
2254 } else {
2255 throw InvalidArgument("Setting parameter '" + key + "' is not supported for laneChangeModel of type '" + toString(myModel) + "'");
2256 }
2258}
2259
2260
2261void
2264 std::vector<long long int> lcState;
2265 lcState.push_back(mySpeedGainProbabilityLeft);
2266 lcState.push_back(mySpeedGainProbabilityRight);
2267 lcState.push_back(myKeepRightProbability);
2268 lcState.push_back((long long int)(myLookAheadSpeed * HYST_PRECISION));
2269 lcState.push_back(myDontBrake);
2270 out.writeAttr(SUMO_ATTR_LCSTATE2, lcState);
2271}
2272
2273
2274void
2277 if (attrs.hasAttribute(SUMO_ATTR_LCSTATE2)) {
2278 std::istringstream bis(attrs.getString(SUMO_ATTR_LCSTATE2));
2282 long long laSpeed;
2283 bis >> laSpeed;
2284 myLookAheadSpeed = (double)laSpeed / HYST_PRECISION;
2285 bis >> myDontBrake;
2286 }
2287}
2288
2289
2290
2291/****************************************************************************/
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
virtual bool isSelected() const
whether this vehicle is selected in the GUI
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:59
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:103
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:277
double brakeGap(const double speed) const
Returns the distance the vehicle needs to halt including driver's reaction time tau (i....
Definition MSCFModel.h:424
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:285
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:189
const std::set< MSTransportable *, ComparatorNumericalIdLess > & getPersons() const
Returns this edge's persons set.
Definition MSEdge.h:204
bool hasLaneChanger() const
Definition MSEdge.h:759
bool isRoundabout() const
Definition MSEdge.h:742
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:4614
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:2888
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:602
double getLength() const
Returns the lane's length.
Definition MSLane.h:632
bool allowsChangingLeft(SUMOVehicleClass vclass) const
Returns whether the given vehicle class may change left from this lane.
Definition MSLane.h:963
bool allowsVehicleClass(SUMOVehicleClass vclass) const
Definition MSLane.h:956
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:4607
int getIndex() const
Returns the lane's index.
Definition MSLane.h:668
double getBruttoOccupancy() const
Returns the brutto (including minGaps) occupancy of this lane during the last step.
Definition MSLane.cpp:3434
bool isNormal() const
Definition MSLane.cpp:2658
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:2957
MSLane * getBidiLane() const
retrieve bidirectional lane or nullptr
Definition MSLane.cpp:4719
MSEdge & getEdge() const
Returns the lane's edge.
Definition MSLane.h:790
const MSLane * getNormalPredecessorLane() const
get normal lane leading to this internal lane, for normal lanes, the lane itself is returned
Definition MSLane.cpp:3279
const std::vector< MSLink * > & getLinkCont() const
returns the container with all links !!!
Definition MSLane.h:750
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:1042
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:973
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:66
const std::string & getID() const
Returns the id.
Definition Named.h:73
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, const bool escape=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:861
double length
The overall length which may be driven when using this lane without a lane change.
Definition MSVehicle.h:865
std::vector< MSLane * > bestContinuations
Definition MSVehicle.h:881
MSLane * lane
The described lane.
Definition MSVehicle.h:863
int bestLaneOffset
The (signed) number of lanes to be crossed to get to the lane which allows to continue the drive.
Definition MSVehicle.h:873
double occupation
The overall vehicle sum on consecutive lanes which can be passed without a lane change.
Definition MSVehicle.h:869