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