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)
550 // not enough space to overtake?
552 // using brakeGap() without headway seems adequate in a situation where the obstacle (the lane end) is not moving [XXX implemented in branch ticket860, can be used in general if desired, refs. #2575] (Leo).
554 // not enough time to overtake? (skipped for a stopped leader [currently only for ballistic update XXX: check if appropriate for euler, too, refs. #2575] to ensure that it can be overtaken if only enough space is exists) (Leo)
555 || (remainingSeconds < overtakeTime && (MSGlobals::gSemiImplicitEulerUpdate || !nv->isStopped())))
556 // opposite driving and must overtake
557 && (!neighLead.first->isStopped() || (isOpposite() && neighLead.second >= 0))) {
558 // cannot overtake
559 msgPass.informNeighLeader(new Info(std::numeric_limits<double>::max(), dir | LCA_AMBLOCKINGLEADER), &myVehicle);
560 // slow down smoothly to follow leader
561 // account for minor decelerations by the leader (dawdling)
563 getCarFollowModel().followSpeed(&myVehicle, myVehicle.getSpeed(), neighNextGap, neighNextSpeed, nv->getCarFollowModel().getMaxDecel()),
564 // avoid changing on intersection
566 if (targetSpeed < myVehicle.getSpeed()) {
567 // slow down smoothly to follow leader
568 const double decel = remainingSeconds == 0. ? myVehicle.getCarFollowModel().getMaxDecel() :
570 MAX2(MIN_FALLBEHIND, (myVehicle.getSpeed() - targetSpeed) / remainingSeconds));
571 const double nextSpeed = MIN2(plannedSpeed, MAX2(0.0, myVehicle.getSpeed() - ACCEL2SPEED(decel)));
572#ifdef DEBUG_INFORMER
573 if (DEBUG_COND) {
574 std::cout << SIMTIME
575 << " cannot overtake leader nv=" << nv->getID()
576 << " dv=" << dv
577 << " myLookAheadSpeed=" << myLookAheadSpeed
578 << " myLeftSpace=" << myLeftSpace
579 << " overtakeDist=" << overtakeDist
580 << " overtakeTime=" << overtakeTime
581 << " remainingSeconds=" << remainingSeconds
582 << " currentGap=" << neighLead.second
583 << " brakeGap=" << myVehicle.getCarFollowModel().brakeGap(myVehicle.getSpeed(), getCarFollowModel().getMaxDecel(), 0.)
584 << " neighNextSpeed=" << neighNextSpeed
585 << " neighNextGap=" << neighNextGap
586 << " targetSpeed=" << targetSpeed
587 << " nextSpeed=" << nextSpeed
588 << "\n";
589 }
590#endif
591 addLCSpeedAdvice(nextSpeed);
592 return nextSpeed;
593 } else {
594 // leader is fast enough anyway
595#ifdef DEBUG_INFORMER
596 if (DEBUG_COND) {
597 std::cout << SIMTIME
598 << " cannot overtake fast leader nv=" << nv->getID()
599 << " dv=" << dv
600 << " myLookAheadSpeed=" << myLookAheadSpeed
601 << " myLeftSpace=" << myLeftSpace
602 << " overtakeDist=" << overtakeDist
603 << " myLeadingBlockerLength=" << myLeadingBlockerLength
604 << " overtakeTime=" << overtakeTime
605 << " remainingSeconds=" << remainingSeconds
606 << " currentGap=" << neighLead.second
607 << " neighNextSpeed=" << neighNextSpeed
608 << " neighNextGap=" << neighNextGap
609 << " targetSpeed=" << targetSpeed
610 << "\n";
611 }
612#endif
613 addLCSpeedAdvice(targetSpeed);
614 return plannedSpeed;
615 }
616 } else {
617 // overtaking, leader should not accelerate
618#ifdef DEBUG_INFORMER
619 if (DEBUG_COND) {
620 std::cout << SIMTIME
621 << " wants to overtake leader nv=" << nv->getID()
622 << " dv=" << dv
623 << " overtakeDist=" << overtakeDist
624 << " remainingSeconds=" << remainingSeconds
625 << " overtakeTime=" << overtakeTime
626 << " currentGap=" << neighLead.second
628 << "\n";
629 }
630#endif
631 // no need to pass a message if the neighbor is waiting/stuck anyway (but sending it would risk deadlock)
633 msgPass.informNeighLeader(new Info(nv->getSpeed(), dir | LCA_AMBLOCKINGLEADER), &myVehicle);
634 }
635 return -1; // XXX: using -1 is ambiguous for the ballistic update! Currently this is being catched in patchSpeed() (Leo), consider returning INVALID_SPEED, refs. #2577
636 }
637 } else { // (remainUnblocked)
638 // we are not blocked now. make sure we stay far enough from the leader
639 const double targetSpeed = MAX2(
641 getCarFollowModel().followSpeed(&myVehicle, myVehicle.getSpeed(), neighNextGap, neighNextSpeed, nv->getCarFollowModel().getMaxDecel()));
642 addLCSpeedAdvice(targetSpeed);
643#ifdef DEBUG_INFORMER
644 if (DEBUG_COND) {
645 std::cout << " not blocked by leader nv=" << nv->getID()
646 << " nvSpeed=" << nv->getSpeed()
647 << " gap=" << neighLead.second
648 << " neighNextSpeed=" << neighNextSpeed
649 << " neighNextGap=" << neighNextGap
651 << " targetSpeed=" << targetSpeed
652 << "\n";
653 }
654#endif
655 return MIN2(targetSpeed, plannedSpeed);
656 }
657}
658
659void
661 int blocked,
662 int dir,
663 const std::pair<MSVehicle*, double>& neighFollow,
664 double remainingSeconds,
665 double plannedSpeed) {
666
667 MSVehicle* nv = neighFollow.first;
668 const double plannedAccel = SPEED2ACCEL(MAX2(MIN2(getCarFollowModel().getMaxAccel(), plannedSpeed - myVehicle.getSpeed()), -getCarFollowModel().getMaxDecel()));
669
670#ifdef DEBUG_INFORMER
671 if (DEBUG_COND) {
672 std::cout << "\nINFORM_FOLLOWER"
673 << "\nspeed=" << myVehicle.getSpeed() << " planned=" << plannedSpeed << "\n";
674 }
675
676#endif
677 if ((blocked & LCA_BLOCKED_BY_FOLLOWER) != 0 && nv != nullptr) {
679 //std::cout << SIMTIME << " ego=" << myVehicle.getID() << " ignoresDivergentBlockingFollower=" << nv->getID() << "\n";
680 return;
681 }
682#ifdef DEBUG_INFORMER
683 if (DEBUG_COND) {
684 std::cout << " blocked by follower nv=" << nv->getID() << " nvSpeed=" << nv->getSpeed() << " needGap="
685 << nv->getCarFollowModel().getSecureGap(nv, &myVehicle, nv->getSpeed(), myVehicle.getSpeed(), myVehicle.getCarFollowModel().getMaxDecel()) << " planned=" << plannedSpeed << "\n";
686 }
687#endif
688
689 // are we fast enough to cut in without any help?
690 if (MAX2(plannedSpeed, 0.) - nv->getSpeed() >= HELP_OVERTAKE) {
691 const double neededGap = nv->getCarFollowModel().getSecureGap(nv, &myVehicle, nv->getSpeed(), plannedSpeed, myVehicle.getCarFollowModel().getMaxDecel());
692 if ((neededGap - neighFollow.second) / remainingSeconds < (MAX2(plannedSpeed, 0.) - nv->getSpeed())) {
693#ifdef DEBUG_INFORMER
694 if (DEBUG_COND) {
695 std::cout << " wants to cut in before nv=" << nv->getID() << " without any help." << "\nneededGap = " << neededGap << "\n";
696 }
697#endif
698 // follower might even accelerate but not to much
699 // XXX: I don't understand this. The needed gap was determined for nv->getSpeed(), not for (plannedSpeed - HELP_OVERTAKE)?! (Leo), refs. #2578
700 msgPass.informNeighFollower(new Info(MAX2(plannedSpeed, 0.) - HELP_OVERTAKE, dir | LCA_AMBLOCKINGFOLLOWER), &myVehicle);
701 return;
702 }
703 }
704
705 // decide whether we will request help to cut in before the follower or allow to be overtaken
706
707 // PARAMETERS
708 // assume other vehicle will assume the equivalent of 1 second of
709 // maximum deceleration to help us (will probably be spread over
710 // multiple seconds)
711 // -----------
712 const double helpDecel = nv->getCarFollowModel().getMaxDecel() * HELP_DECEL_FACTOR;
713
714 // follower's new speed in next step
715 double neighNewSpeed;
716 // follower's new speed after 1s.
717 double neighNewSpeed1s;
718 // velocity difference, gap after follower-deceleration
719 double dv, decelGap;
720
722 // euler
723 neighNewSpeed = MAX2(0., nv->getSpeed() - ACCEL2SPEED(helpDecel));
724 neighNewSpeed1s = MAX2(0., nv->getSpeed() - helpDecel); // TODO: consider introduction of a configurable anticipationTime here (see far below in the !blocked part). Refs. #2578
725 // change in the gap between ego and blocker over 1 second (not STEP!)
726 // XXX: though here it is calculated as if it were one step!? (Leo) Refs. #2578
727 dv = plannedSpeed - neighNewSpeed1s; // XXX: what is this quantity (if TS!=1)?
728 // new gap between follower and self in case the follower does brake for 1s
729 // XXX: if the step-length is not 1s., this is not the gap after 1s. deceleration!
730 // And this formula overestimates the real gap. Isn't that problematic? (Leo)
731 // Below, it seems that decelGap > secureGap is taken to indicate the possibility
732 // to cut in within the next time-step. However, this is not the case, if TS<1s.,
733 // since decelGap is (not exactly, though!) the gap after 1s. Refs. #2578
734 decelGap = neighFollow.second + dv;
735 } else {
736 // ballistic
737 // negative newSpeed-extrapolation possible, if stop lies within the next time-step
738 // XXX: this code should work for the euler case as well, since gapExtrapolation() takes
739 // care of this, but for TS!=1 we will have different behavior (see previous remark) Refs. #2578
740 neighNewSpeed = nv->getSpeed() - ACCEL2SPEED(helpDecel);
741 neighNewSpeed1s = nv->getSpeed() - helpDecel;
742
743 dv = myVehicle.getSpeed() - nv->getSpeed(); // current velocity difference
744 decelGap = getCarFollowModel().gapExtrapolation(1., neighFollow.second, myVehicle.getSpeed(),
745 nv->getSpeed(), plannedAccel, -helpDecel, myVehicle.getMaxSpeedOnLane(), nv->getMaxSpeedOnLane());
746 }
747
748 const double secureGap = nv->getCarFollowModel().getSecureGap(nv, &myVehicle, MAX2(neighNewSpeed1s, 0.),
749 MAX2(plannedSpeed, 0.), myVehicle.getCarFollowModel().getMaxDecel());
750
751 const double onRampThreshold = myVehicle.getLane()->getSpeedLimit() * 0.8 * myExperimentalParam1 * (1 - myVehicle.getImpatience());
752
753#ifdef DEBUG_INFORMER
754 if (DEBUG_COND) {
755 std::cout << SIMTIME
756 << " speed=" << myVehicle.getSpeed()
757 << " plannedSpeed=" << plannedSpeed
758 << " threshold=" << onRampThreshold
759 << " neighNewSpeed=" << neighNewSpeed
760 << " neighNewSpeed1s=" << neighNewSpeed1s
761 << " dv=" << dv
762 << " gap=" << neighFollow.second
763 << " decelGap=" << decelGap
764 << " secureGap=" << secureGap
765 << "\n";
766 }
767#endif
768 // prevent vehicles on an on ramp stopping the main flow
769 if (dir == LCA_MLEFT
771 && neighNewSpeed1s < onRampThreshold) {
772 return;
773 }
774
775 if (decelGap > 0 && decelGap >= secureGap) {
776 // XXX: This does not assure that the leader can cut in in the next step if TS < 1 (see above)
777 // this seems to be supposed in the following (euler code)...?! (Leo) Refs. #2578
778
779 // if the blocking follower brakes it could help
780 // how hard does it actually need to be?
781 // to be safe in the next step the following equation has to hold for the follower's vsafe:
782 // vsafe <= followSpeed(gap=currentGap - SPEED2DIST(vsafe), ...)
783 double vsafe, vsafe1;
784
786 // euler
787 // we compute an upper bound on vsafe by doing the computation twice
788 vsafe1 = MAX2(neighNewSpeed, nv->getCarFollowModel().followSpeed(
789 nv, nv->getSpeed(), neighFollow.second + SPEED2DIST(plannedSpeed), plannedSpeed, getCarFollowModel().getMaxDecel()));
790 vsafe = MAX2(neighNewSpeed, nv->getCarFollowModel().followSpeed(
791 nv, nv->getSpeed(), neighFollow.second + SPEED2DIST(plannedSpeed - vsafe1), plannedSpeed, getCarFollowModel().getMaxDecel()));
792 //assert(vsafe <= vsafe1); assertion does not hold for models with randomness in followSpeed (W99)
793 } else {
794 // ballistic
795
796 // XXX: This block should actually do as well for euler update (TODO: test!), refs #2575
797 // we compute an upper bound on vsafe
798 // next step's gap without help deceleration (nv's speed assumed constant)
799 double nextGap = getCarFollowModel().gapExtrapolation(TS,
800 neighFollow.second, myVehicle.getSpeed(),
801 nv->getSpeed(), plannedAccel, 0,
803#ifdef DEBUG_INFORMER
804 if (DEBUG_COND) {
805 std::cout << "nextGap=" << nextGap << " (without help decel) \n";
806 }
807#endif
808
809 // NOTE: the second argument of MIN2() can get larger than nv->getSpeed()
810 vsafe1 = MIN2(nv->getSpeed(), MAX2(neighNewSpeed,
812 nv->getSpeed(), nextGap,
813 MAX2(0., plannedSpeed),
814 getCarFollowModel().getMaxDecel())));
815
816
817 // next step's gap with possibly less than maximal help deceleration (in case vsafe1 > neighNewSpeed)
818 double decel2 = SPEED2ACCEL(nv->getSpeed() - vsafe1);
820 neighFollow.second, myVehicle.getSpeed(),
821 nv->getSpeed(), plannedAccel, -decel2,
823
824 // vsafe = MAX(neighNewSpeed, safe speed assuming next_gap)
825 // Thus, the gap resulting from vsafe is larger or equal to next_gap
826 // in contrast to the euler case, where nv's follow speed doesn't depend on the actual speed,
827 // we need to assure, that nv doesn't accelerate
828 vsafe = MIN2(nv->getSpeed(), MAX2(neighNewSpeed,
830 nv->getSpeed(), nextGap,
831 MAX2(0., plannedSpeed),
832 getCarFollowModel().getMaxDecel())));
833
834 assert(vsafe >= vsafe1 - NUMERICAL_EPS);
835
836#ifdef DEBUG_INFORMER
837 if (DEBUG_COND) {
838 std::cout << "nextGap=" << nextGap
839 << " (with vsafe1 and help decel) \nvsafe1=" << vsafe1
840 << " vsafe=" << vsafe
841 << "\n";
842 }
843#endif
844
845 // For subsecond simulation, this might not lead to secure gaps for a long time,
846 // we seek to establish a secure gap as soon as possible
847 double nextSecureGap = nv->getCarFollowModel().getSecureGap(nv, &myVehicle, vsafe, plannedSpeed, getCarFollowModel().getMaxDecel());
848
849 if (nextGap < nextSecureGap) {
850 // establish a secureGap as soon as possible
851 vsafe = neighNewSpeed;
852 }
853
854#ifdef DEBUG_INFORMER
855 if (DEBUG_COND) {
856 std::cout << "nextGap=" << nextGap
857 << " minNextSecureGap=" << nextSecureGap
858 << " vsafe=" << vsafe << "\n";
859 }
860#endif
861
862 }
863 msgPass.informNeighFollower(
864 new Info(vsafe, dir | LCA_AMBLOCKINGFOLLOWER), &myVehicle);
865
866#ifdef DEBUG_INFORMER
867 if (DEBUG_COND) {
868 std::cout << " wants to cut in before nv=" << nv->getID()
869 << " vsafe1=" << vsafe1 << " vsafe=" << vsafe
870 << " newSecGap="
871 << nv->getCarFollowModel().getSecureGap(nv, &myVehicle, vsafe,
872 plannedSpeed,
874 << "\n";
875 }
876#endif
877 } else if ((MSGlobals::gSemiImplicitEulerUpdate && dv > 0 && dv * remainingSeconds > (secureGap - decelGap + POSITION_EPS))
878 || (!MSGlobals::gSemiImplicitEulerUpdate && dv > 0 && dv * (remainingSeconds - 1) > secureGap - decelGap + POSITION_EPS)
879 ) {
880
881 // XXX: Alternative formulation (encapsulating differences of euler and ballistic) TODO: test, refs. #2575
882 // double eventualGap = getCarFollowModel().gapExtrapolation(remainingSeconds - 1., decelGap, plannedSpeed, neighNewSpeed1s);
883 // } else if (eventualGap > secureGap + POSITION_EPS) {
884
885
886 // NOTE: This case corresponds to the situation, where some time is left to perform the lc
887 // For the ballistic case this is interpreted as follows:
888 // If the follower breaks with helpDecel for one second, this vehicle maintains the plannedSpeed,
889 // and both continue with their speeds for remainingSeconds seconds the gap will suffice for a laneChange
890 // For the euler case we had the following comment:
891 // 'decelerating once is sufficient to open up a large enough gap in time', but:
892 // XXX: 1) Decelerating *once* does not necessarily lead to the gap decelGap! (if TS<1s.) (Leo)
893 // 2) Probably, the if() for euler should test for dv * (remainingSeconds-1) > ..., too ?!, refs. #2578
894 msgPass.informNeighFollower(new Info(neighNewSpeed, dir | LCA_AMBLOCKINGFOLLOWER), &myVehicle);
895#ifdef DEBUG_INFORMER
896 if (DEBUG_COND) {
897 std::cout << " wants to cut in before nv=" << nv->getID() << " (eventually)\n";
898 }
899#endif
900 } else if (dir == LCA_MRIGHT && !myAllowOvertakingRight && !nv->congested()) {
901 // XXX: check if this requires a special treatment for the ballistic update, refs. #2575
902 const double vhelp = MAX2(neighNewSpeed, HELP_OVERTAKE);
903 msgPass.informNeighFollower(new Info(vhelp, dir | LCA_AMBLOCKINGFOLLOWER), &myVehicle);
904#ifdef DEBUG_INFORMER
905 if (DEBUG_COND) {
906 std::cout << " wants to cut in before nv=" << nv->getID() << " (nv cannot overtake right)\n";
907 }
908#endif
909 } else {
910 double vhelp = MAX2(nv->getSpeed(), myVehicle.getSpeed() + HELP_OVERTAKE);
911 //if (dir == LCA_MRIGHT && myVehicle.getWaitingSeconds() > LCA_RIGHT_IMPATIENCE &&
912 // nv->getSpeed() > myVehicle.getSpeed()) {
913 if (nv->getSpeed() > myVehicle.getSpeed() &&
914 ((dir == LCA_MRIGHT && myVehicle.getWaitingSeconds() > LCA_RIGHT_IMPATIENCE) // NOTE: it might be considered to use myVehicle.getAccumulatedWaitingSeconds() > LCA_RIGHT_IMPATIENCE instead (Leo). Refs. #2578
915 || (dir == LCA_MLEFT && plannedSpeed > CUT_IN_LEFT_SPEED_THRESHOLD) // VARIANT_22 (slowDownLeft)
916 // XXX this is a hack to determine whether the vehicles is on an on-ramp. This information should be retrieved from the network itself
918 )) {
919 // let the follower slow down to increase the likelihood that later vehicles will be slow enough to help
920 // follower should still be fast enough to open a gap
921 // XXX: The probability for that success would be larger if the slow down of the appropriate following vehicle
922 // would take place without the immediate follower slowing down. We might consider to model reactions of
923 // vehicles that are not immediate followers. (Leo) -> see ticket #2532
924 vhelp = MAX2(neighNewSpeed, myVehicle.getSpeed() + HELP_OVERTAKE);
925#ifdef DEBUG_INFORMER
926 if (DEBUG_COND) {
927 // NOTE: the condition labeled "VARIANT_22" seems to imply that this could as well concern the *left* follower?! (Leo)
928 // Further, vhelp might be larger than nv->getSpeed(), so the request issued below is not to slow down!? (see below) Refs. #2578
929 std::cout << " wants right follower to slow down a bit\n";
930 }
931#endif
933 // euler
934 if ((nv->getSpeed() - myVehicle.getSpeed()) / helpDecel < remainingSeconds) {
935
936#ifdef DEBUG_INFORMER
937 if (DEBUG_COND) {
938 // NOTE: the condition labeled "VARIANT_22" seems to imply that this could as well concern the *left* follower?! Refs. #2578
939 std::cout << " wants to cut in before right follower nv=" << nv->getID() << " (eventually)\n";
940 }
941#endif
942 // XXX: I don't understand. This vhelp might be larger than nv->getSpeed() but the above condition seems to rely
943 // on the reasoning that if nv breaks with helpDecel for remaining Seconds, nv will be so slow, that this
944 // vehicle will be able to cut in. But nv might have overtaken this vehicle already (or am I missing sth?). (Leo)
945 // Ad: To my impression, the intention behind allowing larger speeds for the blocking follower is to prevent a
946 // situation, where an overlapping follower keeps blocking the ego vehicle. Refs. #2578
947 msgPass.informNeighFollower(new Info(vhelp, dir | LCA_AMBLOCKINGFOLLOWER), &myVehicle);
948 return;
949 }
950 } else {
951
952 // ballistic (this block is a bit different to the logic in the euler part, but in general suited to work on euler as well.. must be tested <- TODO, refs. #2575)
953 // estimate gap after remainingSeconds.
954 // Assumptions:
955 // (A1) leader continues with currentSpeed. (XXX: That might be wrong: Think of accelerating on an on-ramp or of a congested region ahead!)
956 // (A2) follower breaks with helpDecel.
957 const double gapAfterRemainingSecs = getCarFollowModel().gapExtrapolation(
958 remainingSeconds, neighFollow.second, myVehicle.getSpeed(), nv->getSpeed(), 0, -helpDecel, myVehicle.getMaxSpeedOnLane(), nv->getMaxSpeedOnLane());
959 const double secureGapAfterRemainingSecs = nv->getCarFollowModel().getSecureGap(nv, &myVehicle,
960 MAX2(nv->getSpeed() - remainingSeconds * helpDecel, 0.), myVehicle.getSpeed(), myVehicle.getCarFollowModel().getMaxDecel());
961 if (gapAfterRemainingSecs >= secureGapAfterRemainingSecs) { // XXX: here it would be wise to check whether there is enough space for eventual braking if the maneuver doesn't succeed
962#ifdef DEBUG_INFORMER
963 if (DEBUG_COND) {
964 std::cout << " wants to cut in before follower nv=" << nv->getID() << " (eventually)\n";
965 }
966#endif
967 // NOTE: ballistic uses neighNewSpeed instead of vhelp, see my note above. (Leo)
968 // TODO: recheck if this might cause suboptimal behaviour in some LC-situations. Refs. #2578
969 msgPass.informNeighFollower(new Info(neighNewSpeed, dir | LCA_AMBLOCKINGFOLLOWER), &myVehicle);
970 return;
971 }
972 }
973
974
975 }
976
977#ifdef DEBUG_INFORMER
978 if (DEBUG_COND) {
979 std::cout << SIMTIME
980 << " veh=" << myVehicle.getID()
981 << " informs follower " << nv->getID()
982 << " vhelp=" << vhelp
983 << "\n";
984 }
985#endif
986
987 msgPass.informNeighFollower(new Info(vhelp, dir | LCA_AMBLOCKINGFOLLOWER), &myVehicle);
988 // This follower is supposed to overtake us. Slow down smoothly to allow this.
989 const double overtakeDist = overtakeDistance(nv, &myVehicle, neighFollow.second, vhelp, plannedSpeed);
990 // speed difference to create a sufficiently large gap
991 const double needDV = overtakeDist / remainingSeconds;
992 // make sure the deceleration is not to strong (XXX: should be assured in finalizeSpeed -> TODO: remove the MAX2 if agreed) -> prob with possibly non-existing maximal deceleration for som CF Models(?) Refs. #2578
994
995#ifdef DEBUG_INFORMER
996 if (DEBUG_COND) {
997 std::cout << SIMTIME
998 << " veh=" << myVehicle.getID()
999 << " wants to be overtaken by=" << nv->getID()
1000 << " overtakeDist=" << overtakeDist
1001 << " vneigh=" << nv->getSpeed()
1002 << " vhelp=" << vhelp
1003 << " needDV=" << needDV
1004 << " vsafe=" << myLCAccelerationAdvices.back().first
1005 << "\n";
1006 }
1007#endif
1008 }
1009 } else if (neighFollow.first != nullptr && (blocked & LCA_BLOCKED_BY_LEADER)) {
1010 // we are not blocked by the follower now, make sure it remains that way
1011 const double vsafe = MSLCHelper::getSpeedPreservingSecureGap(myVehicle, *neighFollow.first, neighFollow.second, plannedSpeed);
1012 msgPass.informNeighFollower(new Info(vsafe, dir), &myVehicle);
1013
1014#ifdef DEBUG_INFORMER
1015 if (DEBUG_COND) {
1016 std::cout << " wants to cut in before non-blocking follower nv=" << nv->getID() << "\n";
1017 }
1018#endif
1019 }
1020}
1021
1022
1023void
1026 // keep information about strategic change direction
1027 if (!isChangingLanes()) {
1029 }
1031 myLeftSpace = 0;
1033 myDontBrake = false;
1034 // truncate to work around numerical instability between different builds
1035 if (mySigma > 0 && !isChangingLanes()) {
1036 // disturb lateral position directly
1037 const double maxDist = SPEED2DIST(myVehicle.getVehicleType().getMaxSpeedLat());
1038 const double oldPosLat = myVehicle.getLateralPositionOnLane();
1039 const double overlap = myVehicle.getLateralOverlap();
1040 double scaledDelta;
1041 if (overlap > 0) {
1042 // return to within lane boundary
1043 scaledDelta = MIN2(overlap, maxDist);
1045 scaledDelta *= -1;
1046 }
1047 } else {
1048 // random drift
1049 double deltaPosLat = OUProcess::step(oldPosLat,
1051 MAX2(NUMERICAL_EPS, (1 - mySigma) * 100), mySigma) - oldPosLat;
1052 deltaPosLat = MAX2(MIN2(deltaPosLat, maxDist), -maxDist);
1053 scaledDelta = deltaPosLat * myVehicle.getSpeed() / myVehicle.getLane()->getSpeedLimit();
1054 }
1055 myVehicle.setLateralPositionOnLane(oldPosLat + scaledDelta);
1056 setSpeedLat(DIST2SPEED(scaledDelta));
1057 } else {
1058 resetSpeedLat();
1059 }
1060}
1061
1062
1063void
1065 myOwnState = 0;
1069 if (myVehicle.getBestLaneOffset() == 0) {
1070 // if we are not yet on our best lane there might still be unseen blockers
1071 // (during patchSpeed)
1073 myLeftSpace = 0;
1074 }
1077 myDontBrake = false;
1079}
1080
1081
1082void
1094
1095
1096int
1098 int laneOffset,
1100 int blocked,
1101 const std::pair<MSVehicle*, double>& leader,
1102 const std::pair<MSVehicle*, double>& follower,
1103 const std::pair<MSVehicle*, double>& neighLead,
1104 const std::pair<MSVehicle*, double>& neighFollow,
1105 const MSLane& neighLane,
1106 const std::vector<MSVehicle::LaneQ>& preb,
1107 MSVehicle* lastBlocked,
1108 MSVehicle* firstBlocked) {
1109 assert(laneOffset == 1 || laneOffset == -1);
1110 const SUMOTime currentTime = MSNet::getInstance()->getCurrentTimeStep();
1111 // compute bestLaneOffset
1112 MSVehicle::LaneQ curr, neigh, best;
1113 int bestLaneOffset = 0;
1114 // What do these "dists" mean? Please comment. (Leo) Ad: I now think the following:
1115 // currentDist is the distance that the vehicle can go on its route without having to
1116 // change lanes from the current lane. neighDist as currentDist for the considered target lane (i.e., neigh)
1117 // If this is true I suggest to put this into the docu of wantsChange()
1118 double currentDist = 0;
1119 double neighDist = 0;
1120 int currIdx = 0;
1121 const bool checkOpposite = &neighLane.getEdge() != &myVehicle.getLane()->getEdge();
1122 const MSLane* prebLane = myVehicle.getLane();
1123 if (prebLane->getEdge().isInternal()) {
1124 // internal edges are not kept inside the bestLanes structure
1125 if (isOpposite()) {
1126 prebLane = prebLane->getNormalPredecessorLane();
1127 } else {
1128 prebLane = prebLane->getLinkCont()[0]->getLane();
1129 }
1130 }
1131 // special case: vehicle considers changing to the opposite direction edge
1132 const int prebOffset = laneOffset;
1133 for (int p = 0; p < (int) preb.size(); ++p) {
1134 //if (DEBUG_COND) {
1135 // std::cout << " p=" << p << " prebLane=" << prebLane->getID() << " preb.p=" << preb[p].lane->getID() << "\n";
1136 //}
1137 if (preb[p].lane == prebLane && p + laneOffset >= 0) {
1138 assert(p + prebOffset < (int)preb.size());
1139 curr = preb[p];
1140 neigh = preb[p + prebOffset];
1141 currentDist = curr.length;
1142 neighDist = neigh.length;
1143 bestLaneOffset = curr.bestLaneOffset;
1144 if (bestLaneOffset == 0 && preb[p + prebOffset].bestLaneOffset == 0 && !checkOpposite) {
1145#ifdef DEBUG_WANTS_CHANGE
1146 if (DEBUG_COND) {
1147 std::cout << STEPS2TIME(currentTime)
1148 << " veh=" << myVehicle.getID()
1149 << " bestLaneOffsetOld=" << bestLaneOffset
1150 << " bestLaneOffsetNew=" << laneOffset
1151 << "\n";
1152 }
1153#endif
1154 bestLaneOffset = prebOffset;
1155 }
1156 best = preb[p + bestLaneOffset];
1157 currIdx = p;
1158 break;
1159 }
1160 }
1161 assert(curr.lane != nullptr);
1162 assert(neigh.lane != nullptr);
1163 assert(best.lane != nullptr);
1164 // direction specific constants
1165 const bool right = (laneOffset == -1);
1166 const double posOnLane = getForwardPos();
1167 double driveToNextStop = -std::numeric_limits<double>::max();
1168 if (myVehicle.nextStopDist() < std::numeric_limits<double>::max()
1170 // vehicle can always drive up to stop distance
1171 // @note this information is dynamic and thus not available in updateBestLanes()
1172 // @note: nextStopDist was compute before the vehicle moved
1173 driveToNextStop = myVehicle.nextStopDist();
1174 const double stopPos = posOnLane + myVehicle.nextStopDist() - myVehicle.getLastStepDist();
1175#ifdef DEBUG_WANTS_CHANGE
1176 if (DEBUG_COND) {
1177 std::cout << SIMTIME << std::setprecision(gPrecision) << " veh=" << myVehicle.getID()
1178 << " stopDist=" << myVehicle.nextStopDist()
1179 << " lastDist=" << myVehicle.getLastStepDist()
1180 << " stopPos=" << stopPos
1181 << " currentDist=" << currentDist
1182 << " neighDist=" << neighDist
1183 << "\n";
1184 }
1185#endif
1186 currentDist = MAX2(currentDist, stopPos);
1187 neighDist = MAX2(neighDist, stopPos);
1188 }
1189 const int lca = (right ? LCA_RIGHT : LCA_LEFT);
1190 const int myLca = (right ? LCA_MRIGHT : LCA_MLEFT);
1191 const int lcaCounter = (right ? LCA_LEFT : LCA_RIGHT);
1192 bool changeToBest = (right && bestLaneOffset < 0) || (!right && bestLaneOffset > 0);
1193 // keep information about being a leader/follower
1194 int ret = (myOwnState & 0xffff0000);
1195 int req = 0; // the request to change or stay
1196
1197 ret = slowDownForBlocked(lastBlocked, ret);
1198 if (lastBlocked != firstBlocked) {
1199 ret = slowDownForBlocked(firstBlocked, ret);
1200 }
1201
1202#ifdef DEBUG_WANTS_CHANGE
1203 if (DEBUG_COND) {
1204 std::cout << SIMTIME
1205 << " veh=" << myVehicle.getID()
1206 << " _wantsChange state=" << myOwnState
1207 << " myLCAccelerationAdvices=" << toString(myLCAccelerationAdvices)
1208 << " firstBlocked=" << Named::getIDSecure(firstBlocked)
1209 << " lastBlocked=" << Named::getIDSecure(lastBlocked)
1210 << " leader=" << Named::getIDSecure(leader.first)
1211 << " leaderGap=" << leader.second
1212 << " follower=" << Named::getIDSecure(follower.first)
1213 << " followerGap=" << follower.second
1214 << " neighLead=" << Named::getIDSecure(neighLead.first)
1215 << " neighLeadGap=" << neighLead.second
1216 << " neighFollow=" << Named::getIDSecure(neighFollow.first)
1217 << " neighFollowGap=" << neighFollow.second
1218 << "\n";
1219 }
1220#endif
1221
1222 // we try to estimate the distance which is necessary to get on a lane
1223 // we have to get on in order to keep our route
1224 // we assume we need something that depends on our velocity
1225 // and compare this with the free space on our wished lane
1226 //
1227 // if the free space is somehow(<-?) less than the space we need, we should
1228 // definitely try to get to the desired lane
1229 //
1230 // this rule forces our vehicle to change the lane if a lane changing is necessary soon
1231
1232
1233 // we do not want the lookahead distance to change all the time so we let it decay slowly
1234 // (in contrast, growth is applied instantaneously)
1237 } else {
1238 // memory decay factor for this action step
1239 const double memoryFactor = 1. - (1. - LOOK_AHEAD_SPEED_MEMORY) * myVehicle.getActionStepLengthSecs();
1240 assert(memoryFactor > 0.);
1242 (memoryFactor * myLookAheadSpeed + (1 - memoryFactor) * myVehicle.getSpeed()));
1243 }
1244 double laDist = myLookAheadSpeed * LOOK_FORWARD * myStrategicParam * (right ? 1 : myLookaheadLeft);
1245 laDist += myVehicle.getVehicleType().getLengthWithGap() * 2.;
1246 const bool hasStoppedLeader = leader.first != 0 && leader.first->isStopped() && leader.second < (currentDist - posOnLane);
1247 const bool hasBidiLeader = myVehicle.getLane()->getBidiLane() != nullptr && MSLCHelper::isBidiLeader(leader.first, curr.bestContinuations);
1248 const bool hasBidiNeighLeader = neighLane.getBidiLane() != nullptr && MSLCHelper::isBidiLeader(neighLead.first, neigh.bestContinuations);
1249
1250 if (bestLaneOffset == 0 && hasBidiLeader) {
1251 // getting out of the way is enough to clear the blockage
1252 laDist = 0;
1253 } else if (bestLaneOffset == 0 && hasStoppedLeader) {
1254 // react to a stopped leader on the current lane
1255 // The value of laDist is doubled below for the check whether the lc-maneuver can be taken out
1256 // on the remaining distance (because the vehicle has to change back and forth). Therefore multiply with 0.5.
1257 laDist = 0.5 * (myVehicle.getVehicleType().getLengthWithGap()
1258 + leader.first->getVehicleType().getLengthWithGap()
1259 + leader.second);
1260 } else if (bestLaneOffset == laneOffset && neighLead.first != 0 && (neighLead.first->isStopped() || hasBidiNeighLeader) && neighLead.second < (currentDist - posOnLane)) {
1261 // react to a stopped leader on the target lane (if it is the bestLane)
1262 if (isOpposite()) {
1263 // always allow changing back
1265 + neighLead.first->getVehicleType().getLengthWithGap()
1266 + neighLead.second);
1267 } else if (!hasStoppedLeader &&
1268 ((neighLead.second + myVehicle.getVehicleType().getLengthWithGap() + neighLead.first->getVehicleType().getLengthWithGap()) < (currentDist - posOnLane)
1269 || hasBidiNeighLeader)) {
1270 // do not change to the target lane until passing the stopped vehicle
1271 // (unless the vehicle blocks our intended stopping position, then we have to wait anyway)
1272 changeToBest = false;
1273 }
1274 }
1275 if (myStrategicParam < 0) {
1276 laDist = -1e3; // never perform strategic change
1277 }
1278
1279 // free space that is available for changing
1280 //const double neighSpeed = (neighLead.first != 0 ? neighLead.first->getSpeed() :
1281 // neighFollow.first != 0 ? neighFollow.first->getSpeed() :
1282 // best.lane->getSpeedLimit());
1283 // @note: while this lets vehicles change earlier into the correct direction
1284 // it also makes the vehicles more "selfish" and prevents changes which are necessary to help others
1285
1286
1287
1288 // Next we assign to roundabout edges a larger distance than to normal edges
1289 // in order to decrease sense of lc urgency and induce higher usage of inner roundabout lanes.
1290 const double roundaboutBonus = MSLCHelper::getRoundaboutDistBonus(myVehicle, myRoundaboutBonus, curr, neigh, best);
1291 currentDist += roundaboutBonus;
1292 neighDist += roundaboutBonus;
1293
1294 const double usableDist = MAX2(currentDist - posOnLane - best.occupation * JAM_FACTOR, driveToNextStop);
1295 //- (best.lane->getVehicleNumber() * neighSpeed)); // VARIANT 9 jfSpeed
1296 const double maxJam = MAX2(preb[currIdx + prebOffset].occupation, preb[currIdx].occupation);
1297 const double vMax = myVehicle.getLane()->getVehicleMaxSpeed(&myVehicle);
1298 const double neighVMax = neighLane.getVehicleMaxSpeed(&myVehicle);
1299 // upper bound which will be restricted successively
1300 double thisLaneVSafe = vMax;
1301 const bool checkOverTakeRight = avoidOvertakeRight();
1302
1303 double neighLeftPlace = MAX2(0.0, neighDist - posOnLane - maxJam);
1304 if (neighLead.first != 0 && neighLead.first->isStopped()) {
1305 neighLeftPlace = MIN2(neighLeftPlace, neighLead.second);
1306 }
1307
1308#ifdef DEBUG_WANTS_CHANGE
1309 if (DEBUG_COND) {
1310 std::cout << STEPS2TIME(currentTime)
1311 << " veh=" << myVehicle.getID()
1312 << " laSpeed=" << myLookAheadSpeed
1313 << " laDist=" << laDist
1314 << " currentDist=" << currentDist
1315 << " usableDist=" << usableDist
1316 << " bestLaneOffset=" << bestLaneOffset
1317 << " best.occupation=" << best.occupation
1318 << " best.length=" << best.length
1319 << "\n roundaboutBonus=" << roundaboutBonus
1320 << " maxJam=" << maxJam
1321 << " neighDist=" << neighDist
1322 << " neighLeftPlace=" << neighLeftPlace
1323 << (hasBidiLeader ? " bidiLeader" : "")
1324 << (hasBidiNeighLeader ? " bidiNeighLeader" : "")
1325 << "\n";
1326 }
1327#endif
1328
1329 bool changeLeftToAvoidOvertakeRight = false;
1330 if (changeToBest && bestLaneOffset == curr.bestLaneOffset
1331 && currentDistDisallows(usableDist, bestLaneOffset, laDist)) {
1333 ret = ret | lca | LCA_STRATEGIC | LCA_URGENT;
1334 } else {
1335 // VARIANT_20 (noOvertakeRight)
1336 if (neighLead.first != 0 && checkOverTakeRight && !right) {
1337 // check for slower leader on the left. we should not overtake but
1338 // rather move left ourselves (unless congested)
1339 MSVehicle* nv = neighLead.first;
1340 const double deltaV = MAX2(vMax - neighLane.getVehicleMaxSpeed(nv),
1341 myVehicle.getSpeed() - nv->getSpeed());
1342 if (deltaV > 0) {
1343 const double vMaxDecel = getCarFollowModel().getSpeedAfterMaxDecel(myVehicle.getSpeed());
1344 const double vSafeFollow = getCarFollowModel().followSpeed(
1345 &myVehicle, myVehicle.getSpeed(), neighLead.second, nv->getSpeed(), nv->getCarFollowModel().getMaxDecel());
1346 const double vStayBehind = nv->getSpeed() - HELP_OVERTAKE;
1347 double vSafe;
1348 if (vSafeFollow >= vMaxDecel) {
1349 vSafe = vSafeFollow;
1350 } else {
1351 vSafe = MAX2(vMaxDecel, vStayBehind);
1352 }
1354 vSafe = MAX2(vSafe, nv->getSpeed());
1355 }
1356 thisLaneVSafe = MIN2(thisLaneVSafe, vSafe);
1357 addLCSpeedAdvice(vSafe);
1358 // only generate impulse for overtaking left shortly before braking would be necessary
1359 const double deltaGapFuture = deltaV * 8;
1360 const double vSafeFuture = getCarFollowModel().followSpeed(
1361 &myVehicle, myVehicle.getSpeed(), neighLead.second - deltaGapFuture, nv->getSpeed(), nv->getCarFollowModel().getMaxDecel());
1362 if (vSafeFuture < vSafe) {
1363 const double relativeGain = deltaV / MAX2(vMax,
1365 mySpeedGainProbabilityLeft += (long long int)(myVehicle.getActionStepLengthSecs() * relativeGain * HYST_PRECISION);
1366 changeLeftToAvoidOvertakeRight = true;
1367 }
1368#ifdef DEBUG_WANTS_CHANGE
1369 if (DEBUG_COND) {
1370 std::cout << STEPS2TIME(currentTime)
1371 << " avoid overtaking on the right nv=" << nv->getID()
1372 << " deltaV=" << deltaV
1373 << " nvSpeed=" << nv->getSpeed()
1374 << " speedGainL=" << mySpeedGainProbabilityLeft / HYST_PRECISION
1375 << " speedGainR=" << mySpeedGainProbabilityRight / HYST_PRECISION
1376 << " planned acceleration =" << myLCAccelerationAdvices.back().first
1377 << "\n";
1378 }
1379#endif
1380 }
1381 }
1382 const bool currFreeUntilNeighEnd = leader.first == nullptr || neighDist - posOnLane <= leader.second;
1383 const double overtakeDist = (leader.first == 0 || hasBidiLeader ? -1 :
1384 leader.second + myVehicle.getVehicleType().getLength() + leader.first->getVehicleType().getLengthWithGap());
1385 const double overtakeDist2 = (neighLead.first == 0 || !neighLead.first->isStopped() ? -1 :
1386 neighLead.second + myVehicle.getVehicleType().getLength() + neighLead.first->getVehicleType().getLengthWithGap());
1387 if (leader.first != 0 && (leader.first->isStopped() || hasBidiLeader) && leader.second < REACT_TO_STOPPED_DISTANCE
1388 // current destination leaves enough space to overtake the leader
1389 && MIN2(neighDist, currentDist) - posOnLane > overtakeDist
1390 // maybe do not overtake on the right at high speed
1391 && (!checkOverTakeRight || !right)
1392 && myStrategicParam >= 0
1393 && (neighLead.first == 0 || !neighLead.first->isStopped()
1394 // neighboring stopped vehicle leaves enough space to overtake leader
1395 || neighLead.second > overtakeDist
1396 // if we cannot pass neighLead before reaching leader we must find another free lane
1397 || (overtakeDist2 > leader.second && hasFreeLane(laneOffset, neighLead)))) {
1398 // avoid becoming stuck behind a stopped leader
1399 currentDist = myVehicle.getPositionOnLane() + leader.second;
1400#ifdef DEBUG_WANTS_CHANGE
1401 if (DEBUG_COND) {
1402 std::cout << " veh=" << myVehicle.getID() << " overtake stopped leader=" << leader.first->getID()
1403 << " overtakeDist=" << overtakeDist
1404 << " overtakeDist2=" << overtakeDist
1405 << " hasFreeLane=" << hasFreeLane(laneOffset, neighLead)
1406 << " remaining=" << MIN2(neighDist, currentDist) - posOnLane
1407 << "\n";
1408 }
1409#endif
1410 ret = ret | lca | LCA_STRATEGIC | LCA_URGENT;
1411 } else if (!changeToBest && currentDistDisallows(neighLeftPlace, abs(bestLaneOffset) + 2, laDist) && !hasBidiLeader) {
1412 // the opposite lane-changing direction should be done than the one examined herein
1413 // we'll check whether we assume we could change anyhow and get back in time...
1414 //
1415 // this rule prevents the vehicle from moving in opposite direction of the best lane
1416 // unless the way till the end where the vehicle has to be on the best lane
1417 // is long enough
1418#ifdef DEBUG_WANTS_CHANGE
1419 if (DEBUG_COND) {
1420 std::cout << " veh=" << myVehicle.getID() << " could not change back and forth in time (1) neighLeftPlace=" << neighLeftPlace << "\n";
1421 }
1422#endif
1423 ret = ret | LCA_STAY | LCA_STRATEGIC;
1424 } else if (bestLaneOffset == 0 && (neighLeftPlace * 2. < laDist)) {
1425 // the current lane is the best and a lane-changing would cause a situation
1426 // of which we assume we will not be able to return to the lane we have to be on.
1427 // this rule prevents the vehicle from leaving the current, best lane when it is
1428 // close to this lane's end
1429#ifdef DEBUG_WANTS_CHANGE
1430 if (DEBUG_COND) {
1431 std::cout << " veh=" << myVehicle.getID() << " could not change back and forth in time (2) neighLeftPlace=" << neighLeftPlace << "\n";
1432 }
1433#endif
1434 ret = ret | LCA_STAY | LCA_STRATEGIC;
1435 } else if (bestLaneOffset == 0
1436 && (leader.first == 0 || !leader.first->isStopped())
1437 && !hasBidiLeader
1438 && neigh.bestContinuations.back()->getLinkCont().size() != 0
1439 && roundaboutBonus == 0
1440 && !checkOpposite
1441 && ((myStrategicParam >= 0 && neighDist < TURN_LANE_DIST)
1442 // lane changing cannot possibly help
1443 || (myStrategicParam < 0 && currFreeUntilNeighEnd))
1444 ) {
1445 // VARIANT_21 (stayOnBest)
1446 // we do not want to leave the best lane for a lane which leads elsewhere
1447 // unless our leader is stopped or we are approaching a roundabout
1448#ifdef DEBUG_WANTS_CHANGE
1449 if (DEBUG_COND) {
1450 std::cout << " veh=" << myVehicle.getID() << " does not want to leave the bestLane (neighDist=" << neighDist << ")\n";
1451 }
1452#endif
1453 ret = ret | LCA_STAY | LCA_STRATEGIC;
1454 }
1455 }
1456 // check for overriding TraCI requests
1457#ifdef DEBUG_WANTS_CHANGE
1458 if (DEBUG_COND) {
1459 std::cout << STEPS2TIME(currentTime) << " veh=" << myVehicle.getID() << " ret=" << toString((LaneChangeAction)ret);
1460 }
1461#endif
1462 // store state before canceling
1463 getCanceledState(laneOffset) |= ret | blocked;
1465 if ((ret & lcaCounter) != 0) {
1466 // we are not interested in traci requests for the opposite direction here
1467 ret &= ~(LCA_TRACI | lcaCounter | LCA_URGENT);
1468 }
1469#ifdef DEBUG_WANTS_CHANGE
1470 if (DEBUG_COND) {
1471 std::cout << " retAfterInfluence=" << toString((LaneChangeAction)ret) << "\n";
1472 }
1473#endif
1474
1475 if ((ret & LCA_STAY) != 0) {
1476 // remove TraCI flags because it should not be included in "state-without-traci"
1477 ret = getCanceledState(laneOffset);
1478 return ret;
1479 }
1480 if ((ret & LCA_URGENT) != 0) {
1481 // prepare urgent lane change maneuver
1482 // save the left space
1483 myLeftSpace = currentDist - posOnLane;
1484 if (changeToBest && abs(bestLaneOffset) > 1 && myVehicle.getNumRemainingEdges() > 1) {
1485 // there might be a vehicle which needs to counter-lane-change one lane further and we cannot see it yet
1486 myLeadingBlockerLength = MAX2(getExtraReservation(bestLaneOffset, neighDist - currentDist), myLeadingBlockerLength);
1487#ifdef DEBUG_SAVE_BLOCKER_LENGTH
1488 if (DEBUG_COND) {
1489 std::cout << " reserving space for unseen blockers myLeadingBlockerLength=" << myLeadingBlockerLength << "\n";
1490 }
1491#endif
1492 }
1493
1494 // letting vehicles merge in at the end of the lane in case of counter-lane change, step#1
1495 // if there is a leader and he wants to change to the opposite direction
1496 const bool canContinue = curr.bestContinuations.size() > 1;
1497 bool canReserve = MSLCHelper::updateBlockerLength(myVehicle, neighLead.first, lcaCounter, myLeftSpace - POSITION_EPS, canContinue, myLeadingBlockerLength);
1498 if (firstBlocked != neighLead.first) {
1499 canReserve &= MSLCHelper::updateBlockerLength(myVehicle, firstBlocked, lcaCounter, myLeftSpace - POSITION_EPS, canContinue, myLeadingBlockerLength);
1500 }
1501#ifdef DEBUG_SAVE_BLOCKER_LENGTH
1502 if (DEBUG_COND) {
1503 std::cout << SIMTIME << " canReserve=" << canReserve << " canContinue=" << canContinue << "\n";
1504 }
1505#endif
1506 if (!canReserve && !isOpposite()) {
1507 // we have a low-priority relief connection
1508 // std::cout << SIMTIME << " veh=" << myVehicle.getID() << " cannotReserve for blockers\n";
1509 myDontBrake = canContinue;
1510 }
1511
1512 const int remainingLanes = MAX2(1, abs(bestLaneOffset));
1513 const double urgency = isOpposite() ? OPPOSITE_URGENCY : URGENCY;
1514 const double remainingSeconds = ((ret & LCA_TRACI) == 0 ?
1515 //MAX2(STEPS2TIME(TS), (myLeftSpace-myLeadingBlockerLength) / MAX2(myLookAheadSpeed, NUMERICAL_EPS) / remainingLanes / urgency) :
1516 MAX2(STEPS2TIME(TS), myLeftSpace / MAX2(myLookAheadSpeed, NUMERICAL_EPS) / remainingLanes / urgency) :
1518 if (!hasBidiNeighLeader) {
1519 const double plannedSpeed = informLeader(msgPass, blocked, myLca, neighLead, remainingSeconds);
1520 // NOTE: for the ballistic update case negative speeds may indicate a stop request,
1521 // while informLeader returns -1 in that case. Refs. #2577
1522 if (plannedSpeed >= 0 || (!MSGlobals::gSemiImplicitEulerUpdate && plannedSpeed != -1)) {
1523 // maybe we need to deal with a blocking follower
1524 const bool hasBidiNeighFollower = neighLane.getBidiLane() != nullptr && MSLCHelper::isBidiFollower(&myVehicle, neighFollow.first);
1525 if (!hasBidiNeighFollower) {
1526 informFollower(msgPass, blocked, myLca, neighFollow, remainingSeconds, plannedSpeed);
1527 }
1528 }
1529#ifdef DEBUG_WANTS_CHANGE
1530 if (DEBUG_COND) {
1531 std::cout << STEPS2TIME(currentTime)
1532 << " veh=" << myVehicle.getID()
1533 << " myLeftSpace=" << myLeftSpace
1534 << " remainingSeconds=" << remainingSeconds
1535 << " plannedSpeed=" << plannedSpeed
1536 << "\n";
1537 }
1538#endif
1539 } else {
1540#ifdef DEBUG_WANTS_CHANGE
1541 if (DEBUG_COND) {
1542 std::cout << STEPS2TIME(currentTime)
1543 << " veh=" << myVehicle.getID()
1544 << " myLeftSpace=" << myLeftSpace
1545 << " remainingSeconds=" << remainingSeconds
1546 << " hasBidiNeighLeader\n";
1547 }
1548#endif
1549 }
1550
1551
1552 // remove TraCI flags because it should not be included in "state-without-traci"
1553 ret = getCanceledState(laneOffset);
1554 return ret;
1555 }
1556
1557 // we wish to anticipate future speeds. This is difficult when the leading
1558 // vehicles are still accelerating so we resort to comparing speeds for the near future (1s) in this case
1559 const bool acceleratingLeader = (neighLead.first != 0 && neighLead.first->getAcceleration() > 0)
1560 || (leader.first != 0 && leader.first->getAcceleration() > 0);
1561 double neighLaneVSafe = MIN2(neighVMax, anticipateFollowSpeed(neighLead, neighDist, neighVMax, acceleratingLeader));
1562 thisLaneVSafe = MIN2(thisLaneVSafe, anticipateFollowSpeed(leader, currentDist, vMax, acceleratingLeader));
1563 //std::cout << SIMTIME << " veh=" << myVehicle.getID() << " thisLaneVSafe=" << thisLaneVSafe << " neighLaneVSafe=" << neighLaneVSafe << "\n";
1564
1565
1566 // a high inconvenience prevents cooperative changes and the following things are inconvenient:
1567 // - a desire to change in the opposite direction for speedGain
1568 // - low anticipated speed on the neighboring lane
1569 // - high occupancy on the neighboring lane while in a roundabout
1570
1571 double inconvenience = laneOffset < 0
1574
1575 const double relSpeedDiff = thisLaneVSafe == 0 ? 0 : (thisLaneVSafe - neighLaneVSafe) / MAX2(thisLaneVSafe, neighLaneVSafe);
1576 inconvenience = MAX2(relSpeedDiff, inconvenience);
1577 inconvenience = MIN2(1.0, inconvenience);
1578
1579 const bool speedGainInconvenient = inconvenience > myCooperativeParam;
1580 const bool neighOccupancyInconvenient = neigh.lane->getBruttoOccupancy() > curr.lane->getBruttoOccupancy();
1581#ifdef DEBUG_WANTS_CHANGE
1582 if (DEBUG_COND) {
1583 std::cout << STEPS2TIME(currentTime)
1584 << " veh=" << myVehicle.getID()
1585 << " speedGainL=" << mySpeedGainProbabilityLeft / HYST_PRECISION
1586 << " speedGainR=" << mySpeedGainProbabilityRight / HYST_PRECISION
1587 << " neighSpeedFactor=" << (thisLaneVSafe / neighLaneVSafe - 1)
1588 << " inconvenience=" << inconvenience
1589 << " speedInconv=" << speedGainInconvenient
1590 << " occInconv=" << neighOccupancyInconvenient
1591 << "\n";
1592 }
1593#endif
1594
1595 // VARIANT_15
1596 if (roundaboutBonus > 0) {
1597
1598#ifdef DEBUG_WANTS_CHANGE
1599 if (DEBUG_COND) {
1600 std::cout << STEPS2TIME(currentTime)
1601 << " veh=" << myVehicle.getID()
1602 << " roundaboutBonus=" << roundaboutBonus
1603 << " myLeftSpace=" << myLeftSpace
1604 << "\n";
1605 }
1606#endif
1607 // try to use the inner lanes of a roundabout to increase throughput
1608 // unless we are approaching the exit
1609 if (lca == LCA_LEFT) {
1610 // if inconvenience is not too high, request collaborative change (currently only for ballistic update)
1611 // TODO: test this for euler update! Refs. #2575
1612 if (MSGlobals::gSemiImplicitEulerUpdate || !neighOccupancyInconvenient) {
1613// if(MSGlobals::gSemiImplicitEulerUpdate || !speedGainInconvenient){
1614 req = ret | lca | LCA_COOPERATIVE;
1615 }
1616 } else {
1617 // if inconvenience is not too high, request collaborative change (currently only for ballistic update)
1618 if (MSGlobals::gSemiImplicitEulerUpdate || neighOccupancyInconvenient) {
1619// if(MSGlobals::gSemiImplicitEulerUpdate || speedGainInconvenient){
1620 req = ret | LCA_STAY | LCA_COOPERATIVE;
1621 }
1622 }
1623 if (!cancelRequest(req, laneOffset)) {
1624 return ret | req;
1625 }
1626 }
1627
1628 // let's also regard the case where the vehicle is driving on a highway...
1629 // in this case, we do not want to get to the dead-end of an on-ramp
1630 if (right) {
1631 if (bestLaneOffset == 0 && myVehicle.getLane()->getSpeedLimit() > 80. / 3.6 && myLookAheadSpeed > SUMO_const_haltingSpeed) {
1632#ifdef DEBUG_WANTS_CHANGE
1633 if (DEBUG_COND) {
1634 std::cout << " veh=" << myVehicle.getID() << " does not want to get stranded on the on-ramp of a highway\n";
1635 }
1636#endif
1637 req = ret | LCA_STAY | LCA_STRATEGIC;
1638 if (!cancelRequest(req, laneOffset)) {
1639 return ret | req;
1640 }
1641 }
1642 }
1643 // --------
1644
1645 // -------- make place on current lane if blocking follower
1646 //if (amBlockingFollowerPlusNB()) {
1647 // std::cout << myVehicle.getID() << ", " << currentDistAllows(neighDist, bestLaneOffset, laDist)
1648 // << " neighDist=" << neighDist
1649 // << " currentDist=" << currentDist
1650 // << "\n";
1651 //}
1652
1654 && (!speedGainInconvenient)
1655 && ((myOwnState & myLca) != 0) // VARIANT_6 : counterNoHelp
1656 && (changeToBest || currentDistAllows(neighDist, abs(bestLaneOffset) + 1, laDist))) {
1657
1658 // VARIANT_2 (nbWhenChangingToHelp)
1659#ifdef DEBUG_COOPERATE
1660 if (DEBUG_COND) {
1661 std::cout << STEPS2TIME(currentTime)
1662 << " veh=" << myVehicle.getID()
1663 << " wantsChangeToHelp=" << (right ? "right" : "left")
1664 << " state=" << myOwnState
1665 << (((myOwnState & myLca) == 0) ? " (counter)" : "")
1666 << "\n";
1667 }
1668#endif
1669 req = ret | lca | LCA_COOPERATIVE | LCA_URGENT ;//| LCA_CHANGE_TO_HELP;
1670 if (!cancelRequest(req, laneOffset)) {
1671 if ((blocked & LCA_BLOCKED_BY_LEFT_FOLLOWER) && !right && mySpeedGainProbabilityLeft > (long long int)(mySpeedGainUrgency * HYST_PRECISION)) {
1672 MSVehicle* nv = neighFollow.first;
1673 const bool hasBidiNeighFollower = neighLane.getBidiLane() != nullptr && MSLCHelper::isBidiFollower(&myVehicle, nv);
1674 if (nv != nullptr && !hasBidiNeighFollower) {
1675 const double helpSpeed = MAX2(nv->getCarFollowModel().minNextSpeed(nv->getSpeed(), nv), myVehicle.getSpeed() - 1);
1676 msgPass.informNeighFollower(new Info(helpSpeed, myLca | LCA_AMBLOCKINGFOLLOWER), &myVehicle);
1677 }
1678 }
1679 return ret | req;
1680 }
1681 }
1682
1683 // --------
1684
1685
1688 //if ((blocked & LCA_BLOCKED) != 0) {
1689 // return ret;
1690 //}
1692
1693 // -------- higher speed
1694 //if ((congested(neighLead.first) && neighLead.second < 20) || predInteraction(leader.first)) { //!!!
1695 // return ret;
1696 //}
1697
1698 if (neighLane.getEdge().getPersons().size() > 0) {
1699 // react to pedestrians
1700 adaptSpeedToPedestrians(myVehicle.getLane(), thisLaneVSafe);
1701 adaptSpeedToPedestrians(&neighLane, neighLaneVSafe);
1702 }
1703
1704 const double relativeGain = (neighLaneVSafe - thisLaneVSafe) / MAX2(neighLaneVSafe,
1706
1707#ifdef DEBUG_WANTS_CHANGE
1708 if (DEBUG_COND) {
1709 std::cout << STEPS2TIME(currentTime)
1710 << " veh=" << myVehicle.getID()
1711 << " currentDist=" << currentDist
1712 << " neighDist=" << neighDist
1713 << " thisVSafe=" << thisLaneVSafe
1714 << " neighVSafe=" << neighLaneVSafe
1715 << " relGain=" << toString(relativeGain, 8)
1716 << "\n";
1717 }
1718#endif
1719
1720 if (right) {
1721 // ONLY FOR CHANGING TO THE RIGHT
1722 if (thisLaneVSafe - 5 / 3.6 > neighLaneVSafe) {
1723 // ok, the current lane is faster than the right one...
1725 //myKeepRightProbability /= 2.0;
1726 } else {
1727 // ok, the current lane is not (much) faster than the right one
1728 mySpeedGainProbabilityRight += (long long int)(myVehicle.getActionStepLengthSecs() * relativeGain * HYST_PRECISION);
1729
1730 // honor the obligation to keep right (Rechtsfahrgebot)
1731 const double roadSpeedFactor = vMax / myVehicle.getLane()->getSpeedLimit(); // differse from speedFactor if vMax < speedLimit
1732 double acceptanceTime;
1733 if (myKeepRightAcceptanceTime == -1) {
1734 // legacy behavior: scale acceptance time with current speed and
1735 // use old hard-coded constant
1736 acceptanceTime = 7 * roadSpeedFactor * MAX2(1.0, myVehicle.getSpeed());
1737 } else {
1738 acceptanceTime = myKeepRightAcceptanceTime * roadSpeedFactor;
1739 if (follower.first != nullptr && follower.second < 2 * follower.first->getCarFollowModel().brakeGap(follower.first->getSpeed())) {
1740 // reduce acceptanceTime if the follower vehicle is faster or wants to drive faster
1741 if (follower.first->getSpeed() >= myVehicle.getSpeed()) {
1742 acceptanceTime *= MAX2(1.0, myVehicle.getSpeed()) / MAX2(1.0, follower.first->getSpeed());
1743 const double fRSF = follower.first->getLane()->getVehicleMaxSpeed(follower.first) / follower.first->getLane()->getSpeedLimit();
1744 if (fRSF > roadSpeedFactor) {
1745 acceptanceTime /= fRSF;
1746 }
1747 }
1748 }
1749 }
1750 double fullSpeedGap = MAX2(0., neighDist - myVehicle.getCarFollowModel().brakeGap(vMax));
1751 double fullSpeedDrivingSeconds = MIN2(acceptanceTime, fullSpeedGap / vMax);
1752 if (neighLead.first != 0 && neighLead.first->getSpeed() < vMax) {
1753 fullSpeedGap = MAX2(0., MIN2(fullSpeedGap,
1754 neighLead.second - myVehicle.getCarFollowModel().getSecureGap(&myVehicle, neighLead.first,
1755 vMax, neighLead.first->getSpeed(), neighLead.first->getCarFollowModel().getMaxDecel())));
1756 fullSpeedDrivingSeconds = MIN2(fullSpeedDrivingSeconds, fullSpeedGap / (vMax - neighLead.first->getSpeed()));
1757 }
1758 // stay on the current lane if we cannot overtake a slow leader on the right
1759 if (checkOverTakeRight && leader.first != 0
1760 && leader.first->getLane()->getVehicleMaxSpeed(leader.first) < vMax) {
1761 fullSpeedGap = MIN2(fullSpeedGap, leader.second);
1762 fullSpeedDrivingSeconds = MIN2(fullSpeedDrivingSeconds, fullSpeedGap / (vMax - leader.first->getSpeed()));
1763 }
1764
1765 const double deltaProb = (myChangeProbThresholdRight == std::numeric_limits<long long int>::max()) ? 0 :
1766 ((double)myChangeProbThresholdRight * (fullSpeedDrivingSeconds / acceptanceTime) / KEEP_RIGHT_TIME);
1767 myKeepRightProbability -= (long long int)(myVehicle.getActionStepLengthSecs() * deltaProb);
1768
1769 //std::cout << STEPS2TIME(currentTime)
1770 // << " veh=" << myVehicle.getID()
1771 // << " acceptanceTime=" << acceptanceTime
1772 // << " fullSpeedDrivingSeconds=" << fullSpeedDrivingSeconds
1773 // << " dProb=" << deltaProb
1774 // << " myKeepRightProbability=" << myKeepRightProbability
1775 // << "\n";
1776
1777#ifdef DEBUG_WANTS_CHANGE
1778 if (DEBUG_COND) {
1779 std::cout << STEPS2TIME(currentTime)
1780 << " veh=" << myVehicle.getID()
1781 << " vMax=" << vMax
1782 << " neighDist=" << neighDist
1783 << " brakeGap=" << myVehicle.getCarFollowModel().brakeGap(myVehicle.getSpeed())
1784 << " leaderSpeed=" << (neighLead.first == 0 ? -1 : neighLead.first->getSpeed())
1785 << " secGap=" << (neighLead.first == 0 ? -1 : myVehicle.getCarFollowModel().getSecureGap(&myVehicle, neighLead.first,
1786 myVehicle.getSpeed(), neighLead.first->getSpeed(), neighLead.first->getCarFollowModel().getMaxDecel()))
1787 << " acceptanceTime=" << acceptanceTime
1788 << " fullSpeedGap=" << fullSpeedGap
1789 << " fullSpeedDrivingSeconds=" << fullSpeedDrivingSeconds
1790 << " dProb=" << deltaProb / HYST_PRECISION
1791 << " myKeepRightProbability=" << myKeepRightProbability / HYST_PRECISION
1792 << "\n";
1793 }
1794#endif
1795 if ((long long int)((double)myKeepRightProbability * myKeepRightParam) < -myChangeProbThresholdRight) {
1796 req = ret | lca | LCA_KEEPRIGHT;
1797 if (!cancelRequest(req, laneOffset)) {
1798 return ret | req;
1799 }
1800 }
1801 }
1802
1803#ifdef DEBUG_WANTS_CHANGE
1804 if (DEBUG_COND) {
1805 std::cout << STEPS2TIME(currentTime)
1806 << " veh=" << myVehicle.getID()
1807 << " speed=" << myVehicle.getSpeed()
1808 << " speedGainL=" << mySpeedGainProbabilityLeft / HYST_PRECISION
1809 << " speedGainR=" << mySpeedGainProbabilityRight / HYST_PRECISION
1810 << " thisLaneVSafe=" << thisLaneVSafe
1811 << " neighLaneVSafe=" << neighLaneVSafe
1812 << " relativeGain=" << relativeGain
1813 << " blocked=" << blocked
1814 << "\n";
1815 }
1816#endif
1817
1819 && neighDist / MAX2(.1, myVehicle.getSpeed()) > mySpeedGainRemainTime) { //./MAX2( .1, myVehicle.getSpeed())) { // -.1
1820 req = ret | lca | LCA_SPEEDGAIN;
1822 req |= LCA_URGENT;
1823 }
1824 if (!cancelRequest(req, laneOffset)) {
1825 return ret | req;
1826 }
1827 }
1828 } else {
1829 // ONLY FOR CHANGING TO THE LEFT
1830 if (thisLaneVSafe > neighLaneVSafe) {
1831 // this lane is better
1833 } else if (thisLaneVSafe == neighLaneVSafe) {
1835 } else {
1836 mySpeedGainProbabilityLeft += (long long int)(myVehicle.getActionStepLengthSecs() * relativeGain * HYST_PRECISION);
1837 }
1838 // VARIANT_19 (stayRight)
1839 //if (neighFollow.first != 0) {
1840 // MSVehicle* nv = neighFollow.first;
1841 // const double secGap = nv->getCarFollowModel().getSecureGap(nv, &myVehicle, nv->getSpeed(), myVehicle.getSpeed(), myVehicle.getCarFollowModel().getMaxDecel());
1842 // if (neighFollow.second < secGap * KEEP_RIGHT_HEADWAY) {
1843 // // do not change left if it would inconvenience faster followers
1844 // return ret | LCA_STAY | LCA_SPEEDGAIN;
1845 // }
1846 //}
1847
1848#ifdef DEBUG_WANTS_CHANGE
1849 if (DEBUG_COND) {
1850 std::cout << STEPS2TIME(currentTime)
1851 << " veh=" << myVehicle.getID()
1852 << " speed=" << myVehicle.getSpeed()
1853 << " speedGainL=" << mySpeedGainProbabilityLeft / HYST_PRECISION
1854 << " speedGainR=" << mySpeedGainProbabilityRight / HYST_PRECISION
1855 << " thisLaneVSafe=" << thisLaneVSafe
1856 << " neighLaneVSafe=" << neighLaneVSafe
1857 << " relativeGain=" << relativeGain
1858 << " blocked=" << blocked
1859 << "\n";
1860 }
1861#endif
1862
1864 && (relativeGain > NUMERICAL_EPS || changeLeftToAvoidOvertakeRight)
1865 && neighDist / MAX2(.1, myVehicle.getSpeed()) > mySpeedGainRemainTime) { // .1
1866 req = ret | lca | LCA_SPEEDGAIN;
1868 req |= LCA_URGENT;
1869 }
1870 if (!cancelRequest(req, laneOffset)) {
1871 if ((req & LCA_URGENT) && (blocked & LCA_BLOCKED_BY_LEFT_FOLLOWER)) {
1872 MSVehicle* nv = neighFollow.first;
1873 const bool hasBidiNeighFollower = neighLane.getBidiLane() != nullptr && MSLCHelper::isBidiFollower(&myVehicle, nv);
1874 if (nv != nullptr && !hasBidiNeighFollower) {
1875 const double helpSpeed = MAX2(nv->getCarFollowModel().minNextSpeed(nv->getSpeed(), nv), myVehicle.getSpeed() - 1);
1876 msgPass.informNeighFollower(new Info(helpSpeed, myLca | LCA_AMBLOCKINGFOLLOWER), &myVehicle);
1877 }
1878 }
1879 return ret | req;
1880 }
1881 }
1882 }
1883 // --------
1884 if (changeToBest && bestLaneOffset == curr.bestLaneOffset
1885 && myStrategicParam >= 0
1886 && relativeGain >= 0
1888 // change towards the correct lane, speedwise it does not hurt
1889 req = ret | lca | LCA_STRATEGIC;
1890 if (!cancelRequest(req, laneOffset)) {
1891 return ret | req;
1892 }
1893 }
1894#ifdef DEBUG_WANTS_CHANGE
1895 if (DEBUG_COND) {
1896 std::cout << STEPS2TIME(currentTime)
1897 << " veh=" << myVehicle.getID()
1898 << " speedGainL=" << mySpeedGainProbabilityLeft / HYST_PRECISION
1899 << " speedGainR=" << mySpeedGainProbabilityRight / HYST_PRECISION
1900 << " myKeepRightProbability=" << myKeepRightProbability / HYST_PRECISION
1901 << " thisLaneVSafe=" << thisLaneVSafe
1902 << " neighLaneVSafe=" << neighLaneVSafe
1903 << "\n";
1904 }
1905#endif
1906
1907 return ret;
1908}
1909
1910
1911double
1912MSLCM_LC2013::anticipateFollowSpeed(const std::pair<MSVehicle*, double>& leaderDist, double dist, double vMax, bool acceleratingLeader) {
1913 const MSVehicle* leader = leaderDist.first;
1914 const double gap = leaderDist.second;
1915 double futureSpeed;
1916 if (acceleratingLeader) {
1917 // XXX see #6562
1918 const double maxSpeed1s = (myVehicle.getSpeed() + myVehicle.getCarFollowModel().getMaxAccel()
1920 if (leader == nullptr) {
1921 if (hasBlueLight()) {
1922 // can continue from any lane if necessary
1923 futureSpeed = vMax;
1924 } else {
1925 futureSpeed = getCarFollowModel().followSpeed(&myVehicle, maxSpeed1s, dist, 0, 0);
1926 }
1927 } else {
1928 futureSpeed = getCarFollowModel().followSpeed(&myVehicle, maxSpeed1s, gap, leader->getSpeed(), leader->getCarFollowModel().getMaxDecel());
1929 }
1930 } else {
1931 // onInsertion = true because the vehicle has already moved
1932 if (leader == nullptr) {
1933 if (hasBlueLight()) {
1934 // can continue from any lane if necessary
1935 futureSpeed = vMax;
1936 } else {
1937 futureSpeed = getCarFollowModel().maximumSafeStopSpeed(dist, getCarFollowModel().getMaxDecel(), myVehicle.getSpeed(), true);
1938 }
1939 } else {
1940 futureSpeed = getCarFollowModel().maximumSafeFollowSpeed(gap, myVehicle.getSpeed(), leader->getSpeed(), leader->getCarFollowModel().getMaxDecel(), true);
1941 }
1942 }
1943 futureSpeed = MIN2(vMax, futureSpeed);
1944 if (leader != nullptr && gap > 0 && mySpeedGainLookahead > 0) {
1945 const double futureLeaderSpeed = acceleratingLeader ? leader->getLane()->getVehicleMaxSpeed(leader) : leader->getSpeed();
1946 const double deltaV = vMax - futureLeaderSpeed;
1947 if (deltaV > 0 && gap > 0) {
1948 const double secGap = getCarFollowModel().getSecureGap(&myVehicle, leader, futureSpeed, leader->getSpeed(), getCarFollowModel().getMaxDecel());
1949 const double fullSpeedGap = gap - secGap;
1950 if (fullSpeedGap / deltaV < mySpeedGainLookahead) {
1951 // anticipate future braking by computing the average
1952 // speed over the next few seconds
1953 const double gapClosingTime = MAX2(0.0, fullSpeedGap / deltaV);
1954 const double foreCastTime = mySpeedGainLookahead * 2;
1955 //if (DEBUG_COND) std::cout << SIMTIME << " veh=" << myVehicle.getID() << " leader=" << leader->getID() << " gap=" << gap << " deltaV=" << deltaV << " futureSpeed=" << futureSpeed << " futureLeaderSpeed=" << futureLeaderSpeed;
1956 futureSpeed = MIN2(futureSpeed, (gapClosingTime * futureSpeed + (foreCastTime - gapClosingTime) * futureLeaderSpeed) / foreCastTime);
1957 //if (DEBUG_COND) std::cout << " newFutureSpeed=" << futureSpeed << "\n";
1958 }
1959 }
1960 }
1961 return futureSpeed;
1962}
1963
1964
1965int
1967 // if this vehicle is blocking someone in front, we maybe decelerate to let him in
1968 if (blocked != nullptr) {
1970#ifdef DEBUG_SLOW_DOWN
1971 if (DEBUG_COND) {
1972 std::cout << SIMTIME
1973 << " veh=" << myVehicle.getID()
1974 << " blocked=" << Named::getIDSecure(blocked)
1975 << " gap=" << gap
1976 << "\n";
1977 }
1978#endif
1979 if (gap > POSITION_EPS) {
1980 //const bool blockedWantsUrgentRight = (((*blocked)->getLaneChangeModel().getOwnState() & LCA_RIGHT != 0)
1981 // && ((*blocked)->getLaneChangeModel().getOwnState() & LCA_URGENT != 0));
1982
1984 //|| blockedWantsUrgentRight // VARIANT_10 (helpblockedRight)
1985 ) {
1986 if (blocked->getSpeed() < SUMO_const_haltingSpeed) {
1988 } else {
1989 state |= LCA_AMBACKBLOCKER;
1990 }
1991 addLCSpeedAdvice(getCarFollowModel().followSpeed(
1993 gap - POSITION_EPS, blocked->getSpeed(),
1994 blocked->getCarFollowModel().getMaxDecel()), false);
1995
1996 //(*blocked) = 0; // VARIANT_14 (furtherBlock)
1997#ifdef DEBUG_SLOW_DOWN
1998 if (DEBUG_COND) {
1999 std::cout << SIMTIME
2000 << " veh=" << myVehicle.getID()
2001 << " slowing down for"
2002 << " blocked=" << Named::getIDSecure(blocked)
2003 << " helpSpeed=" << myLCAccelerationAdvices.back().first
2004 << "\n";
2005 }
2006#endif
2007 } /*else if ((*blocked)->getWaitingSeconds() > 30 && gap > myVehicle.getBrakeGap()) {
2008 // experimental else-branch...
2009
2010 state |= LCA_AMBACKBLOCKER;
2011 addLCSpeedAdvice(getCarFollowModel().followSpeed(
2012 &myVehicle, myVehicle.getSpeed(),
2013 (gap - POSITION_EPS), (*blocked)->getSpeed(),
2014 (*blocked)->getCarFollowModel().getMaxDecel()));
2015 } */
2016 }
2017 }
2018 return state;
2019}
2020
2021
2022void
2024 if (lane->hasPedestrians()) {
2025#ifdef DEBUG_WANTS_CHANGE
2026 if (DEBUG_COND) {
2027 std::cout << SIMTIME << " adapt to pedestrians on lane=" << lane->getID() << "\n";
2028 }
2029#endif
2033 if (leader.first != 0) {
2034 const double stopSpeed = myVehicle.getCarFollowModel().stopSpeed(&myVehicle, myVehicle.getSpeed(), leader.second - myVehicle.getVehicleType().getMinGap());
2035 v = MIN2(v, stopSpeed);
2036#ifdef DEBUG_WANTS_CHANGE
2037 if (DEBUG_COND) {
2038 std::cout << SIMTIME << " pedLeader=" << leader.first->getID() << " dist=" << leader.second << " v=" << v << "\n";
2039 }
2040#endif
2041 }
2042 }
2043}
2044
2045
2046double
2047MSLCM_LC2013::computeSpeedLat(double latDist, double& maneuverDist, bool urgent) const {
2048 double result = MSAbstractLaneChangeModel::computeSpeedLat(latDist, maneuverDist, urgent);
2049#ifdef DEBUG_WANTS_CHANGE
2050 if (DEBUG_COND) {
2051 std::cout << SIMTIME << " veh=" << myVehicle.getID() << " myLeftSpace=" << myLeftSpace << " latDist=" << latDist << " maneuverDist=" << maneuverDist << " result=" << result << "\n";
2052 }
2053#endif
2054 if (myLeftSpace > POSITION_EPS || !urgent) {
2056 if (isChangingLanes()) {
2057 speedBound = MAX2(LC_RESOLUTION_SPEED_LAT, speedBound);
2058 }
2059 result = MAX2(-speedBound, MIN2(speedBound, result));
2060 }
2061 return result;
2062}
2063
2064
2065double
2067 return 1 / myAssertive;
2068}
2069
2070double
2072 return myOppositeParam <= 0 ? std::numeric_limits<double>::max() : 1 / myOppositeParam;
2073}
2074
2075bool
2076MSLCM_LC2013::saveBlockerLength(double length, double foeLeftSpace) {
2077 const bool canReserve = MSLCHelper::canSaveBlockerLength(myVehicle, length, myLeftSpace);
2078 if (!isOpposite() && (canReserve || myLeftSpace > foeLeftSpace)) {
2080#ifdef DEBUG_SAVE_BLOCKER_LENGTH
2081 if (DEBUG_COND) {
2082 std::cout << SIMTIME << " saveBlockerLength veh=" << myVehicle.getID() << " canReserve=" << canReserve << " myLeftSpace=" << myLeftSpace << " foeLeftSpace=" << foeLeftSpace << "\n";
2083 }
2084#endif
2085 if (myLeftSpace == 0 && foeLeftSpace < 0) {
2086 // called from opposite overtaking, myLeftSpace must be initialized
2088 }
2089 return true;
2090 } else {
2091 return false;
2092 }
2093}
2094
2095
2096bool
2097MSLCM_LC2013::hasFreeLane(int laneOffset, const std::pair<MSVehicle*, double>& neighLeadStopped) const {
2098 if (neighLeadStopped.first == nullptr) {
2099 return true;
2100 }
2101 int dir = (laneOffset > 0 ? 1 : -1);
2102 const MSLane* neigh = myVehicle.getLane()->getParallelLane(laneOffset);
2103 if (dir > 0 && !neigh->allowsChangingLeft(myVehicle.getVClass())) {
2104 return false;
2105 } else if (dir < 0 && !neigh->allowsChangingRight(myVehicle.getVClass())) {
2106 return false;
2107 }
2108 int nextOffset = laneOffset + dir;
2109 const MSLane* next = myVehicle.getLane()->getParallelLane(nextOffset);
2110 if (next == nullptr || !next->allowsVehicleClass(myVehicle.getVClass())) {
2111 return false;
2112 }
2113 const double overtakeDist = neighLeadStopped.second + neighLeadStopped.first->getVehicleType().getLengthWithGap() + myVehicle.getLength() + POSITION_EPS;
2114 std::pair<MSVehicle* const, double> nextLead = next->getLeader(&myVehicle, myVehicle.getPositionOnLane(), myVehicle.getBestLanesContinuation(next), overtakeDist);
2115 return nextLead.first == nullptr || nextLead.second >= overtakeDist || hasFreeLane(nextOffset, nextLead);
2116}
2117
2118
2119std::string
2120MSLCM_LC2013::getParameter(const std::string& key) const {
2122 return toString(myStrategicParam);
2123 } else if (key == toString(SUMO_ATTR_LCA_COOPERATIVE_PARAM)) {
2125 } else if (key == toString(SUMO_ATTR_LCA_SPEEDGAIN_PARAM)) {
2126 return toString(mySpeedGainParam);
2127 } else if (key == toString(SUMO_ATTR_LCA_KEEPRIGHT_PARAM)) {
2128 return toString(myKeepRightParam);
2129 } else if (key == toString(SUMO_ATTR_LCA_OPPOSITE_PARAM)) {
2130 return toString(myOppositeParam);
2131 } else if (key == toString(SUMO_ATTR_LCA_LOOKAHEADLEFT)) {
2132 return toString(myLookaheadLeft);
2133 } else if (key == toString(SUMO_ATTR_LCA_SPEEDGAINRIGHT)) {
2134 return toString(mySpeedGainRight);
2135 } else if (key == toString(SUMO_ATTR_LCA_ASSERTIVE)) {
2136 return toString(myAssertive);
2137 } else if (key == toString(SUMO_ATTR_LCA_OVERTAKE_RIGHT)) {
2139 } else if (key == toString(SUMO_ATTR_LCA_SIGMA)) {
2140 return toString(mySigma);
2145 } else if (key == toString(SUMO_ATTR_LCA_STRATEGIC_LOOKAHEAD)) {
2147 } else if (key == toString(SUMO_ATTR_LCA_SPEEDGAIN_LOOKAHEAD)) {
2149 } else if (key == toString(SUMO_ATTR_LCA_SPEEDGAIN_REMAIN_TIME)) {
2153 } else if (key == toString(SUMO_ATTR_LCA_COOPERATIVE_SPEED)) {
2155 } else if (key == toString(SUMO_ATTR_LCA_MAXSPEEDLATSTANDING)) {
2157 } else if (key == toString(SUMO_ATTR_LCA_MAXSPEEDLATFACTOR)) {
2159 } else if (key == toString(SUMO_ATTR_LCA_MAXDISTLATSTANDING)) {
2161 // access to internal state for debugging in sumo-gui (not documented since it may change at any time)
2162 } else if (key == "speedGainProbabilityRight") {
2164 } else if (key == "speedGainProbabilityLeft") {
2166 } else if (key == "keepRightProbability") {
2168 } else if (key == "lookAheadSpeed") {
2169 return toString(myLookAheadSpeed);
2170 // motivation relative to threshold
2171 } else if (key == "speedGainRP") {
2173 } else if (key == "speedGainLP") {
2175 } else if (key == "keepRightP") {
2177 }
2178 throw InvalidArgument("Parameter '" + key + "' is not supported for laneChangeModel of type '" + toString(myModel) + "'");
2179}
2180
2181
2182void
2183MSLCM_LC2013::setParameter(const std::string& key, const std::string& value) {
2184 double doubleValue;
2185 try {
2186 doubleValue = StringUtils::toDouble(value);
2187 } catch (NumberFormatException&) {
2188 throw InvalidArgument("Setting parameter '" + key + "' requires a number for laneChangeModel of type '" + toString(myModel) + "'");
2189 }
2191 myStrategicParam = doubleValue;
2192 } else if (key == toString(SUMO_ATTR_LCA_COOPERATIVE_PARAM)) {
2193 myCooperativeParam = doubleValue;
2194 } else if (key == toString(SUMO_ATTR_LCA_SPEEDGAIN_PARAM)) {
2195 mySpeedGainParam = doubleValue;
2196 } else if (key == toString(SUMO_ATTR_LCA_KEEPRIGHT_PARAM)) {
2197 myKeepRightParam = doubleValue;
2198 } else if (key == toString(SUMO_ATTR_LCA_OPPOSITE_PARAM)) {
2199 myOppositeParam = doubleValue;
2200 } else if (key == toString(SUMO_ATTR_LCA_LOOKAHEADLEFT)) {
2201 myLookaheadLeft = doubleValue;
2202 } else if (key == toString(SUMO_ATTR_LCA_SPEEDGAINRIGHT)) {
2203 mySpeedGainRight = doubleValue;
2204 } else if (key == toString(SUMO_ATTR_LCA_ASSERTIVE)) {
2205 myAssertive = doubleValue;
2206 } else if (key == toString(SUMO_ATTR_LCA_OVERTAKE_RIGHT)) {
2207 myOvertakeRightParam = doubleValue;
2208 } else if (key == toString(SUMO_ATTR_LCA_SIGMA)) {
2209 mySigma = doubleValue;
2211 myKeepRightAcceptanceTime = doubleValue;
2213 myOvertakeDeltaSpeedFactor = doubleValue;
2214 } else if (key == toString(SUMO_ATTR_LCA_STRATEGIC_LOOKAHEAD)) {
2215 myStrategicLookahead = doubleValue;
2216 } else if (key == toString(SUMO_ATTR_LCA_SPEEDGAIN_LOOKAHEAD)) {
2217 mySpeedGainLookahead = doubleValue;
2218 } else if (key == toString(SUMO_ATTR_LCA_SPEEDGAIN_REMAIN_TIME)) {
2219 mySpeedGainRemainTime = doubleValue;
2221 myRoundaboutBonus = doubleValue;
2222 } else if (key == toString(SUMO_ATTR_LCA_COOPERATIVE_SPEED)) {
2223 myCooperativeSpeed = doubleValue;
2224 } else if (key == toString(SUMO_ATTR_LCA_MAXSPEEDLATSTANDING)) {
2225 myMaxSpeedLatStanding = doubleValue;
2226 } else if (key == toString(SUMO_ATTR_LCA_MAXSPEEDLATFACTOR)) {
2227 myMaxSpeedLatFactor = doubleValue;
2228 } else if (key == toString(SUMO_ATTR_LCA_MAXDISTLATSTANDING)) {
2229 myMaxDistLatStanding = doubleValue;
2230 // access to internal state
2231 } else if (key == "speedGainProbabilityRight") {
2232 mySpeedGainProbabilityRight = (long long int)(doubleValue * HYST_PRECISION);
2233 } else if (key == "speedGainProbabilityLeft") {
2234 mySpeedGainProbabilityLeft = (long long int)(doubleValue * HYST_PRECISION);
2235 } else if (key == "keepRightProbability") {
2236 myKeepRightProbability = (long long int)(-doubleValue * HYST_PRECISION);
2237 } else if (key == "lookAheadSpeed") {
2238 myLookAheadSpeed = doubleValue;
2239 } else {
2240 throw InvalidArgument("Setting parameter '" + key + "' is not supported for laneChangeModel of type '" + toString(myModel) + "'");
2241 }
2243}
2244
2245
2246void
2249 std::vector<long long int> lcState;
2250 lcState.push_back(mySpeedGainProbabilityLeft);
2251 lcState.push_back(mySpeedGainProbabilityRight);
2252 lcState.push_back(myKeepRightProbability);
2253 lcState.push_back(myLookAheadSpeed * HYST_PRECISION);
2254 lcState.push_back(myDontBrake);
2255 out.writeAttr(SUMO_ATTR_LCSTATE2, lcState);
2256}
2257
2258void
2261 if (attrs.hasAttribute(SUMO_ATTR_LCSTATE2)) {
2262 std::istringstream bis(attrs.getString(SUMO_ATTR_LCSTATE2));
2266 long long laSpeed;
2267 bis >> laSpeed;
2268 myLookAheadSpeed = (double)laSpeed / HYST_PRECISION;
2269 bis >> myDontBrake;
2270 }
2271}
2272
2273
2274
2275/****************************************************************************/
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.
static bool myAllowOvertakingRight
whether overtaking on the right is permitted
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
void setSpeedLat(double speedLat)
set the lateral speed and update lateral acceleraton
const MSCFModel & getCarFollowModel() const
The vehicle's car following model.
virtual void loadState(const SUMOSAXAttributes &attrs)
Loads the state of the laneChangeModel from the given attributes.
MSVehicle & myVehicle
The vehicle this lane-changer belongs to.
bool isChangingLanes() const
return true if the vehicle currently performs a lane change maneuver
double getImpatience() const
Returns this vehicles impatience.
int getNumRemainingEdges() const
return the number of edges remaining in the route (include the current)
double getLength() const
Returns the vehicle's length.
double getWaitingSeconds() const
Returns the number of seconds waited (speed was lesser than 0.1m/s)
const MSStop & getNextStop() const
SUMOVehicleClass getVClass() const
Returns the vehicle's access class.
const MSVehicleType & getVehicleType() const
Returns the vehicle's type definition.
bool isStopped() const
Returns whether the vehicle is at a stop.
The car-following model abstraction.
Definition MSCFModel.h:57
static double gapExtrapolation(const double duration, const double currentGap, double v1, double v2, double a1=0, double a2=0, const double maxV1=std::numeric_limits< double >::max(), const double maxV2=std::numeric_limits< double >::max())
return the resulting gap if, starting with gap currentGap, two vehicles continue with constant accele...
virtual double minNextSpeedEmergency(double speed, const MSVehicle *const veh=0) const
Returns the minimum speed after emergency braking, given the current speed (depends on the numerical ...
virtual double minNextSpeed(double speed, const MSVehicle *const veh=0) const
Returns the minimum speed given the current speed (depends on the numerical update scheme and its ste...
double maximumSafeFollowSpeed(double gap, double egoSpeed, double predSpeed, double predMaxDecel, bool onInsertion=false) const
Returns the maximum safe velocity for following the given leader.
@ LANE_CHANGE
the return value is used for lane change calculations
Definition MSCFModel.h:87
virtual double getSecureGap(const MSVehicle *const veh, const MSVehicle *const, const double speed, const double leaderSpeed, const double leaderMaxDecel) const
Returns the minimum gap to reserve if the leader is braking at maximum (>=0)
double getMaxAccel() const
Get the vehicle type's maximum acceleration [m/s^2].
Definition MSCFModel.h:261
double brakeGap(const double speed) const
Returns the distance the vehicle needs to halt including driver's reaction time tau (i....
Definition MSCFModel.h:408
double maximumSafeStopSpeed(double gap, double decel, double currentSpeed, bool onInsertion=false, double headway=-1, bool relaxEmergency=true) const
Returns the maximum next velocity for stopping within gap.
double getMaxDecel() const
Get the vehicle type's maximal comfortable deceleration [m/s^2].
Definition MSCFModel.h:269
virtual double getSpeedAfterMaxDecel(double v) const
Returns the velocity after maximum deceleration.
Definition MSCFModel.h:431
virtual double followSpeed(const MSVehicle *const veh, double speed, double gap2pred, double predSpeed, double predMaxDecel, const MSVehicle *const pred=0, const CalcReason usage=CalcReason::CURRENT) const =0
Computes the vehicle's follow speed (no dawdling)
double stopSpeed(const MSVehicle *const veh, const double speed, double gap, const CalcReason usage=CalcReason::CURRENT) const
Computes the vehicle's safe speed for approaching a non-moving obstacle (no dawdling)
Definition MSCFModel.h:173
const std::set< MSTransportable *, ComparatorNumericalIdLess > & getPersons() const
Returns this edge's persons set.
Definition MSEdge.h:204
bool hasLaneChanger() const
Definition MSEdge.h:749
bool isRoundabout() const
Definition MSEdge.h:732
bool isInternal() const
return whether this edge is an internal edge
Definition MSEdge.h:269
static bool gSemiImplicitEulerUpdate
Definition MSGlobals.h:53
static bool isBidiFollower(const MSVehicle *ego, const MSVehicle *follower)
static bool canSaveBlockerLength(const MSVehicle &veh, double requested, double leftSpace)
static double getSpeedPreservingSecureGap(const MSVehicle &leader, const MSVehicle &follower, double currentGap, double leaderPlannedSpeed)
static double getRoundaboutDistBonus(const MSVehicle &veh, double bonusParam, const MSVehicle::LaneQ &curr, const MSVehicle::LaneQ &neigh, const MSVehicle::LaneQ &best)
static bool isBidiLeader(const MSVehicle *leader, const std::vector< MSLane * > &cont)
static bool updateBlockerLength(const MSVehicle &veh, MSVehicle *blocker, int lcaCounter, double leftSpace, bool reliefConnection, double &leadingBlockerLength)
static bool divergentRoute(const MSVehicle &v1, const MSVehicle &v2)
return whether the vehicles are on the same junction but on divergent paths
bool currentDistAllows(double dist, int laneOffset, double lookForwardDist)
int wantsChange(int laneOffset, MSAbstractLaneChangeModel::MSLCMessager &msgPass, int blocked, const std::pair< MSVehicle *, double > &leader, const std::pair< MSVehicle *, double > &follower, const std::pair< MSVehicle *, double > &neighLead, const std::pair< MSVehicle *, double > &neighFollow, const MSLane &neighLane, const std::vector< MSVehicle::LaneQ > &preb, MSVehicle **lastBlocked, MSVehicle **firstBlocked) override
Called to examine whether the vehicle wants to change using the given laneOffset. This method gets th...
void informFollower(MSAbstractLaneChangeModel::MSLCMessager &msgPass, int blocked, int dir, const std::pair< MSVehicle *, double > &neighFollow, double remainingSeconds, double plannedSpeed)
decide whether we will try cut in before the follower or allow to be overtaken
long long int myKeepRightProbability
double computeSpeedLat(double latDist, double &maneuverDist, bool urgent) const override
decides the next lateral speed (for continuous lane changing)
double myOvertakeDeltaSpeedFactor
double myLookAheadSpeed
bool debugVehicle() const override
whether the current vehicles shall be debugged
double myStrategicParam
long long int mySpeedGainProbabilityRight
double myRoundaboutBonus
double mySpeedGainLookahead
const double myExperimentalParam1
double patchSpeed(const double min, const double wanted, const double max, const MSCFModel &cfModel) override
Called to adapt the speed in order to allow a lane change. It uses information on LC-related desired ...
void initDerivedParameters()
init cached parameters derived directly from model parameters
double myCooperativeParam
MSLCM_LC2013(MSVehicle &v)
double anticipateFollowSpeed(const std::pair< MSVehicle *, double > &leaderDist, double dist, double vMax, bool acceleratingLeader)
anticipate future follow speed for the given leader
std::string getParameter(const std::string &key) const override
try to retrieve the given parameter from this device. Throw exception for unsupported key
void setParameter(const std::string &key, const std::string &value) override
try to set the given parameter for this laneChangeModel. Throw exception for unsupported key
bool hasFreeLane(int laneOffset, const std::pair< MSVehicle *, double > &neighLeadStopped) const
whether there is a lane beyond laneOffset that can be used to overtake the stopped leader on the neig...
double myCooperativeSpeed
double informLeader(MSAbstractLaneChangeModel::MSLCMessager &msgPass, int blocked, int dir, const std::pair< MSVehicle *, double > &neighLead, double remainingSeconds)
double _patchSpeed(double min, const double wanted, double max, const MSCFModel &cfModel)
double mySpeedGainParam
double myLookaheadLeft
double myLeadingBlockerLength
int _wantsChange(int laneOffset, MSAbstractLaneChangeModel::MSLCMessager &msgPass, int blocked, const std::pair< MSVehicle *, double > &leader, const std::pair< MSVehicle *, double > &follower, const std::pair< MSVehicle *, double > &neighLead, const std::pair< MSVehicle *, double > &neighFollow, const MSLane &neighLane, const std::vector< MSVehicle::LaneQ > &preb, MSVehicle *lastBlocked, MSVehicle *firstBlocked)
helper function for doing the actual work
std::pair< double, int > Info
information regarding save velocity (unused) and state flags of the ego vehicle
void prepareStep() override
double getSafetyFactor() const override
return factor for modifying the safety constraints of the car-following model
double myLeftSpace
double myOppositeParam
bool amBlockingFollowerPlusNB()
double myKeepRightParam
bool currentDistDisallows(double dist, int laneOffset, double lookForwardDist)
void adaptSpeedToPedestrians(const MSLane *lane, double &v)
react to pedestrians on the given lane
virtual void saveState(OutputDevice &out) const override
Save the state of the laneChangeModel.
virtual ~MSLCM_LC2013()
long long int myChangeProbThresholdRight
double getOppositeSafetyFactor() const override
return factor for modifying the safety constraints for opposite-diretction overtaking of the car-foll...
long long int mySpeedGainProbabilityLeft
a value for tracking the probability that a change to that side is beneficial
void resetState() override
double mySpeedGainRight
double myKeepRightAcceptanceTime
double mySpeedGainUrgency
int slowDownForBlocked(MSVehicle *blocked, int state)
compute useful slowdowns for blocked vehicles
bool saveBlockerLength(double length, double foeLeftSpace) override
reserve space at the end of the lane to avoid dead locks
void changed() override
double mySpeedGainRemainTime
void * inform(void *info, MSVehicle *sender) override
long long int myChangeProbThresholdLeft
virtual void loadState(const SUMOSAXAttributes &attrs) override
Loads the state of the laneChangeModel from the given attributes.
static double overtakeDistance(const MSVehicle *follower, const MSVehicle *leader, const double gap, double followerSpeed=INVALID_SPEED, double leaderSpeed=INVALID_SPEED)
Representation of a lane in the micro simulation.
Definition MSLane.h:84
std::pair< const MSPerson *, double > nextBlocking(double minPos, double minRight, double maxLeft, double stopTime=0, bool bidi=false) const
This is just a wrapper around MSPModel::nextBlocking. You should always check using hasPedestrians be...
Definition MSLane.cpp:4601
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:2877
bool isAccelLane() const
return whether this lane is an acceleration lane
Definition MSLane.h:544
double getSpeedLimit() const
Returns the lane's maximum allowed speed.
Definition MSLane.h:603
double getLength() const
Returns the lane's length.
Definition MSLane.h:617
bool allowsChangingLeft(SUMOVehicleClass vclass) const
Returns whether the given vehicle class may change left from this lane.
Definition MSLane.h:948
bool allowsVehicleClass(SUMOVehicleClass vclass) const
Definition MSLane.h:941
double getVehicleMaxSpeed(const SUMOTrafficObject *const veh) const
Returns the lane's maximum speed, given a vehicle's speed limit adaptation.
Definition MSLane.h:575
bool hasPedestrians() const
whether the lane has pedestrians on it
Definition MSLane.cpp:4594
int getIndex() const
Returns the lane's index.
Definition MSLane.h:653
double getBruttoOccupancy() const
Returns the brutto (including minGaps) occupancy of this lane during the last step.
Definition MSLane.cpp:3423
bool isNormal() const
Definition MSLane.cpp:2647
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:2946
MSLane * getBidiLane() const
retrieve bidirectional lane or nullptr
Definition MSLane.cpp:4706
MSEdge & getEdge() const
Returns the lane's edge.
Definition MSLane.h:775
const MSLane * getNormalPredecessorLane() const
get normal lane leading to this internal lane, for normal lanes, the lane itself is returned
Definition MSLane.cpp:3268
const std::vector< MSLink * > & getLinkCont() const
returns the container with all links !!!
Definition MSLane.h:735
static MSNet * getInstance()
Returns the pointer to the unique instance of MSNet (singleton).
Definition MSNet.cpp:199
SUMOTime getCurrentTimeStep() const
Returns the current simulation step.
Definition MSNet.h:334
const MSLane * lane
The lane to stop at (microsim only)
Definition MSStop.h:50
double changeRequestRemainingSeconds(const SUMOTime currentTime) const
Return the remaining number of seconds of the current laneTimeLine assuming one exists.
Representation of a vehicle in the micro simulation.
Definition MSVehicle.h:77
double getActionStepLengthSecs() const
Returns the vehicle's action step length in secs, i.e. the interval between two action points.
Definition MSVehicle.h:533
int influenceChangeDecision(int state)
allow TraCI to influence a lane change decision
double getMaxSpeedOnLane() const
Returns the maximal speed for the vehicle on its current lane (including speed factor and deviation,...
double nextStopDist() const
return the distance to the next stop or doubleMax if there is none.
Definition MSVehicle.h:1038
double getAcceleration() const
Returns the vehicle's acceleration in m/s (this is computed as the last step's mean acceleration in c...
Definition MSVehicle.h:514
const std::vector< MSLane * > & getBestLanesContinuation() const
Returns the best sequence of lanes to continue the route starting at myLane.
int getBestLaneOffset() const
const MSEdge * getCurrentEdge() const
Returns the edge the vehicle is currently at (possibly an internal edge or nullptr)
const MSLane * getLane() const
Returns the lane the vehicle is on.
Definition MSVehicle.h:581
double getLastStepDist() const
Get the distance the vehicle covered in the previous timestep.
Definition MSVehicle.h:381
Influencer & getInfluencer()
double getRightSideOnLane() const
Get the lateral position of the vehicles right side on the lane:
double getLateralPositionOnLane() const
Get the vehicle's lateral position on the lane.
Definition MSVehicle.h:413
bool congested() const
double getSpeed() const
Returns the vehicle's current speed.
Definition MSVehicle.h:490
const std::vector< LaneQ > & getBestLanes() const
Returns the description of best lanes to use in order to continue the route.
const MSCFModel & getCarFollowModel() const
Returns the vehicle's car following model definition.
Definition MSVehicle.h:969
double getPositionOnLane() const
Get the vehicle's position along the lane.
Definition MSVehicle.h:374
double getLateralOverlap() const
return the amount by which the vehicle extends laterally outside it's primary lane
void setLateralPositionOnLane(double posLat)
Definition MSVehicle.h:417
double getLengthWithGap() const
Get vehicle's length including the minimum gap [m].
double getWidth() const
Get the width which vehicles of this class shall have when being drawn.
double getMinGap() const
Get the free space in front of vehicles of this class.
double getMaxSpeedLat() const
Get vehicle's maximum lateral speed [m/s].
double getLength() const
Get vehicle's length [m].
static std::string getIDSecure(const T *obj, const std::string &fallBack="NULL")
get an identifier for Named-like object which may be Null
Definition Named.h:67
const std::string & getID() const
Returns the id.
Definition Named.h:74
void step(double dt)
evolve for a time step of length dt.
Static storage of an output device and its base (abstract) implementation.
OutputDevice & writeAttr(const ATTR_TYPE &attr, const T &val, const bool isNull=false)
writes a named attribute
Encapsulated SAX-Attributes.
virtual std::string getString(int id, bool *isPresent=nullptr) const =0
Returns the string-value of the named (by its enum-value) attribute.
virtual bool hasAttribute(int id) const =0
Returns the information whether the named (by its enum-value) attribute is within the current list.
static double toDouble(const std::string &sData)
converts a string into the double value described by it by calling the char-type converter
#define UNUSED_PARAMETER(x)
#define DEBUG_COND
A structure representing the best lanes for continuing the current route starting at 'lane'.
Definition MSVehicle.h:857
double length
The overall length which may be driven when using this lane without a lane change.
Definition MSVehicle.h:861
std::vector< MSLane * > bestContinuations
Definition MSVehicle.h:877
MSLane * lane
The described lane.
Definition MSVehicle.h:859
int bestLaneOffset
The (signed) number of lanes to be crossed to get to the lane which allows to continue the drive.
Definition MSVehicle.h:869
double occupation
The overall vehicle sum on consecutive lanes which can be passed without a lane change.
Definition MSVehicle.h:865