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