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.org/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 LOOK_FORWARD 10.
48
49#define JAM_FACTOR 1.
50
51#define LCA_RIGHT_IMPATIENCE -1.
52#define CUT_IN_LEFT_SPEED_THRESHOLD 27.
53
54#define LOOK_AHEAD_MIN_SPEED 0.0
55#define LOOK_AHEAD_SPEED_MEMORY 0.9
56
57#define HELP_DECEL_FACTOR 1.0
58
59#define HELP_OVERTAKE (10.0 / 3.6)
60#define MIN_FALLBEHIND (7.0 / 3.6)
61
62#define RELGAIN_NORMALIZATION_MIN_SPEED 10.0
63#define URGENCY 2.0
64#define OPPOSITE_URGENCY 5.0
65
66#define KEEP_RIGHT_TIME 5.0 // the number of seconds after which a vehicle should move to the right lane
67
68#define KEEP_RIGHT_HEADWAY 2.0
69#define MAX_ONRAMP_LENGTH 200.
70#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
71
72#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
73
74#define REACT_TO_STOPPED_DISTANCE 100
75
76// ===========================================================================
77// debug defines
78// ===========================================================================
79//#define DEBUG_CONSTRUCTOR
80//#define DEBUG_PATCH_SPEED
81//#define DEBUG_INFORMED
82//#define DEBUG_INFORMER
83//#define DEBUG_WANTS_CHANGE
84//#define DEBUG_SLOW_DOWN
85//#define DEBUG_COOPERATE
86//#define DEBUG_SAVE_BLOCKER_LENGTH
87
88//#define DEBUG_COND (myVehicle.getID() == "disabled")
89#define DEBUG_COND (myVehicle.isSelected())
90//#define DEBUG_COND (false)
91
92// ===========================================================================
93// member method definitions
94// ===========================================================================
97 mySpeedGainProbability(0),
98 myKeepRightProbability(0),
99 myLeadingBlockerLength(0),
100 myLeftSpace(0),
101 myLookAheadSpeed(LOOK_AHEAD_MIN_SPEED),
102 myStrategicParam(v.getVehicleType().getParameter().getLCParam(SUMO_ATTR_LCA_STRATEGIC_PARAM, 1)),
103 myCooperativeParam(v.getVehicleType().getParameter().getLCParam(SUMO_ATTR_LCA_COOPERATIVE_PARAM, 1)),
104 mySpeedGainParam(v.getVehicleType().getParameter().getLCParam(SUMO_ATTR_LCA_SPEEDGAIN_PARAM, 1)),
105 myKeepRightParam(v.getVehicleType().getParameter().getLCParam(SUMO_ATTR_LCA_KEEPRIGHT_PARAM, 1)),
106 myOppositeParam(v.getVehicleType().getParameter().getLCParam(SUMO_ATTR_LCA_OPPOSITE_PARAM, 1)),
107 myLookaheadLeft(v.getVehicleType().getParameter().getLCParam(SUMO_ATTR_LCA_LOOKAHEADLEFT, 2.0)),
108 mySpeedGainRight(v.getVehicleType().getParameter().getLCParam(SUMO_ATTR_LCA_SPEEDGAINRIGHT, 0.1)),
109 myAssertive(v.getVehicleType().getParameter().getLCParam(SUMO_ATTR_LCA_ASSERTIVE, 1)),
110 mySpeedGainLookahead(v.getVehicleType().getParameter().getLCParam(SUMO_ATTR_LCA_SPEEDGAIN_LOOKAHEAD, 0)),
111 myRoundaboutBonus(v.getVehicleType().getParameter().getLCParam(SUMO_ATTR_LCA_COOPERATIVE_ROUNDABOUT, myCooperativeParam)),
112 myCooperativeSpeed(v.getVehicleType().getParameter().getLCParam(SUMO_ATTR_LCA_COOPERATIVE_SPEED, myCooperativeParam)),
113 myKeepRightAcceptanceTime(v.getVehicleType().getParameter().getLCParam(SUMO_ATTR_LCA_KEEPRIGHT_ACCEPTANCE_TIME, -1)),
114 myOvertakeDeltaSpeedFactor(v.getVehicleType().getParameter().getLCParam(SUMO_ATTR_LCA_OVERTAKE_DELTASPEED_FACTOR, 0)),
115 myExperimentalParam1(v.getVehicleType().getParameter().getLCParam(SUMO_ATTR_LCA_EXPERIMENTAL1, 0)) {
117#ifdef DEBUG_CONSTRUCTOR
118 if (DEBUG_COND) {
119 std::cout << SIMTIME
120 << " create lcModel veh=" << myVehicle.getID()
121 << " lcStrategic=" << myStrategicParam
122 << " lcCooperative=" << myCooperativeParam
123 << " lcSpeedGain=" << mySpeedGainParam
124 << " lcKeepRight=" << myKeepRightParam
125 << "\n";
126 }
127#endif
128}
129
131 changed();
132}
133
134
135void
137 if (mySpeedGainParam <= 0) {
138 myChangeProbThresholdRight = std::numeric_limits<double>::max();
139 myChangeProbThresholdLeft = std::numeric_limits<double>::max();
140 } else {
143 }
144}
145
146
147bool
149 return DEBUG_COND;
150}
151
152
153int
155 int laneOffset,
157 int blocked,
158 const std::pair<MSVehicle*, double>& leader,
159 const std::pair<MSVehicle*, double>& follower,
160 const std::pair<MSVehicle*, double>& neighLead,
161 const std::pair<MSVehicle*, double>& neighFollow,
162 const MSLane& neighLane,
163 const std::vector<MSVehicle::LaneQ>& preb,
164 MSVehicle** lastBlocked,
165 MSVehicle** firstBlocked) {
166
167#ifdef DEBUG_WANTS_CHANGE
168 if (DEBUG_COND) {
169 std::cout << "\nWANTS_CHANGE\n" << SIMTIME
170 << std::setprecision(gPrecision)
171 << " veh=" << myVehicle.getID()
172 << " lane=" << myVehicle.getLane()->getID()
173 << " pos=" << myVehicle.getPositionOnLane()
174 << " posLat=" << myVehicle.getLateralPositionOnLane()
175 << " speed=" << myVehicle.getSpeed()
176 << " considerChangeTo=" << (laneOffset == -1 ? "right" : "left")
177 << "\n";
178 }
179#endif
180
181 const int result = _wantsChange(laneOffset, msgPass, blocked, leader, follower, neighLead, neighFollow, neighLane, preb, lastBlocked, firstBlocked);
182
183#ifdef DEBUG_WANTS_CHANGE
184 if (DEBUG_COND) {
185 std::cout << SIMTIME << " veh=" << myVehicle.getID() << " result=" << toString((LaneChangeAction)result) << " blocked=" << toString((LaneChangeAction)blocked) << "\n\n\n";
186 }
187#endif
188
189 return result;
190}
191
192
193double
194MSLCM_LC2013::patchSpeed(const double min, const double wanted, const double max, const MSCFModel& cfModel) {
195
196#ifdef DEBUG_PATCH_SPEED
197 if (DEBUG_COND) {
198 std::cout << "\nPATCH_SPEED\n"
199 << SIMTIME
200 << " veh=" << myVehicle.getID()
201 << " lane=" << myVehicle.getLane()->getID()
202 << " pos=" << myVehicle.getPositionOnLane()
203 << " v=" << myVehicle.getSpeed()
204 << " min=" << min
205 << " wanted=" << wanted
206 << " max=" << max
207 << "\n";
208 }
209#endif
210
211 // negative min speed may be passed when using ballistic updated
212 const double newSpeed = _patchSpeed(MAX2(min, 0.0), wanted, max, cfModel);
213
214#ifdef DEBUG_PATCH_SPEED
215 if (DEBUG_COND) {
216 const std::string patched = (wanted != newSpeed ? " patched=" + toString(newSpeed) : "");
217 std::cout << patched
218 << "\n";
219 }
220#endif
221
222 return newSpeed;
223}
224
225
226double
227MSLCM_LC2013::_patchSpeed(double min, const double wanted, double max, const MSCFModel& cfModel) {
228 int state = myOwnState;
229#ifdef DEBUG_PATCH_SPEED
230 if (DEBUG_COND) {
231 std::cout
232 << "\n" << SIMTIME << std::setprecision(gPrecision)
233 << " patchSpeed state=" << toString((LaneChangeAction)state) << " myLCAccelerationAdvices=" << toString(myLCAccelerationAdvices)
234 << "\n speed=" << myVehicle.getSpeed() << " min=" << min << " wanted=" << wanted
235 << "\n myLeadingBlockerLength=" << myLeadingBlockerLength
236 << "\n";
237 }
238#endif
239
240 // letting vehicles merge in at the end of the lane in case of counter-lane change, step#2
241 double MAGIC_offset = 1.;
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) {
246 double space = myLeftSpace - myLeadingBlockerLength - MAGIC_offset - myVehicle.getVehicleType().getMinGap();
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
1242 && leader.first != nullptr
1243 && leader.first->getLane()->getBidiLane() != nullptr
1244 && std::find(curr.bestContinuations.begin(), curr.bestContinuations.end(), leader.first->getLane()->getBidiLane()) != curr.bestContinuations.end());
1245
1246 if (bestLaneOffset == 0 && hasBidiLeader) {
1247 // getting out of the way is enough to clear the blockage
1248 laDist = 0;
1249 } else if (bestLaneOffset == 0 && hasStoppedLeader) {
1250 // react to a stopped leader on the current lane
1251 // The value of laDist is doubled below for the check whether the lc-maneuver can be taken out
1252 // on the remaining distance (because the vehicle has to change back and forth). Therefore multiply with 0.5.
1253 laDist = 0.5 * (myVehicle.getVehicleType().getLengthWithGap()
1254 + leader.first->getVehicleType().getLengthWithGap()
1255 + leader.second);
1256 } else if (bestLaneOffset == laneOffset && neighLead.first != 0 && neighLead.first->isStopped() && neighLead.second < (currentDist - posOnLane)) {
1257 // react to a stopped leader on the target lane (if it is the bestLane)
1258 if (isOpposite()) {
1259 // always allow changing back
1261 + neighLead.first->getVehicleType().getLengthWithGap()
1262 + neighLead.second);
1263 } else if (!hasStoppedLeader &&
1264 (neighLead.second + myVehicle.getVehicleType().getLengthWithGap() + neighLead.first->getVehicleType().getLengthWithGap()) < (currentDist - posOnLane)) {
1265 // do not change to the target lane until passing the stopped vehicle
1266 // (unless the vehicle blocks our intended stopping position, then we have to wait anyway)
1267 changeToBest = false;
1268 }
1269 }
1270 if (myStrategicParam < 0) {
1271 laDist = -1e3; // never perform strategic change
1272 }
1273
1274 // free space that is available for changing
1275 //const double neighSpeed = (neighLead.first != 0 ? neighLead.first->getSpeed() :
1276 // neighFollow.first != 0 ? neighFollow.first->getSpeed() :
1277 // best.lane->getSpeedLimit());
1278 // @note: while this lets vehicles change earlier into the correct direction
1279 // it also makes the vehicles more "selfish" and prevents changes which are necessary to help others
1280
1281
1282
1283 // Next we assign to roundabout edges a larger distance than to normal edges
1284 // in order to decrease sense of lc urgency and induce higher usage of inner roundabout lanes.
1285 const double roundaboutBonus = MSLCHelper::getRoundaboutDistBonus(myVehicle, myRoundaboutBonus, curr, neigh, best);
1286 currentDist += roundaboutBonus;
1287 neighDist += roundaboutBonus;
1288
1289 const double usableDist = MAX2(currentDist - posOnLane - best.occupation * JAM_FACTOR, driveToNextStop);
1290 //- (best.lane->getVehicleNumber() * neighSpeed)); // VARIANT 9 jfSpeed
1291 const double maxJam = MAX2(preb[currIdx + prebOffset].occupation, preb[currIdx].occupation);
1292 const double vMax = myVehicle.getLane()->getVehicleMaxSpeed(&myVehicle);
1293 const double neighVMax = neighLane.getVehicleMaxSpeed(&myVehicle);
1294 // upper bound which will be restricted successively
1295 double thisLaneVSafe = vMax;
1296 const bool checkOverTakeRight = avoidOvertakeRight();
1297
1298 double neighLeftPlace = MAX2(0.0, neighDist - posOnLane - maxJam);
1299 if (neighLead.first != 0 && neighLead.first->isStopped()) {
1300 neighLeftPlace = MIN2(neighLeftPlace, neighLead.second);
1301 }
1302
1303#ifdef DEBUG_WANTS_CHANGE
1304 if (DEBUG_COND) {
1305 std::cout << STEPS2TIME(currentTime)
1306 << " veh=" << myVehicle.getID()
1307 << " laSpeed=" << myLookAheadSpeed
1308 << " laDist=" << laDist
1309 << " currentDist=" << currentDist
1310 << " usableDist=" << usableDist
1311 << " bestLaneOffset=" << bestLaneOffset
1312 << " best.occupation=" << best.occupation
1313 << " best.length=" << best.length
1314 << "\n roundaboutBonus=" << roundaboutBonus
1315 << " maxJam=" << maxJam
1316 << " neighDist=" << neighDist
1317 << " neighLeftPlace=" << neighLeftPlace
1318 << "\n";
1319 }
1320#endif
1321
1322 bool changeLeftToAvoidOvertakeRight = false;
1323 if (changeToBest && bestLaneOffset == curr.bestLaneOffset
1324 && currentDistDisallows(usableDist, bestLaneOffset, laDist)) {
1326 ret = ret | lca | LCA_STRATEGIC | LCA_URGENT;
1327 } else {
1328 // VARIANT_20 (noOvertakeRight)
1329 if (neighLead.first != 0 && checkOverTakeRight && !right) {
1330 // check for slower leader on the left. we should not overtake but
1331 // rather move left ourselves (unless congested)
1332 MSVehicle* nv = neighLead.first;
1333 const double deltaV = MAX2(vMax - neighLane.getVehicleMaxSpeed(nv),
1334 myVehicle.getSpeed() - nv->getSpeed());
1335 if (deltaV > 0) {
1336 const double vMaxDecel = getCarFollowModel().getSpeedAfterMaxDecel(myVehicle.getSpeed());
1337 const double vSafeFollow = getCarFollowModel().followSpeed(
1338 &myVehicle, myVehicle.getSpeed(), neighLead.second, nv->getSpeed(), nv->getCarFollowModel().getMaxDecel());
1339 const double vStayBehind = nv->getSpeed() - HELP_OVERTAKE;
1340 double vSafe;
1341 if (vSafeFollow >= vMaxDecel) {
1342 vSafe = vSafeFollow;
1343 } else {
1344 vSafe = MAX2(vMaxDecel, vStayBehind);
1345 }
1347 vSafe = MAX2(vSafe, nv->getSpeed());
1348 }
1349 thisLaneVSafe = MIN2(thisLaneVSafe, vSafe);
1350 addLCSpeedAdvice(vSafe);
1351 // only generate impulse for overtaking left shortly before braking would be necessary
1352 const double deltaGapFuture = deltaV * 8;
1353 const double vSafeFuture = getCarFollowModel().followSpeed(
1354 &myVehicle, myVehicle.getSpeed(), neighLead.second - deltaGapFuture, nv->getSpeed(), nv->getCarFollowModel().getMaxDecel());
1355 if (vSafeFuture < vSafe) {
1356 const double relativeGain = deltaV / MAX2(vMax,
1359 changeLeftToAvoidOvertakeRight = true;
1360 }
1361#ifdef DEBUG_WANTS_CHANGE
1362 if (DEBUG_COND) {
1363 std::cout << STEPS2TIME(currentTime)
1364 << " avoid overtaking on the right nv=" << nv->getID()
1365 << " deltaV=" << deltaV
1366 << " nvSpeed=" << nv->getSpeed()
1367 << " mySpeedGainProbability=" << mySpeedGainProbability
1368 << " planned acceleration =" << myLCAccelerationAdvices.back().first
1369 << "\n";
1370 }
1371#endif
1372 }
1373 }
1374 const bool currFreeUntilNeighEnd = leader.first == nullptr || neighDist - posOnLane <= leader.second;
1375 const double overtakeDist = (leader.first == 0 ? -1 :
1376 leader.second + myVehicle.getVehicleType().getLength() + leader.first->getVehicleType().getLengthWithGap());
1377 if (leader.first != 0 && (leader.first->isStopped() || hasBidiLeader) && leader.second < REACT_TO_STOPPED_DISTANCE
1378 // current destination leaves enough space to overtake the leader
1379 && MIN2(neighDist, currentDist) - posOnLane > overtakeDist
1380 // maybe do not overtake on the right at high speed
1381 && (!checkOverTakeRight || !right)
1382 && myStrategicParam >= 0
1383 && (neighLead.first == 0 || !neighLead.first->isStopped()
1384 // neighboring stopped vehicle leaves enough space to overtake leader
1385 || neighLead.second > overtakeDist)) {
1386 // avoid becoming stuck behind a stopped leader
1387 currentDist = myVehicle.getPositionOnLane() + leader.second;
1388#ifdef DEBUG_WANTS_CHANGE
1389 if (DEBUG_COND) {
1390 std::cout << " veh=" << myVehicle.getID() << " overtake stopped leader=" << leader.first->getID()
1391 << " overtakeDist=" << overtakeDist
1392 << " remaining=" << MIN2(neighDist, currentDist) - posOnLane
1393 << "\n";
1394 }
1395#endif
1396 ret = ret | lca | LCA_STRATEGIC | LCA_URGENT;
1397 } else if (!changeToBest && (currentDistDisallows(neighLeftPlace, abs(bestLaneOffset) + 2, laDist))) {
1398 // the opposite lane-changing direction should be done than the one examined herein
1399 // we'll check whether we assume we could change anyhow and get back in time...
1400 //
1401 // this rule prevents the vehicle from moving in opposite direction of the best lane
1402 // unless the way till the end where the vehicle has to be on the best lane
1403 // is long enough
1404#ifdef DEBUG_WANTS_CHANGE
1405 if (DEBUG_COND) {
1406 std::cout << " veh=" << myVehicle.getID() << " could not change back and forth in time (1) neighLeftPlace=" << neighLeftPlace << "\n";
1407 }
1408#endif
1409 ret = ret | LCA_STAY | LCA_STRATEGIC;
1410 } else if (bestLaneOffset == 0 && (neighLeftPlace * 2. < laDist)) {
1411 // the current lane is the best and a lane-changing would cause a situation
1412 // of which we assume we will not be able to return to the lane we have to be on.
1413 // this rule prevents the vehicle from leaving the current, best lane when it is
1414 // close to this lane's end
1415#ifdef DEBUG_WANTS_CHANGE
1416 if (DEBUG_COND) {
1417 std::cout << " veh=" << myVehicle.getID() << " could not change back and forth in time (2) neighLeftPlace=" << neighLeftPlace << "\n";
1418 }
1419#endif
1420 ret = ret | LCA_STAY | LCA_STRATEGIC;
1421 } else if (bestLaneOffset == 0
1422 && (leader.first == 0 || !leader.first->isStopped())
1423 && neigh.bestContinuations.back()->getLinkCont().size() != 0
1424 && roundaboutBonus == 0
1425 && !checkOpposite
1426 && ((myStrategicParam >= 0 && neighDist < TURN_LANE_DIST)
1427 // lane changing cannot possibly help
1428 || (myStrategicParam < 0 && currFreeUntilNeighEnd))
1429 ) {
1430 // VARIANT_21 (stayOnBest)
1431 // we do not want to leave the best lane for a lane which leads elsewhere
1432 // unless our leader is stopped or we are approaching a roundabout
1433#ifdef DEBUG_WANTS_CHANGE
1434 if (DEBUG_COND) {
1435 std::cout << " veh=" << myVehicle.getID() << " does not want to leave the bestLane (neighDist=" << neighDist << ")\n";
1436 }
1437#endif
1438 ret = ret | LCA_STAY | LCA_STRATEGIC;
1439 }
1440 }
1441 // check for overriding TraCI requests
1442#ifdef DEBUG_WANTS_CHANGE
1443 if (DEBUG_COND) {
1444 std::cout << STEPS2TIME(currentTime) << " veh=" << myVehicle.getID() << " ret=" << toString((LaneChangeAction)ret);
1445 }
1446#endif
1447 // store state before canceling
1448 getCanceledState(laneOffset) |= ret;
1450 if ((ret & lcaCounter) != 0) {
1451 // we are not interested in traci requests for the opposite direction here
1452 ret &= ~(LCA_TRACI | lcaCounter | LCA_URGENT);
1453 }
1454#ifdef DEBUG_WANTS_CHANGE
1455 if (DEBUG_COND) {
1456 std::cout << " retAfterInfluence=" << toString((LaneChangeAction)ret) << "\n";
1457 }
1458#endif
1459
1460 if ((ret & LCA_STAY) != 0) {
1461 // remove TraCI flags because it should not be included in "state-without-traci"
1462 ret = getCanceledState(laneOffset);
1463 return ret;
1464 }
1465 if ((ret & LCA_URGENT) != 0) {
1466 // prepare urgent lane change maneuver
1467 // save the left space
1468 myLeftSpace = currentDist - posOnLane;
1469 if (changeToBest && abs(bestLaneOffset) > 1) {
1470 // there might be a vehicle which needs to counter-lane-change one lane further and we cannot see it yet
1471 myLeadingBlockerLength = MAX2((right ? 20.0 : 40.0), myLeadingBlockerLength);
1472#ifdef DEBUG_WANTS_CHANGE
1473 if (DEBUG_COND) {
1474 std::cout << " reserving space for unseen blockers myLeadingBlockerLength=" << myLeadingBlockerLength << "\n";
1475 }
1476#endif
1477 }
1478
1479 // letting vehicles merge in at the end of the lane in case of counter-lane change, step#1
1480 // if there is a leader and he wants to change to the opposite direction
1481 const bool canContinue = curr.bestContinuations.size() > 1;
1482 bool canReserve = MSLCHelper::saveBlockerLength(myVehicle, neighLead.first, lcaCounter, myLeftSpace, canContinue, myLeadingBlockerLength);
1483 if (*firstBlocked != neighLead.first) {
1484 canReserve &= MSLCHelper::saveBlockerLength(myVehicle, *firstBlocked, lcaCounter, myLeftSpace, canContinue, myLeadingBlockerLength);
1485 }
1486#ifdef DEBUG_SAVE_BLOCKER_LENGTH
1487 if (DEBUG_COND) {
1488 std::cout << SIMTIME << " canReserve=" << canReserve << " canContinue=" << canContinue << "\n";
1489 }
1490#endif
1491 if (!canReserve && !isOpposite()) {
1492 // we have a low-priority relief connection
1493 // std::cout << SIMTIME << " veh=" << myVehicle.getID() << " cannotReserve for blockers\n";
1494 myDontBrake = canContinue;
1495 }
1496
1497 const int remainingLanes = MAX2(1, abs(bestLaneOffset));
1498 const double urgency = isOpposite() ? OPPOSITE_URGENCY : URGENCY;
1499 const double remainingSeconds = ((ret & LCA_TRACI) == 0 ?
1500 //MAX2(STEPS2TIME(TS), (myLeftSpace-myLeadingBlockerLength) / MAX2(myLookAheadSpeed, NUMERICAL_EPS) / remainingLanes / urgency) :
1501 MAX2(STEPS2TIME(TS), myLeftSpace / MAX2(myLookAheadSpeed, NUMERICAL_EPS) / remainingLanes / urgency) :
1503 const double plannedSpeed = informLeader(msgPass, blocked, myLca, neighLead, remainingSeconds);
1504 // NOTE: for the ballistic update case negative speeds may indicate a stop request,
1505 // while informLeader returns -1 in that case. Refs. #2577
1506 if (plannedSpeed >= 0 || (!MSGlobals::gSemiImplicitEulerUpdate && plannedSpeed != -1)) {
1507 // maybe we need to deal with a blocking follower
1508 informFollower(msgPass, blocked, myLca, neighFollow, remainingSeconds, plannedSpeed);
1509 }
1510
1511#ifdef DEBUG_WANTS_CHANGE
1512 if (DEBUG_COND) {
1513 std::cout << STEPS2TIME(currentTime)
1514 << " veh=" << myVehicle.getID()
1515 << " myLeftSpace=" << myLeftSpace
1516 << " remainingSeconds=" << remainingSeconds
1517 << " plannedSpeed=" << plannedSpeed
1518 << "\n";
1519 }
1520#endif
1521
1522 // remove TraCI flags because it should not be included in "state-without-traci"
1523 ret = getCanceledState(laneOffset);
1524 return ret;
1525 }
1526
1527 // we wish to anticipate future speeds. This is difficult when the leading
1528 // vehicles are still accelerating so we resort to comparing speeds for the near future (1s) in this case
1529 const bool acceleratingLeader = (neighLead.first != 0 && neighLead.first->getAcceleration() > 0)
1530 || (leader.first != 0 && leader.first->getAcceleration() > 0);
1531 double neighLaneVSafe = MIN2(neighVMax, anticipateFollowSpeed(neighLead, neighDist, neighVMax, acceleratingLeader));
1532 thisLaneVSafe = MIN2(thisLaneVSafe, anticipateFollowSpeed(leader, currentDist, vMax, acceleratingLeader));
1533 //std::cout << SIMTIME << " veh=" << myVehicle.getID() << " thisLaneVSafe=" << thisLaneVSafe << " neighLaneVSafe=" << neighLaneVSafe << "\n";
1534
1535
1536 // a high inconvenience prevents cooperative changes and the following things are inconvenient:
1537 // - a desire to change in the opposite direction for speedGain
1538 // - low anticipated speed on the neighboring lane
1539 // - high occupancy on the neighboring lane while in a roundabout
1540
1541 double inconvenience = laneOffset < 0
1544
1545 const double relSpeedDiff = thisLaneVSafe == 0 ? 0 : (thisLaneVSafe - neighLaneVSafe) / MAX2(thisLaneVSafe, neighLaneVSafe);
1546 inconvenience = MAX2(relSpeedDiff, inconvenience);
1547 inconvenience = MIN2(1.0, inconvenience);
1548
1549 const bool speedGainInconvenient = inconvenience > myCooperativeParam;
1550 const bool neighOccupancyInconvenient = neigh.lane->getBruttoOccupancy() > curr.lane->getBruttoOccupancy();
1551#ifdef DEBUG_WANTS_CHANGE
1552 if (DEBUG_COND) {
1553 std::cout << STEPS2TIME(currentTime)
1554 << " veh=" << myVehicle.getID()
1555 << " speedGainProb=" << mySpeedGainProbability
1556 << " neighSpeedFactor=" << (thisLaneVSafe / neighLaneVSafe - 1)
1557 << " inconvenience=" << inconvenience
1558 << " speedInconv=" << speedGainInconvenient
1559 << " occInconv=" << neighOccupancyInconvenient
1560 << "\n";
1561 }
1562#endif
1563
1564 // VARIANT_15
1565 if (roundaboutBonus > 0) {
1566
1567#ifdef DEBUG_WANTS_CHANGE
1568 if (DEBUG_COND) {
1569 std::cout << STEPS2TIME(currentTime)
1570 << " veh=" << myVehicle.getID()
1571 << " roundaboutBonus=" << roundaboutBonus
1572 << " myLeftSpace=" << myLeftSpace
1573 << "\n";
1574 }
1575#endif
1576 // try to use the inner lanes of a roundabout to increase throughput
1577 // unless we are approaching the exit
1578 if (lca == LCA_LEFT) {
1579 // if inconvenience is not too high, request collaborative change (currently only for ballistic update)
1580 // TODO: test this for euler update! Refs. #2575
1581 if (MSGlobals::gSemiImplicitEulerUpdate || !neighOccupancyInconvenient) {
1582// if(MSGlobals::gSemiImplicitEulerUpdate || !speedGainInconvenient){
1583 req = ret | lca | LCA_COOPERATIVE;
1584 }
1585 } else {
1586 // if inconvenience is not too high, request collaborative change (currently only for ballistic update)
1587 if (MSGlobals::gSemiImplicitEulerUpdate || neighOccupancyInconvenient) {
1588// if(MSGlobals::gSemiImplicitEulerUpdate || speedGainInconvenient){
1589 req = ret | LCA_STAY | LCA_COOPERATIVE;
1590 }
1591 }
1592 if (!cancelRequest(req, laneOffset)) {
1593 return ret | req;
1594 }
1595 }
1596
1597 // let's also regard the case where the vehicle is driving on a highway...
1598 // in this case, we do not want to get to the dead-end of an on-ramp
1599 if (right) {
1600 if (bestLaneOffset == 0 && myVehicle.getLane()->getSpeedLimit() > 80. / 3.6 && myLookAheadSpeed > SUMO_const_haltingSpeed) {
1601#ifdef DEBUG_WANTS_CHANGE
1602 if (DEBUG_COND) {
1603 std::cout << " veh=" << myVehicle.getID() << " does not want to get stranded on the on-ramp of a highway\n";
1604 }
1605#endif
1606 req = ret | LCA_STAY | LCA_STRATEGIC;
1607 if (!cancelRequest(req, laneOffset)) {
1608 return ret | req;
1609 }
1610 }
1611 }
1612 // --------
1613
1614 // -------- make place on current lane if blocking follower
1615 //if (amBlockingFollowerPlusNB()) {
1616 // std::cout << myVehicle.getID() << ", " << currentDistAllows(neighDist, bestLaneOffset, laDist)
1617 // << " neighDist=" << neighDist
1618 // << " currentDist=" << currentDist
1619 // << "\n";
1620 //}
1621
1623 && (!speedGainInconvenient)
1624 && ((myOwnState & myLca) != 0) // VARIANT_6 : counterNoHelp
1625 && (changeToBest || currentDistAllows(neighDist, abs(bestLaneOffset) + 1, laDist))) {
1626
1627 // VARIANT_2 (nbWhenChangingToHelp)
1628#ifdef DEBUG_COOPERATE
1629 if (DEBUG_COND) {
1630 std::cout << STEPS2TIME(currentTime)
1631 << " veh=" << myVehicle.getID()
1632 << " wantsChangeToHelp=" << (right ? "right" : "left")
1633 << " state=" << myOwnState
1634 << (((myOwnState & myLca) == 0) ? " (counter)" : "")
1635 << "\n";
1636 }
1637#endif
1638 req = ret | lca | LCA_COOPERATIVE | LCA_URGENT ;//| LCA_CHANGE_TO_HELP;
1639 if (!cancelRequest(req, laneOffset)) {
1640 return ret | req;
1641 }
1642 }
1643
1644 // --------
1645
1646
1649 //if ((blocked & LCA_BLOCKED) != 0) {
1650 // return ret;
1651 //}
1653
1654 // -------- higher speed
1655 //if ((congested(neighLead.first) && neighLead.second < 20) || predInteraction(leader.first)) { //!!!
1656 // return ret;
1657 //}
1658
1659 if (neighLane.getEdge().getPersons().size() > 0) {
1660 // react to pedestrians
1661 adaptSpeedToPedestrians(myVehicle.getLane(), thisLaneVSafe);
1662 adaptSpeedToPedestrians(&neighLane, neighLaneVSafe);
1663 }
1664
1665 const double relativeGain = (neighLaneVSafe - thisLaneVSafe) / MAX2(neighLaneVSafe,
1667
1668#ifdef DEBUG_WANTS_CHANGE
1669 if (DEBUG_COND) {
1670 std::cout << STEPS2TIME(currentTime)
1671 << " veh=" << myVehicle.getID()
1672 << " currentDist=" << currentDist
1673 << " neighDist=" << neighDist
1674 << " thisVSafe=" << thisLaneVSafe
1675 << " neighVSafe=" << neighLaneVSafe
1676 << " relGain=" << toString(relativeGain, 8)
1677 << "\n";
1678 }
1679#endif
1680
1681 if (right) {
1682 // ONLY FOR CHANGING TO THE RIGHT
1683 if (thisLaneVSafe - 5 / 3.6 > neighLaneVSafe) {
1684 // ok, the current lane is faster than the right one...
1685 if (mySpeedGainProbability < 0) {
1687 //myKeepRightProbability /= 2.0;
1688 }
1689 } else {
1690 // ok, the current lane is not (much) faster than the right one
1691 // @todo recheck the 5 km/h discount on thisLaneVSafe, refs. #2068
1692
1693 // do not promote changing to the left just because changing to the right is bad
1694 // XXX: The following code may promote it, though!? (recheck!)
1695 // (Think of small negative mySpeedGainProbability and larger negative relativeGain)
1696 // One might think of replacing '||' by '&&' to exclude that possibility...
1697 // Still, for negative relativeGain, we might want to decrease the inclination for
1698 // changing to the left. Another solution could be the seperation of mySpeedGainProbability into
1699 // two variables (one for left and one for right). Refs #2578
1700 if (mySpeedGainProbability < 0 || relativeGain > 0) {
1702 }
1703
1704 // honor the obligation to keep right (Rechtsfahrgebot)
1705 const double roadSpeedFactor = vMax / myVehicle.getLane()->getSpeedLimit(); // differse from speedFactor if vMax < speedLimit
1706 double acceptanceTime;
1707 if (myKeepRightAcceptanceTime == -1) {
1708 // legacy behavior: scale acceptance time with current speed and
1709 // use old hard-coded constant
1710 acceptanceTime = 7 * roadSpeedFactor * MAX2(1.0, myVehicle.getSpeed());
1711 } else {
1712 acceptanceTime = myKeepRightAcceptanceTime * roadSpeedFactor;
1713 if (follower.first != nullptr && follower.second < 2 * follower.first->getCarFollowModel().brakeGap(follower.first->getSpeed())) {
1714 // reduce acceptanceTime if the follower vehicle is faster or wants to drive faster
1715 if (follower.first->getSpeed() >= myVehicle.getSpeed()) {
1716 acceptanceTime *= MAX2(1.0, myVehicle.getSpeed()) / MAX2(1.0, follower.first->getSpeed());
1717 const double fRSF = follower.first->getLane()->getVehicleMaxSpeed(follower.first) / follower.first->getLane()->getSpeedLimit();
1718 if (fRSF > roadSpeedFactor) {
1719 acceptanceTime /= fRSF;
1720 }
1721 }
1722 }
1723 }
1724 double fullSpeedGap = MAX2(0., neighDist - myVehicle.getCarFollowModel().brakeGap(vMax));
1725 double fullSpeedDrivingSeconds = MIN2(acceptanceTime, fullSpeedGap / vMax);
1726 if (neighLead.first != 0 && neighLead.first->getSpeed() < vMax) {
1727 fullSpeedGap = MAX2(0., MIN2(fullSpeedGap,
1728 neighLead.second - myVehicle.getCarFollowModel().getSecureGap(&myVehicle, neighLead.first,
1729 vMax, neighLead.first->getSpeed(), neighLead.first->getCarFollowModel().getMaxDecel())));
1730 fullSpeedDrivingSeconds = MIN2(fullSpeedDrivingSeconds, fullSpeedGap / (vMax - neighLead.first->getSpeed()));
1731 }
1732 // stay on the current lane if we cannot overtake a slow leader on the right
1733 if (checkOverTakeRight && leader.first != 0
1734 && leader.first->getLane()->getVehicleMaxSpeed(leader.first) < vMax) {
1735 fullSpeedGap = MIN2(fullSpeedGap, leader.second);
1736 fullSpeedDrivingSeconds = MIN2(fullSpeedDrivingSeconds, fullSpeedGap / (vMax - leader.first->getSpeed()));
1737 const double relGain = (vMax - leader.first->getLane()->getVehicleMaxSpeed(leader.first)) / MAX2(vMax,
1739 // tiebraker to avoid buridans paradox see #1312
1741 }
1742
1743 const double deltaProb = (myChangeProbThresholdRight * (fullSpeedDrivingSeconds / acceptanceTime) / KEEP_RIGHT_TIME);
1745
1746 //std::cout << STEPS2TIME(currentTime)
1747 // << " veh=" << myVehicle.getID()
1748 // << " acceptanceTime=" << acceptanceTime
1749 // << " fullSpeedDrivingSeconds=" << fullSpeedDrivingSeconds
1750 // << " dProb=" << deltaProb
1751 // << " myKeepRightProbability=" << myKeepRightProbability
1752 // << "\n";
1753
1754#ifdef DEBUG_WANTS_CHANGE
1755 if (DEBUG_COND) {
1756 std::cout << STEPS2TIME(currentTime)
1757 << " veh=" << myVehicle.getID()
1758 << " vMax=" << vMax
1759 << " neighDist=" << neighDist
1760 << " brakeGap=" << myVehicle.getCarFollowModel().brakeGap(myVehicle.getSpeed())
1761 << " leaderSpeed=" << (neighLead.first == 0 ? -1 : neighLead.first->getSpeed())
1762 << " secGap=" << (neighLead.first == 0 ? -1 : myVehicle.getCarFollowModel().getSecureGap(&myVehicle, neighLead.first,
1763 myVehicle.getSpeed(), neighLead.first->getSpeed(), neighLead.first->getCarFollowModel().getMaxDecel()))
1764 << " acceptanceTime=" << acceptanceTime
1765 << " fullSpeedGap=" << fullSpeedGap
1766 << " fullSpeedDrivingSeconds=" << fullSpeedDrivingSeconds
1767 << " dProb=" << deltaProb
1768 << " myKeepRightProbability=" << myKeepRightProbability
1769 << "\n";
1770 }
1771#endif
1773 req = ret | lca | LCA_KEEPRIGHT;
1774 if (!cancelRequest(req, laneOffset)) {
1775 return ret | req;
1776 }
1777 }
1778 }
1779
1780#ifdef DEBUG_WANTS_CHANGE
1781 if (DEBUG_COND) {
1782 std::cout << STEPS2TIME(currentTime)
1783 << " veh=" << myVehicle.getID()
1784 << " speed=" << myVehicle.getSpeed()
1785 << " mySpeedGainProbability=" << mySpeedGainProbability
1786 << " thisLaneVSafe=" << thisLaneVSafe
1787 << " neighLaneVSafe=" << neighLaneVSafe
1788 << " relativeGain=" << relativeGain
1789 << " blocked=" << blocked
1790 << "\n";
1791 }
1792#endif
1793
1795 && neighDist / MAX2(.1, myVehicle.getSpeed()) > 20.) { //./MAX2( .1, myVehicle.getSpeed())) { // -.1
1796 req = ret | lca | LCA_SPEEDGAIN;
1797 if (!cancelRequest(req, laneOffset)) {
1798 return ret | req;
1799 }
1800 }
1801 } else {
1802 // ONLY FOR CHANGING TO THE LEFT
1803 if (thisLaneVSafe > neighLaneVSafe) {
1804 // this lane is better
1805 if (mySpeedGainProbability > 0) {
1807 }
1808 } else if (thisLaneVSafe == neighLaneVSafe) {
1809 if (mySpeedGainProbability > 0) {
1811 }
1812 } else {
1813 // left lane is better
1815 }
1816 // VARIANT_19 (stayRight)
1817 //if (neighFollow.first != 0) {
1818 // MSVehicle* nv = neighFollow.first;
1819 // const double secGap = nv->getCarFollowModel().getSecureGap(nv, &myVehicle, nv->getSpeed(), myVehicle.getSpeed(), myVehicle.getCarFollowModel().getMaxDecel());
1820 // if (neighFollow.second < secGap * KEEP_RIGHT_HEADWAY) {
1821 // // do not change left if it would inconvenience faster followers
1822 // return ret | LCA_STAY | LCA_SPEEDGAIN;
1823 // }
1824 //}
1825
1826#ifdef DEBUG_WANTS_CHANGE
1827 if (DEBUG_COND) {
1828 std::cout << STEPS2TIME(currentTime)
1829 << " veh=" << myVehicle.getID()
1830 << " speed=" << myVehicle.getSpeed()
1831 << " mySpeedGainProbability=" << mySpeedGainProbability
1832 << " thisLaneVSafe=" << thisLaneVSafe
1833 << " neighLaneVSafe=" << neighLaneVSafe
1834 << " relativeGain=" << relativeGain
1835 << " blocked=" << blocked
1836 << "\n";
1837 }
1838#endif
1839
1841 && (relativeGain > NUMERICAL_EPS || changeLeftToAvoidOvertakeRight)
1842 && neighDist / MAX2(.1, myVehicle.getSpeed()) > 20.) { // .1
1843 req = ret | lca | LCA_SPEEDGAIN;
1844 if (!cancelRequest(req, laneOffset)) {
1845 return ret | req;
1846 }
1847 }
1848 }
1849 // --------
1850 if (changeToBest && bestLaneOffset == curr.bestLaneOffset
1851 && myStrategicParam >= 0
1852 && relativeGain >= 0
1853 && (right ? mySpeedGainProbability < 0 : mySpeedGainProbability > 0)) {
1854 // change towards the correct lane, speedwise it does not hurt
1855 req = ret | lca | LCA_STRATEGIC;
1856 if (!cancelRequest(req, laneOffset)) {
1857 return ret | req;
1858 }
1859 }
1860#ifdef DEBUG_WANTS_CHANGE
1861 if (DEBUG_COND) {
1862 std::cout << STEPS2TIME(currentTime)
1863 << " veh=" << myVehicle.getID()
1864 << " mySpeedGainProbability=" << mySpeedGainProbability
1865 << " myKeepRightProbability=" << myKeepRightProbability
1866 << " thisLaneVSafe=" << thisLaneVSafe
1867 << " neighLaneVSafe=" << neighLaneVSafe
1868 << "\n";
1869 }
1870#endif
1871
1872 return ret;
1873}
1874
1875
1876double
1877MSLCM_LC2013::anticipateFollowSpeed(const std::pair<MSVehicle*, double>& leaderDist, double dist, double vMax, bool acceleratingLeader) {
1878 const MSVehicle* leader = leaderDist.first;
1879 const double gap = leaderDist.second;
1880 double futureSpeed;
1881 if (acceleratingLeader) {
1882 // XXX see #6562
1883 const double maxSpeed1s = (myVehicle.getSpeed() + myVehicle.getCarFollowModel().getMaxAccel()
1885 if (leader == nullptr) {
1886 if (hasBlueLight()) {
1887 // can continue from any lane if necessary
1888 futureSpeed = vMax;
1889 } else {
1890 futureSpeed = getCarFollowModel().followSpeed(&myVehicle, maxSpeed1s, dist, 0, 0);
1891 }
1892 } else {
1893 futureSpeed = getCarFollowModel().followSpeed(&myVehicle, maxSpeed1s, gap, leader->getSpeed(), leader->getCarFollowModel().getMaxDecel());
1894 }
1895 } else {
1896 // onInsertion = true because the vehicle has already moved
1897 if (leader == nullptr) {
1898 if (hasBlueLight()) {
1899 // can continue from any lane if necessary
1900 futureSpeed = vMax;
1901 } else {
1902 futureSpeed = getCarFollowModel().maximumSafeStopSpeed(dist, getCarFollowModel().getMaxDecel(), myVehicle.getSpeed(), true);
1903 }
1904 } else {
1905 futureSpeed = getCarFollowModel().maximumSafeFollowSpeed(gap, myVehicle.getSpeed(), leader->getSpeed(), leader->getCarFollowModel().getMaxDecel(), true);
1906 }
1907 }
1908 futureSpeed = MIN2(vMax, futureSpeed);
1909 if (leader != nullptr && gap > 0 && mySpeedGainLookahead > 0) {
1910 const double futureLeaderSpeed = acceleratingLeader ? leader->getLane()->getVehicleMaxSpeed(leader) : leader->getSpeed();
1911 const double deltaV = vMax - futureLeaderSpeed;
1912 if (deltaV > 0 && gap > 0) {
1913 const double secGap = getCarFollowModel().getSecureGap(&myVehicle, leader, futureSpeed, leader->getSpeed(), getCarFollowModel().getMaxDecel());
1914 const double fullSpeedGap = gap - secGap;
1915 if (fullSpeedGap / deltaV < mySpeedGainLookahead) {
1916 // anticipate future braking by computing the average
1917 // speed over the next few seconds
1918 const double gapClosingTime = MAX2(0.0, fullSpeedGap / deltaV);
1919 const double foreCastTime = mySpeedGainLookahead * 2;
1920 //if (DEBUG_COND) std::cout << SIMTIME << " veh=" << myVehicle.getID() << " leader=" << leader->getID() << " gap=" << gap << " deltaV=" << deltaV << " futureSpeed=" << futureSpeed << " futureLeaderSpeed=" << futureLeaderSpeed;
1921 futureSpeed = MIN2(futureSpeed, (gapClosingTime * futureSpeed + (foreCastTime - gapClosingTime) * futureLeaderSpeed) / foreCastTime);
1922 //if (DEBUG_COND) std::cout << " newFutureSpeed=" << futureSpeed << "\n";
1923 }
1924 }
1925 }
1926 return futureSpeed;
1927}
1928
1929
1930int
1932 // if this vehicle is blocking someone in front, we maybe decelerate to let him in
1933 if ((*blocked) != nullptr) {
1934 double gap = (*blocked)->getPositionOnLane() - (*blocked)->getVehicleType().getLength() - myVehicle.getPositionOnLane() - myVehicle.getVehicleType().getMinGap();
1935#ifdef DEBUG_SLOW_DOWN
1936 if (DEBUG_COND) {
1937 std::cout << SIMTIME
1938 << " veh=" << myVehicle.getID()
1939 << " blocked=" << Named::getIDSecure(*blocked)
1940 << " gap=" << gap
1941 << "\n";
1942 }
1943#endif
1944 if (gap > POSITION_EPS) {
1945 //const bool blockedWantsUrgentRight = (((*blocked)->getLaneChangeModel().getOwnState() & LCA_RIGHT != 0)
1946 // && ((*blocked)->getLaneChangeModel().getOwnState() & LCA_URGENT != 0));
1947
1949 //|| blockedWantsUrgentRight // VARIANT_10 (helpblockedRight)
1950 ) {
1951 if ((*blocked)->getSpeed() < SUMO_const_haltingSpeed) {
1953 } else {
1954 state |= LCA_AMBACKBLOCKER;
1955 }
1956 addLCSpeedAdvice(getCarFollowModel().followSpeed(
1958 gap - POSITION_EPS, (*blocked)->getSpeed(),
1959 (*blocked)->getCarFollowModel().getMaxDecel()), false);
1960
1961 //(*blocked) = 0; // VARIANT_14 (furtherBlock)
1962#ifdef DEBUG_SLOW_DOWN
1963 if (DEBUG_COND) {
1964 std::cout << SIMTIME
1965 << " veh=" << myVehicle.getID()
1966 << " slowing down for"
1967 << " blocked=" << Named::getIDSecure(*blocked)
1968 << " helpSpeed=" << myLCAccelerationAdvices.back().first
1969 << "\n";
1970 }
1971#endif
1972 } /* else {
1973 // experimental else-branch...
1974 state |= LCA_AMBACKBLOCKER;
1975 myVSafes.push_back(getCarFollowModel().followSpeed(
1976 &myVehicle, myVehicle.getSpeed(),
1977 (gap - POSITION_EPS), (*blocked)->getSpeed(),
1978 (*blocked)->getCarFollowModel().getMaxDecel()));
1979 }*/
1980 }
1981 }
1982 return state;
1983}
1984
1985
1986void
1988 if (lane->hasPedestrians()) {
1989#ifdef DEBUG_WANTS_CHANGE
1990 if (DEBUG_COND) {
1991 std::cout << SIMTIME << " adapt to pedestrians on lane=" << lane->getID() << "\n";
1992 }
1993#endif
1997 if (leader.first != 0) {
1998 const double stopSpeed = myVehicle.getCarFollowModel().stopSpeed(&myVehicle, myVehicle.getSpeed(), leader.second - myVehicle.getVehicleType().getMinGap());
1999 v = MIN2(v, stopSpeed);
2000#ifdef DEBUG_WANTS_CHANGE
2001 if (DEBUG_COND) {
2002 std::cout << SIMTIME << " pedLeader=" << leader.first->getID() << " dist=" << leader.second << " v=" << v << "\n";
2003 }
2004#endif
2005 }
2006 }
2007}
2008
2009
2010double
2011MSLCM_LC2013::computeSpeedLat(double latDist, double& maneuverDist, bool urgent) const {
2012 double result = MSAbstractLaneChangeModel::computeSpeedLat(latDist, maneuverDist, urgent);
2013#ifdef DEBUG_WANTS_CHANGE
2014 if (DEBUG_COND) {
2015 std::cout << SIMTIME << " veh=" << myVehicle.getID() << " myLeftSpace=" << myLeftSpace << " latDist=" << latDist << " maneuverDist=" << maneuverDist << " result=" << result << "\n";
2016 }
2017#endif
2018 if (myLeftSpace > POSITION_EPS) {
2020 if (isChangingLanes()) {
2021 speedBound = MAX2(LC_RESOLUTION_SPEED_LAT, speedBound);
2022 }
2023 result = MAX2(-speedBound, MIN2(speedBound, result));
2024 }
2025 return result;
2026}
2027
2028
2029double
2031 return 1 / myAssertive;
2032}
2033
2034double
2036 return myOppositeParam <= 0 ? std::numeric_limits<double>::max() : 1 / myOppositeParam;
2037}
2038
2039bool
2040MSLCM_LC2013::saveBlockerLength(double length, double foeLeftSpace) {
2041 const bool canReserve = MSLCHelper::canSaveBlockerLength(myVehicle, length, myLeftSpace);
2042 if (!isOpposite() && (canReserve || myLeftSpace > foeLeftSpace)) {
2044#ifdef DEBUG_SAVE_BLOCKER_LENGTH
2045 if (DEBUG_COND) {
2046 std::cout << SIMTIME << " saveBlockerLength veh=" << myVehicle.getID() << " canReserve=" << canReserve << " myLeftSpace=" << myLeftSpace << " foeLeftSpace=" << foeLeftSpace << "\n";
2047 }
2048#endif
2049 if (myLeftSpace == 0 && foeLeftSpace < 0) {
2050 // called from opposite overtaking, myLeftSpace must be initialized
2052 }
2053 return true;
2054 } else {
2055 return false;
2056 }
2057}
2058
2059std::string
2060MSLCM_LC2013::getParameter(const std::string& key) const {
2062 return toString(myStrategicParam);
2063 } else if (key == toString(SUMO_ATTR_LCA_COOPERATIVE_PARAM)) {
2065 } else if (key == toString(SUMO_ATTR_LCA_SPEEDGAIN_PARAM)) {
2066 return toString(mySpeedGainParam);
2067 } else if (key == toString(SUMO_ATTR_LCA_KEEPRIGHT_PARAM)) {
2068 return toString(myKeepRightParam);
2069 } else if (key == toString(SUMO_ATTR_LCA_OPPOSITE_PARAM)) {
2070 return toString(myOppositeParam);
2071 } else if (key == toString(SUMO_ATTR_LCA_LOOKAHEADLEFT)) {
2072 return toString(myLookaheadLeft);
2073 } else if (key == toString(SUMO_ATTR_LCA_SPEEDGAINRIGHT)) {
2074 return toString(mySpeedGainRight);
2075 } else if (key == toString(SUMO_ATTR_LCA_ASSERTIVE)) {
2076 return toString(myAssertive);
2077 } else if (key == toString(SUMO_ATTR_LCA_OVERTAKE_RIGHT)) {
2079 } else if (key == toString(SUMO_ATTR_LCA_SIGMA)) {
2080 return toString(mySigma);
2085 } else if (key == toString(SUMO_ATTR_LCA_SPEEDGAIN_LOOKAHEAD)) {
2089 } else if (key == toString(SUMO_ATTR_LCA_COOPERATIVE_SPEED)) {
2091 } else if (key == toString(SUMO_ATTR_LCA_MAXSPEEDLATSTANDING)) {
2093 } else if (key == toString(SUMO_ATTR_LCA_MAXSPEEDLATFACTOR)) {
2095 } else if (key == toString(SUMO_ATTR_LCA_MAXDISTLATSTANDING)) {
2097 // access to internal state for debugging in sumo-gui (not documented since it may change at any time)
2098 } else if (key == "speedGainProbabilityRight") {
2100 } else if (key == "speedGainProbabilityLeft") {
2102 } else if (key == "keepRightProbability") {
2104 } else if (key == "lookAheadSpeed") {
2105 return toString(myLookAheadSpeed);
2106 // motivation relative to threshold
2107 } else if (key == "speedGainRP") {
2109 } else if (key == "speedGainLP") {
2111 } else if (key == "keepRightP") {
2113 }
2114 throw InvalidArgument("Parameter '" + key + "' is not supported for laneChangeModel of type '" + toString(myModel) + "'");
2115}
2116
2117
2118void
2119MSLCM_LC2013::setParameter(const std::string& key, const std::string& value) {
2120 double doubleValue;
2121 try {
2122 doubleValue = StringUtils::toDouble(value);
2123 } catch (NumberFormatException&) {
2124 throw InvalidArgument("Setting parameter '" + key + "' requires a number for laneChangeModel of type '" + toString(myModel) + "'");
2125 }
2127 myStrategicParam = doubleValue;
2128 } else if (key == toString(SUMO_ATTR_LCA_COOPERATIVE_PARAM)) {
2129 myCooperativeParam = doubleValue;
2130 } else if (key == toString(SUMO_ATTR_LCA_SPEEDGAIN_PARAM)) {
2131 mySpeedGainParam = doubleValue;
2132 } else if (key == toString(SUMO_ATTR_LCA_KEEPRIGHT_PARAM)) {
2133 myKeepRightParam = doubleValue;
2134 } else if (key == toString(SUMO_ATTR_LCA_OPPOSITE_PARAM)) {
2135 myOppositeParam = doubleValue;
2136 } else if (key == toString(SUMO_ATTR_LCA_LOOKAHEADLEFT)) {
2137 myLookaheadLeft = doubleValue;
2138 } else if (key == toString(SUMO_ATTR_LCA_SPEEDGAINRIGHT)) {
2139 mySpeedGainRight = doubleValue;
2140 } else if (key == toString(SUMO_ATTR_LCA_ASSERTIVE)) {
2141 myAssertive = doubleValue;
2142 } else if (key == toString(SUMO_ATTR_LCA_OVERTAKE_RIGHT)) {
2143 myOvertakeRightParam = doubleValue;
2144 } else if (key == toString(SUMO_ATTR_LCA_SIGMA)) {
2145 mySigma = doubleValue;
2147 myKeepRightAcceptanceTime = doubleValue;
2149 myOvertakeDeltaSpeedFactor = doubleValue;
2150 } else if (key == toString(SUMO_ATTR_LCA_SPEEDGAIN_LOOKAHEAD)) {
2151 mySpeedGainLookahead = doubleValue;
2153 myRoundaboutBonus = doubleValue;
2154 } else if (key == toString(SUMO_ATTR_LCA_COOPERATIVE_SPEED)) {
2155 myCooperativeSpeed = doubleValue;
2156 } else if (key == toString(SUMO_ATTR_LCA_MAXSPEEDLATSTANDING)) {
2157 myMaxSpeedLatStanding = doubleValue;
2158 } else if (key == toString(SUMO_ATTR_LCA_MAXSPEEDLATFACTOR)) {
2159 myMaxSpeedLatFactor = doubleValue;
2160 } else if (key == toString(SUMO_ATTR_LCA_MAXDISTLATSTANDING)) {
2161 myMaxDistLatStanding = doubleValue;
2162 // access to internal state
2163 } else if (key == "speedGainProbabilityRight") {
2164 mySpeedGainProbability = -doubleValue;
2165 } else if (key == "speedGainProbabilityLeft") {
2166 mySpeedGainProbability = doubleValue;
2167 } else if (key == "keepRightProbability") {
2168 myKeepRightProbability = -doubleValue;
2169 } else if (key == "lookAheadSpeed") {
2170 myLookAheadSpeed = doubleValue;
2171 } else {
2172 throw InvalidArgument("Setting parameter '" + key + "' is not supported for laneChangeModel of type '" + toString(myModel) + "'");
2173 }
2175}
2176
2177
2178/****************************************************************************/
long long int SUMOTime
Definition: GUI.h:36
#define INVALID_SPEED
Definition: MSCFModel.h:31
#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:54
#define SPEED2DIST(x)
Definition: SUMOTime.h:44
#define ACCEL2SPEED(x)
Definition: SUMOTime.h:50
#define TS
Definition: SUMOTime.h:41
#define SIMTIME
Definition: SUMOTime.h:61
#define DIST2SPEED(x)
Definition: SUMOTime.h:46
#define SPEED2ACCEL(x)
Definition: SUMOTime.h:52
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
double maximumSafeStopSpeed(double gap, double decel, double currentSpeed, bool onInsertion=false, double headway=-1) const
Returns the maximum next velocity for stopping within gap.
Definition: MSCFModel.cpp:774
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:919
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 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 canSaveBlockerLength(const MSVehicle &veh, double requested, double leftSpace)
Definition: MSLCHelper.cpp:276
static double getSpeedPreservingSecureGap(const MSVehicle &leader, const MSVehicle &follower, double currentGap, double leaderPlannedSpeed)
Definition: MSLCHelper.cpp:297
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 saveBlockerLength(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:288
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:4247
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:4240
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:3088
MSLane * getBidiLane() const
retrieve bidirectional lane or nullptr
Definition: MSLane.cpp:4321
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:2933
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:320
const MSLane * lane
The lane to stop at (microsim only)
Definition: MSStop.h:50
double changeRequestRemainingSeconds(const SUMOTime currentTime) const
Return the remaining number of seconds of the current laneTimeLine assuming one exists.
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:6974
double getMaxSpeedOnLane() const
Returns the maximal speed for the vehicle on its current lane (including speed factor and deviation,...
Definition: MSVehicle.cpp:1315
double nextStopDist() const
return the distance to the next stop or doubleMax if there is none.
Definition: MSVehicle.h:1049
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:6176
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:6939
double getRightSideOnLane() const
Get the lateral position of the vehicles right side on the lane:
Definition: MSVehicle.cpp:6406
double getLateralPositionOnLane() const
Get the vehicle's lateral position on the lane.
Definition: MSVehicle.h:416
bool congested() const
Definition: MSVehicle.cpp:1399
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:5528
const MSCFModel & getCarFollowModel() const
Returns the vehicle's car following model definition.
Definition: MSVehicle.h:973
double getPositionOnLane() const
Get the vehicle's position along the lane.
Definition: MSVehicle.h:377
double getLateralOverlap() const
return the amount by which the vehicle extends laterally outside it's primary lane
Definition: MSVehicle.cpp:6614
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:864
double length
The overall length which may be driven when using this lane without a lane change.
Definition: MSVehicle.h:868
std::vector< MSLane * > bestContinuations
Definition: MSVehicle.h:884
MSLane * lane
The described lane.
Definition: MSVehicle.h:866
int bestLaneOffset
The (signed) number of lanes to be crossed to get to the lane which allows to continue the drive.
Definition: MSVehicle.h:876
double occupation
The overall vehicle sum on consecutive lanes which can be passed without a lane change.
Definition: MSVehicle.h:872