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