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