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