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