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