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