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