Eclipse SUMO - Simulation of Urban MObility
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Modules Pages
MSLaneChanger.cpp
Go to the documentation of this file.
1/****************************************************************************/
2// Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
3// Copyright (C) 2002-2025 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/****************************************************************************/
23// Performs lane changing of vehicles
24/****************************************************************************/
25#include <config.h>
26
27#include "MSLaneChanger.h"
28#include "MSNet.h"
29#include "MSLink.h"
30#include "MSVehicle.h"
31#include "MSVehicleType.h"
32#include "MSVehicleTransfer.h"
33#include "MSStop.h"
34#include "MSGlobals.h"
35#include <cassert>
36#include <iterator>
37#include <cstdlib>
38#include <cmath>
43
44#define OPPOSITE_OVERTAKING_SAFE_TIMEGAP 0.0
45#define OPPOSITE_OVERTAKING_SAFETYGAP_HEADWAY_FACTOR 0.0
46#define OPPOSITE_OVERTAKING_SAFETY_FACTOR 1.2
47// XXX maxLookAhead should be higher if all leaders are stopped and lower when they are jammed/queued
48#define OPPOSITE_OVERTAKING_MAX_LOOKAHEAD 150.0 // just a guess
49#define OPPOSITE_OVERTAKING_MAX_LOOKAHEAD_EMERGENCY 1000.0 // just a guess
50// this is used for finding oncoming vehicles while driving in the opposite direction
51#define OPPOSITE_OVERTAKING_ONCOMING_LOOKAHEAD 1000.0 // just a guess
52// do not attempt overtaking maneuvers that would exceed this distance
53#define OPPOSITE_OVERTAKING_MAX_SPACE_TO_OVERTAKE 1000.0 // just a guess
54#define OPPOSITE_OVERTAKING_HILLTOP_THRESHOHOLD 5 // (m)
55
56// halting time to signal yielding in deadlock
57#define OPPOSITE_OVERTAKING_DEADLOCK_WAIT 1 // (s)
58
59// ===========================================================================
60// debug defines
61// ===========================================================================
62
63//#define DEBUG_CONTINUE_CHANGE
64//#define DEBUG_CHECK_CHANGE
65//#define DEBUG_SURROUNDING_VEHICLES // debug getRealFollower() and getRealLeader()
66//#define DEBUG_CHANGE_OPPOSITE
67//#define DEBUG_CHANGE_OPPOSITE_OVERTAKINGTIME
68//#define DEBUG_CHANGE_OPPOSITE_DEADLOCK
69//#define DEBUG_ACTIONSTEPS
70//#define DEBUG_STATE
71//#define DEBUG_CANDIDATE
72//#define DEBUG_COND (vehicle->getLaneChangeModel().debugVehicle())
73#define DEBUG_COND (vehicle->isSelected())
74//#define DEBUG_COND (true)
75
76
77
78// ===========================================================================
79// ChangeElem member method definitions
80// ===========================================================================
82 lead(nullptr),
83 lane(_lane),
84 hoppedVeh(nullptr),
85 lastBlocked(nullptr),
86 firstBlocked(nullptr),
87 lastStopped(nullptr),
88 ahead(_lane->getWidth()),
89 aheadNext(_lane->getWidth(), nullptr, 0.),
90 zipperDist(0)
91{
92 if (lane->isInternal()) {
93 for (auto ili : lane->getIncomingLanes()) {
94 if (ili.viaLink->getState() == LINKSTATE_ZIPPER) {
96 break;
97 }
98 }
99 } else {
100 for (const MSLink* link : lane->getLinkCont()) {
101 if (link->getState() == LINKSTATE_ZIPPER) {
102 zipperDist = MAX2(zipperDist, link->getFoeVisibilityDistance());
103 // @note: if this lane is shorter than zipperDist it would be better to extend this to any upstream edges within the
104 // visibility distance of the zipper link
105 }
106 }
107 }
108}
109
110void
112 //std::cout << SIMTIME << " registerHop lane=" << lane->getID() << " veh=" << vehicle->getID() << "\n";
113 lane->myTmpVehicles.insert(lane->myTmpVehicles.begin(), vehicle);
114 dens += vehicle->getVehicleType().getLengthWithGap();
115 hoppedVeh = vehicle;
116}
117
118
119// ===========================================================================
120// member method definitions
121// ===========================================================================
122MSLaneChanger::MSLaneChanger(const std::vector<MSLane*>* lanes, bool allowChanging) :
123 myAllowsChanging(allowChanging),
124 myChangeToOpposite(lanes->front()->getEdge().canChangeToOpposite()) {
125
126 // Fill the changer with the lane-data.
127 myChanger.reserve(lanes->size());
128 for (std::vector<MSLane*>::const_iterator lane = lanes->begin(); lane != lanes->end(); ++lane) {
129 myChanger.push_back(ChangeElem(*lane));
130 myChanger.back().mayChangeRight = lane != lanes->begin();
131 myChanger.back().mayChangeLeft = (lane + 1) != lanes->end();
132 if ((*lane)->isInternal()) {
133 // avoid changing on internal sibling lane
134 if (myChanger.back().mayChangeRight && (*lane)->getLogicalPredecessorLane() == (*(lane - 1))->getLogicalPredecessorLane()) {
135 myChanger.back().mayChangeRight = false;
136 }
137 if (myChanger.back().mayChangeLeft && (*lane)->getLogicalPredecessorLane() == (*(lane + 1))->getLogicalPredecessorLane()) {
138 myChanger.back().mayChangeLeft = false;
139 }
140 // avoid changing if lanes have different lengths
141 if (myChanger.back().mayChangeRight && (*lane)->getLength() != (*(lane - 1))->getLength()) {
142 //std::cout << " cannot change right from lane=" << (*lane)->getID() << " len=" << (*lane)->getLength() << " to=" << (*(lane - 1))->getID() << " len2=" << (*(lane - 1))->getLength() << "\n";
143 myChanger.back().mayChangeRight = false;
144 }
145 if (myChanger.back().mayChangeLeft && (*lane)->getLength() != (*(lane + 1))->getLength()) {
146 //std::cout << " cannot change left from lane=" << (*lane)->getID() << " len=" << (*lane)->getLength() << " to=" << (*(lane + 1))->getID() << " len2=" << (*(lane + 1))->getLength() << "\n";
147 myChanger.back().mayChangeLeft = false;
148 }
149 }
150 }
151}
152
153
156
157
158void
160 // This is what happens in one timestep. After initialization of the
161 // changer, each vehicle will try to change. After that the changer
162 // needs an update to prevent multiple changes of one vehicle.
163 // Finally, the change-result has to be given back to the lanes.
164 initChanger();
165 try {
166 while (vehInChanger()) {
167 const bool haveChanged = change();
168 updateChanger(haveChanged);
169 }
170 updateLanes(t);
171 } catch (const ProcessError&) {
172 // clean up locks or the gui may hang
173 for (ChangerIt ce = myChanger.begin(); ce != myChanger.end(); ++ce) {
174 ce->lane->releaseVehicles();
175 }
176 throw;
177 }
178}
179
180
181void
183 // Prepare myChanger with a safe state.
184 for (ChangerIt ce = myChanger.begin(); ce != myChanger.end(); ++ce) {
185 ce->lead = nullptr;
186 ce->hoppedVeh = nullptr;
187 ce->lastBlocked = nullptr;
188 ce->firstBlocked = nullptr;
189 ce->lastStopped = nullptr;
190 ce->dens = 0;
191 ce->lane->getVehiclesSecure();
192
193 //std::cout << SIMTIME << " initChanger lane=" << ce->lane->getID() << " vehicles=" << toString(ce->lane->myVehicles) << "\n";
194 }
195}
196
197
198void
199MSLaneChanger::updateChanger(bool vehHasChanged) {
200 assert(veh(myCandi) != 0);
201
202 // "Push" the vehicles to the back, i.e. follower becomes vehicle,
203 // vehicle becomes leader, and leader becomes predecessor of vehicle,
204 // if it exists.
205 if (!vehHasChanged) {
206 //std::cout << SIMTIME << " updateChanger: lane=" << myCandi->lane->getID() << " has new lead=" << veh(myCandi)->getID() << "\n";
207 myCandi->lead = veh(myCandi);
208 }
209
210 MSLane::VehCont& vehicles = myCandi->lane->myVehicles;
211 vehicles.pop_back();
212 //std::cout << SIMTIME << " updateChanger lane=" << myCandi->lane->getID() << " vehicles=" << toString(myCandi->lane->myVehicles) << "\n";
213}
214
215
216void
218
219 // Update the lane's vehicle-container.
220 // First: it is bad style to change other classes members, but for
221 // this release, other attempts were too time-consuming. In a next
222 // release we will change from this lane-centered design to a vehicle-
223 // centered. This will solve many problems.
224 // Second: this swap would be faster if vehicle-containers would have
225 // been pointers, but then I had to change too much of the MSLane code.
226 for (ChangerIt ce = myChanger.begin(); ce != myChanger.end(); ++ce) {
227 //std::cout << SIMTIME << " updateLanes lane=" << ce->lane->getID() << " myVehicles=" << toString(ce->lane->myVehicles) << " myTmpVehicles=" << toString(ce->lane->myTmpVehicles) << "\n";
228 ce->lane->swapAfterLaneChange(t);
229 ce->lane->releaseVehicles();
230 }
231}
232
233
236 // Find the vehicle in myChanger with the largest position. If there
237 // is no vehicle in myChanger (shouldn't happen) , return myChanger.end().
238 ChangerIt max = myChanger.end();
239#ifdef DEBUG_CANDIDATE
240 std::cout << SIMTIME << " findCandidate() on edge " << myChanger.begin()->lane->getEdge().getID() << std::endl;
241#endif
242
243 for (ChangerIt ce = myChanger.begin(); ce != myChanger.end(); ++ce) {
244 if (veh(ce) == nullptr) {
245 continue;
246 }
247#ifdef DEBUG_CANDIDATE
248 std::cout << " lane = " << ce->lane->getID() << "\n";
249 std::cout << " check vehicle=" << veh(ce)->getID() << " pos=" << veh(ce)->getPositionOnLane() << " lane=" << ce->lane->getID() << " isFrontOnLane=" << veh(ce)->isFrontOnLane(ce->lane) << "\n";
250#endif
251 if (max == myChanger.end()) {
252#ifdef DEBUG_CANDIDATE
253 std::cout << " new max vehicle=" << veh(ce)->getID() << " pos=" << veh(ce)->getPositionOnLane() << " lane=" << ce->lane->getID() << " isFrontOnLane=" << veh(ce)->isFrontOnLane(ce->lane) << "\n";
254#endif
255 max = ce;
256 continue;
257 }
258 assert(veh(ce) != 0);
259 assert(veh(max) != 0);
260 if (veh(max)->getPositionOnLane() < veh(ce)->getPositionOnLane()) {
261#ifdef DEBUG_CANDIDATE
262 std::cout << " new max vehicle=" << veh(ce)->getID() << " pos=" << veh(ce)->getPositionOnLane() << " lane=" << ce->lane->getID() << " isFrontOnLane=" << veh(ce)->isFrontOnLane(ce->lane) << " oldMaxPos=" << veh(max)->getPositionOnLane() << "\n";
263#endif
264 max = ce;
265 }
266 }
267 assert(max != myChanger.end());
268 assert(veh(max) != 0);
269 return max;
270}
271
272
273bool
274MSLaneChanger::mayChange(int direction) const {
275 if (direction == 0) {
276 return true;
277 }
278 if (!myAllowsChanging) {
279 return false;
280 }
282 if (direction == -1) {
283 return myCandi->mayChangeRight && (myCandi - 1)->lane->allowsVehicleClass(svc) && myCandi->lane->allowsChangingRight(svc);
284 } else if (direction == 1) {
285 return myCandi->mayChangeLeft && (myCandi + 1)->lane->allowsVehicleClass(svc) && myCandi->lane->allowsChangingLeft(svc);
286 } else {
287 return false;
288 }
289}
290
291
292bool
294 // Find change-candidate. If it is on an allowed lane, try to change
295 // to the right (there is a rule in Germany that you have to change
296 // to the right, unless you are overtaking). If change to the right
297 // isn't possible, check if there is a possibility to overtake (on the
298 // left.
299 // If candidate isn't on an allowed lane, changing to an allowed has
300 // priority.
301
302#ifdef DEBUG_ACTIONSTEPS
303// std::cout<< "\nCHANGE" << std::endl;
304#endif
305
306
308 MSVehicle* vehicle = veh(myCandi);
310
311 if (vehicle->getLaneChangeModel().isChangingLanes() && !vehicle->getLaneChangeModel().alreadyChanged()) {
312 return continueChange(vehicle, myCandi);
313 }
314 if (!myAllowsChanging || vehicle->getLaneChangeModel().alreadyChanged() || vehicle->isStoppedOnLane()) {
315 registerUnchanged(vehicle);
316 if (vehicle->isStoppedOnLane()) {
317 myCandi->lastStopped = vehicle;
318 }
319 return false;
320 }
321
322 if (!vehicle->isActive()) {
323#ifdef DEBUG_ACTIONSTEPS
324 if (DEBUG_COND) {
325 std::cout << SIMTIME << " veh '" << vehicle->getID() << "' skips regular change checks." << std::endl;
326 }
327#endif
328 bool changed = false;
329 const int oldstate = vehicle->getLaneChangeModel().getOwnState();
330 // let TraCI influence the wish to change lanes during non-actionsteps
331 checkTraCICommands(vehicle);
332 if (oldstate != vehicle->getLaneChangeModel().getOwnState()) {
333 changed = applyTraCICommands(vehicle);
334 }
335 if (!changed) {
336 registerUnchanged(vehicle);
337 }
338 return changed;
339 }
340
341 // Check for changes to the opposite lane if vehicle is active
342 std::pair<MSVehicle* const, double> leader = getRealLeader(myCandi);
343 if (myChanger.size() == 1 || vehicle->getLaneChangeModel().isOpposite() || (!mayChange(-1) && !mayChange(1))) {
344 if (changeOpposite(vehicle, leader, myCandi->lastStopped)) {
345 return true;
346 }
347 registerUnchanged(vehicle);
348 return false;
349 }
350
351 vehicle->updateBestLanes(); // needed?
352 for (int i = 0; i < (int) myChanger.size(); ++i) {
353 vehicle->adaptBestLanesOccupation(i, myChanger[i].dens);
354 }
355
356 const std::vector<MSVehicle::LaneQ>& preb = vehicle->getBestLanes();
357 // check whether the vehicle wants and is able to change to right lane
358 int stateRight = 0;
359 if (mayChange(-1)) {
360 stateRight = checkChangeWithinEdge(-1, leader, preb);
361 // change if the vehicle wants to and is allowed to change
362 if ((stateRight & LCA_RIGHT) != 0 && (stateRight & LCA_BLOCKED) == 0) {
363 vehicle->getLaneChangeModel().setOwnState(stateRight);
364 return startChange(vehicle, myCandi, -1);
365 }
366 if ((stateRight & LCA_RIGHT) != 0 && (stateRight & LCA_URGENT) != 0) {
367 (myCandi - 1)->lastBlocked = vehicle;
368 if ((myCandi - 1)->firstBlocked == nullptr) {
369 (myCandi - 1)->firstBlocked = vehicle;
370 }
371 }
372 }
373
374 // check whether the vehicle wants and is able to change to left lane
375 int stateLeft = 0;
376 if (mayChange(1)) {
377 stateLeft = checkChangeWithinEdge(1, leader, preb);
378 // change if the vehicle wants to and is allowed to change
379 if ((stateLeft & LCA_LEFT) != 0 && (stateLeft & LCA_BLOCKED) == 0) {
380 vehicle->getLaneChangeModel().setOwnState(stateLeft);
381 return startChange(vehicle, myCandi, 1);
382 }
383 if ((stateLeft & LCA_LEFT) != 0 && (stateLeft & LCA_URGENT) != 0) {
384 (myCandi + 1)->lastBlocked = vehicle;
385 if ((myCandi + 1)->firstBlocked == nullptr) {
386 (myCandi + 1)->firstBlocked = vehicle;
387 }
388 }
389 }
390
391 if ((stateRight & LCA_URGENT) != 0 && (stateLeft & LCA_URGENT) != 0) {
392 // ... wants to go to the left AND to the right
393 // just let them go to the right lane...
394 stateLeft = 0;
395 }
396 vehicle->getLaneChangeModel().setOwnState(stateRight | stateLeft);
397
398 // only emergency vehicles should change to the opposite side on a
399 // multi-lane road (or vehicles that need to stop on the opposite side)
400 if ((vehicle->getVClass() == SVC_EMERGENCY
401 || hasOppositeStop(vehicle))
402 && changeOpposite(vehicle, leader, myCandi->lastStopped)) {
403 return true;
404 }
405
406 registerUnchanged(vehicle);
407 return false;
408}
409
410
411void
413 //std::cout << SIMTIME << " registerUnchanged lane=" << myCandi->lane->getID() << " veh=" << vehicle->getID() << "\n";
414 myCandi->lane->myTmpVehicles.insert(myCandi->lane->myTmpVehicles.begin(), veh(myCandi));
415 myCandi->dens += vehicle->getVehicleType().getLengthWithGap();
416 vehicle->getLaneChangeModel().unchanged();
417}
418
419
420
421void
423#ifdef DEBUG_STATE
424 const int oldstate = vehicle->getLaneChangeModel().getOwnState();
425#endif
427#ifdef DEBUG_STATE
428 if (DEBUG_COND) {
429 const int newstate = vehicle->getLaneChangeModel().getOwnState();
430 std::cout << SIMTIME
431 << " veh=" << vehicle->getID()
432 << " oldState=" << toString((LaneChangeAction) oldstate)
433 << " newState=" << toString((LaneChangeAction) newstate)
434 << ((newstate & LCA_BLOCKED) != 0 ? " (blocked)" : "")
435 << ((newstate & LCA_OVERLAPPING) != 0 ? " (overlap)" : "")
436 << "\n";
437 }
438#endif
439}
440
441
442bool
444 // Execute request if not blocked
445 bool changed = false;
446 const int state = vehicle->getLaneChangeModel().getOwnState();
447 const int dir = (state & LCA_RIGHT) != 0 ? -1 : ((state & LCA_LEFT) != 0 ? 1 : 0);
448 const bool execute = dir != 0 && ((state & LCA_BLOCKED) == 0);
449 if (execute) {
450 ChangerIt to = myCandi + dir;
451 bool continuous = vehicle->getLaneChangeModel().startLaneChangeManeuver(myCandi->lane, to->lane, dir);
452 if (continuous) {
453 changed = continueChange(vehicle, myCandi);
454 } else {
455 // insert vehicle into target lane
456 to->registerHop(vehicle);
457 changed = true;
458 }
459 }
460 return changed;
461}
462
463
464bool
465MSLaneChanger::startChange(MSVehicle* vehicle, ChangerIt& from, int direction) {
466 if (vehicle->isRemoteControlled()) {
467 registerUnchanged(vehicle);
468 return false;
469 }
470 ChangerIt to = from + direction;
471 // @todo delay entering the target lane until the vehicle intersects it
472 // physically (considering lane width and vehicle width)
473 //if (to->lane->getID() == "beg_1") std::cout << SIMTIME << " startChange to lane=" << to->lane->getID() << " myTmpVehiclesBefore=" << toString(to->lane->myTmpVehicles) << "\n";
474 const bool continuous = vehicle->getLaneChangeModel().startLaneChangeManeuver(from->lane, to->lane, direction);
475 if (continuous) {
476 return continueChange(vehicle, myCandi);
477 } else {
478 to->registerHop(vehicle);
479 to->lane->requireCollisionCheck();
480 return true;
481 }
482}
483
484bool
487 const int direction = lcm.isOpposite() ? -lcm.getLaneChangeDirection() : lcm.getLaneChangeDirection();
488 const bool pastMidpoint = lcm.updateCompletion(); // computes lcm.mySpeedLat as a side effect
489 const double speedLat = lcm.isOpposite() ? -lcm.getSpeedLat() : lcm.getSpeedLat();
490 vehicle->myState.myPosLat += SPEED2DIST(speedLat);
492 //std::cout << SIMTIME << " veh=" << vehicle->getID() << " dir=" << direction << " pm=" << pastMidpoint << " speedLat=" << speedLat << " posLat=" << vehicle->myState.myPosLat << "\n";
493 if (pastMidpoint) {
494 MSLane* source = myCandi->lane;
495 MSLane* target = source->getParallelLane(direction);
496 vehicle->myState.myPosLat -= direction * 0.5 * (source->getWidth() + target->getWidth());
497 lcm.primaryLaneChanged(source, target, direction);
498 if (&source->getEdge() == &target->getEdge()) {
499 ChangerIt to = from + direction;
500 to->registerHop(vehicle);
501 }
502 target->requireCollisionCheck();
503 } else {
504 from->registerHop(vehicle);
505 from->lane->requireCollisionCheck();
506 }
507 if (!lcm.isChangingLanes()) {
508 vehicle->myState.myPosLat = 0;
510 }
511 lcm.updateShadowLane();
512 if (lcm.getShadowLane() != nullptr && &lcm.getShadowLane()->getEdge() == &vehicle->getLane()->getEdge()) {
513 // set as hoppedVeh on the shadow lane so it is found as leader on both lanes
514 myChanger[lcm.getShadowLane()->getIndex()].hoppedVeh = vehicle;
516 }
517 vehicle->myAngle = vehicle->computeAngle();
518 if (lcm.isOpposite()) {
519 vehicle->myAngle += M_PI;
520 }
521
522#ifdef DEBUG_CONTINUE_CHANGE
523 if (DEBUG_COND) {
524 std::cout << SIMTIME
525 << " continueChange veh=" << vehicle->getID()
526 << " from=" << Named::getIDSecure(from->lane)
527 << " dir=" << direction
528 << " speedLat=" << speedLat
529 << " pastMidpoint=" << pastMidpoint
530 << " posLat=" << vehicle->getLateralPositionOnLane()
531 << " completion=" << lcm.getLaneChangeCompletion()
532 << " shadowLane=" << Named::getIDSecure(lcm.getShadowLane())
533 //<< " shadowHopped=" << Named::getIDSecure(shadow->lane)
534 << "\n";
535 }
536#endif
537 return pastMidpoint && lcm.getShadowLane() == nullptr;
538}
539
540
541std::pair<MSVehicle* const, double>
543 assert(veh(myCandi) != 0);
544 MSVehicle* vehicle = veh(myCandi);
545#ifdef DEBUG_SURROUNDING_VEHICLES
546 if (DEBUG_COND) {
547 std::cout << SIMTIME << " veh '" << vehicle->getID() << "' looks for leader on lc-target lane '" << target->lane->getID() << "'." << std::endl;
548 }
549#endif
550 // get the leading vehicle on the lane to change to
551 MSVehicle* neighLead = target->lead;
552
553#ifdef DEBUG_SURROUNDING_VEHICLES
554 if (DEBUG_COND) {
555 if (neighLead != 0) {
556 std::cout << "Considering '" << neighLead->getID() << "' at position " << neighLead->getPositionOnLane() << std::endl;
557 }
558 }
559#endif
560
561 // check whether the hopped vehicle became the leader
562 if (target->hoppedVeh != nullptr) {
563 double hoppedPos = target->hoppedVeh->getPositionOnLane();
564#ifdef DEBUG_SURROUNDING_VEHICLES
565 if (DEBUG_COND) {
566 std::cout << "Considering hopped vehicle '" << target->hoppedVeh->getID() << "' at position " << hoppedPos << std::endl;
567 }
568#endif
569 if (hoppedPos > vehicle->getPositionOnLane() && (neighLead == nullptr || neighLead->getPositionOnLane() > hoppedPos)) {
570 neighLead = target->hoppedVeh;
571 //if (vehicle->getID() == "flow.21") std::cout << SIMTIME << " neighLead=" << Named::getIDSecure(neighLead) << " (422)\n";
572 }
573 }
574 // extra check for shared lane
575 const bool checkBidi = target->lane->getBidiLane() != nullptr && target->lane->getBidiLane()->getVehicleNumberWithPartials() > 0;
576 if (neighLead == nullptr || checkBidi) {
577#ifdef DEBUG_SURROUNDING_VEHICLES
578 if (DEBUG_COND) {
579 std::cout << "Looking for leader on consecutive lanes." << std::endl;
580 }
581#endif
582 // There's no leader on the target lane. Look for leaders on consecutive lanes.
583 // (there might also be partial leaders due to continuous lane changing or bidiLane)
584 MSLane* targetLane = target->lane;
585 const double egoBack = vehicle->getBackPositionOnLane();
586 double leaderBack = targetLane->getLength();
587 if (neighLead != nullptr) {
588 leaderBack = neighLead->getBackPositionOnLane(targetLane);
589 }
590 for (MSVehicle* pl : targetLane->myPartialVehicles) {
591 double plBack = pl->getBackPositionOnLane(targetLane);
592 if (pl->isBidiOn(targetLane)) {
593 plBack -= pl->getVehicleType().getLengthWithGap();
594 }
595 const double plPos = plBack + pl->getVehicleType().getLength();
596#ifdef DEBUG_SURROUNDING_VEHICLES
597 if (DEBUG_COND) {
598 std::cout << " partial=" << pl->getID() << " plBack=" << plBack << " plPos=" << plPos << " leaderBack=" << leaderBack << " egoBack=" << egoBack << "\n";
599 }
600#endif
601 if (plBack < leaderBack && plPos + pl->getVehicleType().getMinGap() >= egoBack) {
602 neighLead = pl;
603 leaderBack = plBack;
604 }
605 }
606 if (neighLead != nullptr) {
607#ifdef DEBUG_SURROUNDING_VEHICLES
608 if (DEBUG_COND) {
609 std::cout << " found leader=" << neighLead->getID() << " (partial)\n";
610 }
611#endif
612 const double gap = leaderBack - vehicle->getPositionOnLane() - vehicle->getVehicleType().getMinGap();
613 return std::pair<MSVehicle*, double>(neighLead, gap);
614 }
615 double seen = myCandi->lane->getLength() - vehicle->getPositionOnLane();
616 double speed = vehicle->getSpeed();
617 double dist = vehicle->getCarFollowModel().brakeGap(speed) + vehicle->getVehicleType().getMinGap();
618 if (target->lane->getBidiLane() != nullptr) {
619 dist += target->lane->getBidiLane()->getMaximumBrakeDist();
620 }
621 // always check for link leaders while on an internal lane
622 if (seen > dist && !myCandi->lane->isInternal()) {
623#ifdef DEBUG_SURROUNDING_VEHICLES
624 if (DEBUG_COND) {
625 std::cout << " found no leader within dist=" << dist << "\n";
626 }
627#endif
628 return std::pair<MSVehicle* const, double>(static_cast<MSVehicle*>(nullptr), -1);
629 }
630 const std::vector<MSLane*>& bestLaneConts = vehicle->getBestLanesContinuation(targetLane);
631
632 std::pair<MSVehicle* const, double> result = target->lane->getLeaderOnConsecutive(dist, seen, speed, *vehicle, bestLaneConts);
633#ifdef DEBUG_SURROUNDING_VEHICLES
634 if (DEBUG_COND) {
635 std::cout << " found consecutiveLeader=" << Named::getIDSecure(result.first) << "\n";
636 }
637#endif
638 return result;
639 } else {
640#ifdef DEBUG_SURROUNDING_VEHICLES
641 if (DEBUG_COND) {
642 std::cout << " found leader=" << neighLead->getID() << "\n";
643 }
644#endif
645 return std::pair<MSVehicle* const, double>(neighLead, neighLead->getBackPositionOnLane(target->lane) - vehicle->getPositionOnLane() - vehicle->getVehicleType().getMinGap());
646 }
647}
648
649
650std::pair<MSVehicle* const, double>
652 assert(veh(myCandi) != 0);
653 MSVehicle* vehicle = veh(myCandi);
654#ifdef DEBUG_SURROUNDING_VEHICLES
655 if (DEBUG_COND) {
656 std::cout << SIMTIME << " veh '" << vehicle->getID() << "' looks for follower on lc-target lane '" << target->lane->getID() << "'." << std::endl;
657 }
658#endif
659 const double candiPos = vehicle->getPositionOnLane();
660 MSVehicle* neighFollow = nullptr;
661 if (target != myCandi) {
662 neighFollow = veh(target);
663 } else {
664 // veh(target) would return the ego vehicle so we use its predecessor instead
665 if (target->lane->myVehicles.size() > 1) {
666 neighFollow = target->lane->myVehicles[target->lane->myVehicles.size() - 2];
667 }
668 }
669
670#ifdef DEBUG_SURROUNDING_VEHICLES
671 if (DEBUG_COND) {
672 if (neighFollow != 0) {
673 std::cout << "veh(target) returns '" << neighFollow->getID() << "' at position " << neighFollow->getPositionOnLane() << std::endl;
674 } else {
675 std::cout << "veh(target) returns none." << std::endl;
676 }
677 }
678#endif
679
680
681#ifdef DEBUG_SURROUNDING_VEHICLES
682 if (DEBUG_COND) {
683 if (getCloserFollower(candiPos, neighFollow, target->hoppedVeh) != neighFollow) {
684 std::cout << "Hopped vehicle '" << target->hoppedVeh->getID() << "' at position " << target->hoppedVeh->getPositionOnLane() << " is closer." << std::endl;
685 }
686 }
687#endif
688
689 // check whether the hopped vehicle became the follower
690 neighFollow = getCloserFollower(candiPos, neighFollow, target->hoppedVeh);
691
692
693#ifdef DEBUG_SURROUNDING_VEHICLES
694 if (DEBUG_COND) {
695 MSVehicle* partialBehind = getCloserFollower(candiPos, neighFollow, target->lane->getPartialBehind(vehicle));
696 if (partialBehind != 0 && partialBehind != neighFollow) {
697 std::cout << "'Partial behind'-vehicle '" << target->lane->getPartialBehind(vehicle)->getID() << "' at position " << partialBehind->getPositionOnLane() << " is closer." << std::endl;
698 }
699 }
700#endif
701 // or a follower which is partially lapping into the target lane
702 neighFollow = getCloserFollower(candiPos, neighFollow, target->lane->getPartialBehind(vehicle));
703
704 if (neighFollow == nullptr) {
705 CLeaderDist consecutiveFollower = target->lane->getFollowersOnConsecutive(vehicle, vehicle->getBackPositionOnLane(), true)[0];
706#ifdef DEBUG_SURROUNDING_VEHICLES
707 if (DEBUG_COND) {
708 if (consecutiveFollower.first == 0) {
709 std::cout << "no follower found." << std::endl;
710 } else {
711 std::cout << "found follower '" << consecutiveFollower.first->getID() << "' on consecutive lanes." << std::endl;
712 }
713 }
714#endif
715 return std::make_pair(const_cast<MSVehicle*>(consecutiveFollower.first), consecutiveFollower.second);
716 } else {
717#ifdef DEBUG_SURROUNDING_VEHICLES
718 if (DEBUG_COND) {
719 std::cout << "found follower '" << neighFollow->getID() << "'." << std::endl;
720 }
721#endif
722 return std::pair<MSVehicle* const, double>(neighFollow,
723 vehicle->getPositionOnLane() - vehicle->getVehicleType().getLength() - neighFollow->getPositionOnLane() - neighFollow->getVehicleType().getMinGap());
724 }
725}
726
727
729MSLaneChanger::getCloserFollower(const double maxPos, MSVehicle* follow1, MSVehicle* follow2) {
730 if (follow1 == nullptr || follow1->getPositionOnLane() > maxPos) {
731 return follow2;
732 } else if (follow2 == nullptr || follow2->getPositionOnLane() > maxPos) {
733 return follow1;
734 } else {
735 if (follow1->getPositionOnLane() > follow2->getPositionOnLane()) {
736 return follow1;
737 } else {
738 return follow2;
739 }
740 }
741}
742
743int
745 int laneOffset,
746 const std::pair<MSVehicle* const, double>& leader,
747 const std::vector<MSVehicle::LaneQ>& preb) const {
748
749 std::pair<MSVehicle*, double> follower = getRealFollower(myCandi);
750 std::pair<MSVehicle* const, double> neighLead = getRealLeader(myCandi + laneOffset);
751 std::pair<MSVehicle*, double> neighFollow = getRealFollower(myCandi + laneOffset);
752 if (neighLead.first != nullptr && neighLead.first == neighFollow.first) {
753 // vehicles should not be leader and follower at the same time to avoid
754 // contradictory behavior
755 neighFollow.first = 0;
756 }
757 ChangerIt target = myCandi + laneOffset;
758 return checkChange(laneOffset, target->lane, leader, follower, neighLead, neighFollow, preb);
759}
760
761int
763 int laneOffset,
764 const MSLane* targetLane,
765 const std::pair<MSVehicle* const, double>& leader,
766 const std::pair<MSVehicle* const, double>& follower,
767 const std::pair<MSVehicle* const, double>& neighLead,
768 const std::pair<MSVehicle* const, double>& neighFollow,
769 const std::vector<MSVehicle::LaneQ>& preb) const {
770
771 MSVehicle* vehicle = veh(myCandi);
772
773#ifdef DEBUG_CHECK_CHANGE
774 if (DEBUG_COND) {
775 std::cout
776 << "\n" << SIMTIME << " checkChange() for vehicle '" << vehicle->getID() << "'"
777 << std::endl;
778 }
779#endif
780
781 int blocked = 0;
782 int blockedByLeader = (laneOffset == -1 ? LCA_BLOCKED_BY_RIGHT_LEADER : LCA_BLOCKED_BY_LEFT_LEADER);
783 int blockedByFollower = (laneOffset == -1 ? LCA_BLOCKED_BY_RIGHT_FOLLOWER : LCA_BLOCKED_BY_LEFT_FOLLOWER);
784 // overlap
785 if (neighFollow.first != nullptr && neighFollow.second < 0) {
786 blocked |= (blockedByFollower | LCA_OVERLAPPING);
787
788 // Debug (Leo)
789#ifdef DEBUG_CHECK_CHANGE
790 if (DEBUG_COND) {
791 std::cout << SIMTIME
792 << " overlapping with follower..."
793 << std::endl;
794 }
795#endif
796
797 }
798 if (neighLead.first != nullptr && neighLead.second < 0) {
799 blocked |= (blockedByLeader | LCA_OVERLAPPING);
800
801#ifdef DEBUG_CHECK_CHANGE
802 if (DEBUG_COND) {
803 std::cout << SIMTIME
804 << " overlapping with leader..."
805 << std::endl;
806 }
807#endif
808
809 }
810 double secureFrontGap = MSAbstractLaneChangeModel::NO_NEIGHBOR;
811 double secureBackGap = MSAbstractLaneChangeModel::NO_NEIGHBOR;
812 double secureOrigFrontGap = MSAbstractLaneChangeModel::NO_NEIGHBOR;
813
814 const double tauRemainder = vehicle->getActionStepLength() == DELTA_T ? 0 : MAX2(vehicle->getCarFollowModel().getHeadwayTime() - TS, 0.);
815 // safe back gap
816 if ((blocked & blockedByFollower) == 0 && neighFollow.first != nullptr) {
817 // Calculate secure gap conservatively with vNextFollower / vNextLeader as
818 // extrapolated speeds after the driver's expected reaction time (tau).
819 // NOTE: there exists a possible source for collisions if the follower and the leader
820 // have desynchronized action steps as the extrapolated speeds can be exceeded in this case
821
822 // Expected reaction time (tau) for the follower-vehicle.
823 // (subtracted TS since at this point the vehicles' states are already updated)
824 const double vNextFollower = neighFollow.first->getSpeed() + MAX2(0., tauRemainder * neighFollow.first->getAcceleration());
825 const double vNextLeader = vehicle->getSpeed() + MIN2(0., tauRemainder * vehicle->getAcceleration());
826 // !!! eigentlich: vsafe braucht die Max. Geschwindigkeit beider Spuren
827 secureBackGap = neighFollow.first->getCarFollowModel().getSecureGap(neighFollow.first, vehicle, vNextFollower,
828 vNextLeader, vehicle->getCarFollowModel().getMaxDecel());
829#ifdef DEBUG_CHECK_CHANGE
830 if (DEBUG_COND) {
831 std::cout << SIMTIME
832 << " follower=" << neighFollow.first->getID()
833 << " backGap=" << neighFollow.second
834 << " vNextFollower=" << vNextFollower
835 << " vNextEgo=" << vNextLeader
836 << " secureGap=" << secureBackGap
837 << " safetyFactor=" << vehicle->getLaneChangeModel().getSafetyFactor()
838 << " blocked=" << (neighFollow.second < secureBackGap * vehicle->getLaneChangeModel().getSafetyFactor())
839 << "\n";
840 }
841#endif
842 if (neighFollow.second < secureBackGap * vehicle->getLaneChangeModel().getSafetyFactor()) {
843 if (vehicle->getLaneChangeModel().isOpposite()
844 && neighFollow.first->getLaneChangeModel().getLastLaneChangeOffset() == laneOffset) {
845 // during opposite direction driving, the vehicle are handled in
846 // downstream rather than upstream order, the neighFollower may have
847 // been the actual follower in this simulation step and should not
848 // block changing in this case
849#ifdef DEBUG_CHECK_CHANGE
850 if (DEBUG_COND) {
851 std::cout << " ignoring opposite follower who changed in this step\n";
852 }
853#endif
854 } else {
855 blocked |= blockedByFollower;
856 }
857 }
858 }
859
860 // safe front gap
861 if ((blocked & blockedByLeader) == 0 && neighLead.first != nullptr) {
862 // Calculate secure gap conservatively with vNextFollower / vNextLeader as
863 // extrapolated speeds after the driver's expected reaction time (tau).
864 // NOTE: there exists a possible source for collisions if the follower and the leader
865 // have desynchronized action steps as the extrapolated speeds can be exceeded in this case
866
867 // Expected reaction time (tau) for the follower-vehicle.
868 // (subtracted TS since at this point the vehicles' states are already updated)
869 const double vNextFollower = vehicle->getSpeed() + MAX2(0., tauRemainder * vehicle->getAcceleration());
870 const double vNextLeader = neighLead.first->getSpeed() + MIN2(0., tauRemainder * neighLead.first->getAcceleration());
871 // !!! eigentlich: vsafe braucht die Max. Geschwindigkeit beider Spuren
872 secureFrontGap = vehicle->getCarFollowModel().getSecureGap(vehicle, neighLead.first, vNextFollower,
873 vNextLeader, neighLead.first->getCarFollowModel().getMaxDecel());
874#ifdef DEBUG_CHECK_CHANGE
875 if (DEBUG_COND) {
876 std::cout << SIMTIME
877 << " leader=" << neighLead.first->getID()
878 << " frontGap=" << neighLead.second
879 << " vNextEgo=" << vNextFollower
880 << " vNextLeader=" << vNextLeader
881 << " secureGap=" << secureFrontGap
882 << " safetyFactor=" << vehicle->getLaneChangeModel().getSafetyFactor()
883 << " blocked=" << (neighLead.second < secureFrontGap * vehicle->getLaneChangeModel().getSafetyFactor())
884 << "\n";
885 }
886#endif
887 if (neighLead.second < secureFrontGap * vehicle->getLaneChangeModel().getSafetyFactor()) {
888 blocked |= blockedByLeader;
889 }
890 }
891 if (blocked == 0 && targetLane->hasPedestrians()) {
892 PersonDist nextLeader = targetLane->nextBlocking(vehicle->getBackPositionOnLane(),
893 vehicle->getRightSideOnLane(targetLane), vehicle->getRightSideOnLane(targetLane) + vehicle->getVehicleType().getWidth(),
894 ceil(vehicle->getSpeed() / vehicle->getCarFollowModel().getMaxDecel()));
895 if (nextLeader.first != 0) {
896 const double brakeGap = vehicle->getCarFollowModel().brakeGap(vehicle->getSpeed());
897 // returned gap value is relative to backPosition
898 const double gap = nextLeader.second - vehicle->getVehicleType().getLengthWithGap();
899#ifdef DEBUG_CHECK_CHANGE
900 if (DEBUG_COND) {
901 std::cout << SIMTIME << " pedestrian on road " + leader.first->getID() << " gap=" << gap << " brakeGap=" << brakeGap << "\n";
902 }
903#endif
904 if (brakeGap > gap) {
905 blocked |= blockedByLeader;
906#ifdef DEBUG_CHECK_CHANGE
907 if (DEBUG_COND) {
908 std::cout << SIMTIME << " blocked by pedestrian " + leader.first->getID() << "\n";
909 }
910#endif
911 }
912 }
913 }
914
915 if (leader.first != nullptr) {
916 secureOrigFrontGap = vehicle->getCarFollowModel().getSecureGap(vehicle, leader.first, vehicle->getSpeed(), leader.first->getSpeed(), leader.first->getCarFollowModel().getMaxDecel());
917 }
918
919 MSAbstractLaneChangeModel::MSLCMessager msg(leader.first, neighLead.first, neighFollow.first);
920 int state = blocked | vehicle->getLaneChangeModel().wantsChange(
921 laneOffset, msg, blocked, leader, follower, neighLead, neighFollow, *targetLane, preb, &(myCandi->lastBlocked), &(myCandi->firstBlocked));
922
923 if (blocked == 0 && (state & LCA_WANTS_LANECHANGE) != 0 && neighLead.first != nullptr) {
924 // do a more careful (but expensive) check to ensure that a
925 // safety-critical leader is not being overlooked
926 // while changing on an intersection, it is not sufficient to abort the
927 // search with a leader on the current lane because all linkLeaders must
928 // be considered as well
929 const double seen = myCandi->lane->getLength() - vehicle->getPositionOnLane();
930 const double speed = vehicle->getSpeed();
931 const double dist = vehicle->getCarFollowModel().brakeGap(speed) + vehicle->getVehicleType().getMinGap();
932 if (seen < dist || myCandi->lane->isInternal()) {
933 std::pair<MSVehicle* const, double> neighLead2 = targetLane->getCriticalLeader(dist, seen, speed, *vehicle);
934 if (neighLead2.first != nullptr && neighLead2.first != neighLead.first) {
935 const double secureGap = vehicle->getCarFollowModel().getSecureGap(vehicle, neighLead2.first, vehicle->getSpeed(),
936 neighLead2.first->getSpeed(), neighLead2.first->getCarFollowModel().getMaxDecel());
937 const double secureGap2 = secureGap * vehicle->getLaneChangeModel().getSafetyFactor();
938#ifdef DEBUG_SURROUNDING_VEHICLES
939 if (DEBUG_COND) {
940 std::cout << SIMTIME << " found critical leader=" << neighLead2.first->getID()
941 << " gap=" << neighLead2.second << " secGap=" << secureGap << " secGap2=" << secureGap2 << "\n";
942 }
943#endif
944 if (neighLead2.second < secureGap2) {
945 state |= blockedByLeader;
946 }
947 }
948 }
949 }
950 if (blocked == 0 && (state & LCA_WANTS_LANECHANGE)) {
951 // ensure that merging is safe for any upcoming zipper links after changing
952 double targetZipperDist = 0;
953 if (laneOffset == 0) {
954 targetZipperDist = myCandi->zipperDist;
955 } else if (laneOffset == 1) {
956 if ((myCandi + 1) != myChanger.end()) {
957 targetZipperDist = (myCandi + 1)->zipperDist;
958 }
959 } else if (laneOffset == -1) {
960 if (myCandi > myChanger.begin()) {
961 targetZipperDist = (myCandi - 1)->zipperDist;
962 }
963 }
964 if (vehicle->unsafeLinkAhead(targetLane, targetZipperDist)) {
965 state |= blockedByLeader;
966 }
967 }
968
969 if ((state & LCA_BLOCKED) == 0 && (state & LCA_WANTS_LANECHANGE) != 0 && MSGlobals::gLaneChangeDuration > DELTA_T) {
970 // Ensure that a continuous lane change manoeuvre can be completed before the next turning movement.
971 // Assume lateral position == 0. (If this should change in the future add + laneOffset*vehicle->getLateralPositionOnLane() to distToNeighLane)
972 const double distToNeighLane = 0.5 * (vehicle->getLane()->getWidth() + targetLane->getWidth());
973 // Extrapolate the LC duration if operating with speed dependent lateral speed.
974 const MSAbstractLaneChangeModel& lcm = vehicle->getLaneChangeModel();
975 const double assumedDecel = lcm.getAssumedDecelForLaneChangeDuration();
976 const double estimatedLCDuration = lcm.estimateLCDuration(vehicle->getSpeed(), distToNeighLane, assumedDecel, (state & LCA_URGENT) != 0);
977 if (estimatedLCDuration == -1) {
978 // Can't guarantee that LC will succeed if vehicle is braking -> assert(lcm.myMaxSpeedLatStanding==0)
979#ifdef DEBUG_CHECK_CHANGE
980 if (DEBUG_COND) {
981 std::cout << SIMTIME << " checkChange() too slow to guarantee completion of continuous lane change."
982 << "\nestimatedLCDuration=" << estimatedLCDuration
983 << "\ndistToNeighLane=" << distToNeighLane
984 << std::endl;
985 }
986#endif
987 state |= LCA_INSUFFICIENT_SPEED;
988 } else {
989 // Compute covered distance, when braking for the whole lc duration
990 const double decel = vehicle->getCarFollowModel().getMaxDecel() * estimatedLCDuration;
991 const double avgSpeed = 0.5 * (
992 MAX2(0., vehicle->getSpeed() - ACCEL2SPEED(vehicle->getCarFollowModel().getMaxDecel())) +
993 MAX2(0., vehicle->getSpeed() - decel));
994 // Distance required for lane change.
995 const double space2change = avgSpeed * estimatedLCDuration;
996 // Available distance for LC maneuver (distance till next turn)
997 double seen = myCandi->lane->getLength() - vehicle->getPositionOnLane();
998#ifdef DEBUG_CHECK_CHANGE
999 if (DEBUG_COND) {
1000 std::cout << SIMTIME << " checkChange() checking continuous lane change..."
1001 << "\ndistToNeighLane=" << distToNeighLane
1002 << " estimatedLCDuration=" << estimatedLCDuration
1003 << " space2change=" << space2change
1004 << " avgSpeed=" << avgSpeed
1005 << std::endl;
1006 }
1007#endif
1008
1009 // for finding turns it doesn't matter whether we look along the current lane or the target lane
1010 const std::vector<MSLane*>& bestLaneConts = vehicle->getBestLanesContinuation();
1011 int view = 1;
1012 const MSLane* nextLane = vehicle->getLane();
1013 std::vector<MSLink*>::const_iterator link = MSLane::succLinkSec(*vehicle, view, *nextLane, bestLaneConts);
1014 while (!nextLane->isLinkEnd(link) && seen <= space2change) {
1015 if ((*link)->getDirection() == LinkDirection::LEFT || (*link)->getDirection() == LinkDirection::RIGHT
1016 // the lanes after an internal junction are on different
1017 // edges and do not allow lane-changing
1018 || (nextLane->getEdge().isInternal() && (*link)->getViaLaneOrLane()->getEdge().isInternal())
1019 ) {
1020 state |= LCA_INSUFFICIENT_SPACE;
1021 break;
1022 }
1023 if ((*link)->getViaLane() == nullptr) {
1024 view++;
1025 }
1026 nextLane = (*link)->getViaLaneOrLane();
1027 seen += nextLane->getLength();
1028 // get the next link used
1029 link = MSLane::succLinkSec(*vehicle, view, *nextLane, bestLaneConts);
1030 }
1031#ifdef DEBUG_CHECK_CHANGE
1032 if (DEBUG_COND) {
1033 std::cout << " available distance=" << seen << std::endl;
1034 }
1035#endif
1036 if (nextLane->isLinkEnd(link) && seen < space2change) {
1037#ifdef DEBUG_CHECK_CHANGE
1038 if (DEBUG_COND) {
1039 std::cout << SIMTIME << " checkChange insufficientSpace: seen=" << seen << " space2change=" << space2change << "\n";
1040 }
1041#endif
1042 state |= LCA_INSUFFICIENT_SPACE;
1043 }
1044
1045 if ((state & LCA_BLOCKED) == 0) {
1046 // check for dangerous leaders in case the target lane changes laterally between
1047 // now and the lane-changing midpoint
1048 const double speed = vehicle->getSpeed();
1049 seen = myCandi->lane->getLength() - vehicle->getPositionOnLane();
1050 nextLane = vehicle->getLane();
1051 view = 1;
1052 const double dist = vehicle->getCarFollowModel().brakeGap(speed) + vehicle->getVehicleType().getMinGap();
1053 std::vector<MSLink*>::const_iterator nextLink = MSLane::succLinkSec(*vehicle, view, *nextLane, bestLaneConts);
1054 while (!nextLane->isLinkEnd(nextLink) && seen <= space2change && seen <= dist) {
1055 nextLane = (*nextLink)->getViaLaneOrLane();
1056 const MSLane* const parallelLane = nextLane->getParallelLane(laneOffset);
1057 if (parallelLane == nullptr) {
1058 state |= LCA_INSUFFICIENT_SPACE;
1059 break;
1060 } else {
1061 std::pair<MSVehicle* const, double> neighLead2 = parallelLane->getLeader(vehicle, -seen, std::vector<MSLane*>());
1062 if (neighLead2.first != nullptr && neighLead2.first != neighLead.first
1063 && (neighLead2.second < vehicle->getCarFollowModel().getSecureGap(vehicle, neighLead2.first,
1064 vehicle->getSpeed(), neighLead2.first->getSpeed(), neighLead2.first->getCarFollowModel().getMaxDecel()))) {
1065 state |= blockedByLeader;
1066 break;
1067 }
1068 }
1069 if ((*nextLink)->getViaLane() == nullptr) {
1070 view++;
1071 }
1072 seen += nextLane->getLength();
1073 // get the next link used
1074 nextLink = MSLane::succLinkSec(*vehicle, view, *nextLane, bestLaneConts);
1075 }
1076 }
1077 }
1078 }
1079 const int oldstate = state;
1080 // let TraCI influence the wish to change lanes and the security to take
1081 state = vehicle->influenceChangeDecision(state);
1082 blocked = state & LCA_BLOCKED;
1083#ifdef DEBUG_CHECK_CHANGE
1084 if (DEBUG_COND) {
1085 std::cout << SIMTIME
1086 << " veh=" << vehicle->getID()
1087 << " oldState=" << toString((LaneChangeAction)oldstate)
1088 << " newState=" << toString((LaneChangeAction)state)
1089 << ((blocked & LCA_BLOCKED) ? " (blocked)" : "")
1090 << ((blocked & LCA_OVERLAPPING) ? " (overlap)" : "")
1091 << "\n";
1092 }
1093#endif
1094
1095 if (state & LCA_WANTS_LANECHANGE && blocked == 0) {
1096 blocked = vehicle->getLaneChangeModel().checkChangeBeforeCommitting(vehicle, state);
1097 state |= blocked;
1098 }
1099 vehicle->getLaneChangeModel().saveLCState(laneOffset, oldstate, state);
1100 if (blocked == 0 && (state & LCA_WANTS_LANECHANGE)) {
1101 // this lane change will be executed, save gaps
1102 vehicle->getLaneChangeModel().setFollowerGaps(neighFollow, secureBackGap);
1103 vehicle->getLaneChangeModel().setLeaderGaps(neighLead, secureFrontGap);
1104 vehicle->getLaneChangeModel().setOrigLeaderGaps(leader, secureOrigFrontGap);
1105 }
1106 if (laneOffset != 0) {
1107 vehicle->getLaneChangeModel().saveNeighbors(laneOffset, neighFollow, neighLead);
1108 }
1109 return state;
1110}
1111
1112bool
1114 if (vehicle->hasStops()) {
1115 const MSStop& stop = vehicle->getNextStop();
1117 return true;
1118 }
1119 }
1120 return false;
1121}
1122
1123
1124bool
1125MSLaneChanger::checkOppositeStop(MSVehicle* vehicle, const MSLane* oncomingLane, const MSLane* opposite, std::pair<MSVehicle*, double> leader) {
1126 const bool isOpposite = vehicle->getLaneChangeModel().isOpposite();
1127 double vMax = vehicle->getLane()->getVehicleMaxSpeed(vehicle);
1128 std::pair<MSVehicle*, double> neighLead(nullptr, -1);
1129 std::pair<MSVehicle*, double> oncoming(nullptr, -1);
1130 const std::vector<MSVehicle::LaneQ> preb = getBestLanesOpposite(vehicle, vehicle->getNextStop().lane, -1);
1131 const int laneIndex = vehicle->getLaneChangeModel().getNormalizedLaneIndex();
1132 const int bestOffset = preb[laneIndex].bestLaneOffset;
1133 //std::cout << SIMTIME << " veh=" << vehicle->getID() << " laneIndex=" << laneIndex << " bestOffset=" << bestOffset << " target=" << target->getID() << "\n";
1134
1135 // compute safety constraints (assume vehicle is safe once stop is reached)
1136 const double spaceToStop = vehicle->nextStopDist();
1137 const double timeToStopForward = spaceToStop / MAX2(vehicle->getSpeed(), vehicle->getCarFollowModel().getMaxAccel());
1138 const double timeToStopLateral = (MSGlobals::gLaneChangeDuration > 0
1141 ? bestOffset * SUMO_const_laneWidth / vehicle->getVehicleType().getMaxSpeedLat()
1142 : 0.));
1143 const double timeToStop = MAX2(timeToStopForward, timeToStopLateral);
1144 if (!isOpposite) {
1145 // we keep neighLead distinct from oncoming because it determines blocking on the neigh lane
1146 // but also look for an oncoming leader to compute safety constraint
1147 const double searchDist = timeToStop * oncomingLane->getSpeedLimit() * 2 + spaceToStop;
1148 neighLead = oncomingLane->getOppositeLeader(vehicle, searchDist, true);
1149 oncoming = getOncomingVehicle(oncomingLane, neighLead, searchDist, vMax);
1150 } else {
1151 double searchDist = OPPOSITE_OVERTAKING_ONCOMING_LOOKAHEAD;
1152 oncoming = oncomingLane->getOppositeLeader(vehicle, searchDist, true);
1153 oncoming = getOncomingVehicle(oncomingLane, oncoming, searchDist, vMax);
1154 }
1155 double oncomingSpeed;
1156 const double surplusGap = computeSurplusGap(vehicle, opposite, oncoming, timeToStop, spaceToStop, oncomingSpeed);
1157 if (!isOpposite && surplusGap < 0) {
1158#ifdef DEBUG_CHANGE_OPPOSITE
1159 if (DEBUG_COND) {
1160 std::cout << " cannot changeOppositeStop due to dangerous oncoming spaceToStop=" << spaceToStop
1161 << " timeToStopForward=" << timeToStopForward << " timeToStopLateral=" << timeToStopLateral << " surplusGap=" << surplusGap << "\n";
1162 }
1163#endif
1164 return false;
1165 }
1166
1167 if (bestOffset > 0) {
1168 MSLane* const target = preb[laneIndex + 1].lane;
1169 neighLead = target->getOppositeLeader(vehicle, OPPOSITE_OVERTAKING_MAX_LOOKAHEAD, true);
1170 std::pair<MSVehicle* const, double> neighFollow = target->getOppositeFollower(vehicle);
1171 return checkChangeOpposite(vehicle, 1, target, leader, neighLead, neighFollow, preb);
1172 } else {
1173 // return prematurely (due to foe?)
1174 //return checkChangeOpposite(vehicle, -1, target, leader, neighLead, neighFollow, preb);
1175 return false;
1176 }
1177}
1178
1179
1180std::vector<MSVehicle::LaneQ>
1181MSLaneChanger::getBestLanesOpposite(MSVehicle* vehicle, const MSLane* stopLane, double oppositeLength) {
1182 const bool isOpposite = vehicle->getLaneChangeModel().isOpposite();
1183 const MSEdge* forward = isOpposite ? vehicle->getLane()->getEdge().getOppositeEdge()->getNormalSuccessor() : vehicle->getLane()->getEdge().getNormalSuccessor();
1184 const MSEdge* opposite = forward->getOppositeEdge();
1185 const int numForward = forward->getNumLanes();
1186 const int numOpposite = opposite->getNumLanes();
1187 const std::vector<MSLane*>& oLanes = opposite->getLanes();
1188 std::vector<MSVehicle::LaneQ> preb = vehicle->getBestLanes();
1189 for (int i = 0; i < numOpposite; i++) {
1190 preb.push_back(preb.back());
1191 preb.back().lane = oLanes[numOpposite - 1 - i];
1192 preb.back().length = oppositeLength;
1193 if (isOpposite) {
1194 preb.back().bestLaneOffset = -1 - i;
1195 //std::cout << " oi=" << i << " bestOffset =" << preb.back().bestLaneOffset << "\n";
1196 }
1197 }
1198 if (stopLane != nullptr) {
1199 const int stopIndex = numForward + numOpposite - stopLane->getIndex() - 1;
1200 for (int i = 0; i < (int)preb.size(); i++) {
1201 preb[i].bestLaneOffset = stopIndex - i;
1202 preb[i].length = vehicle->getLaneChangeModel().getForwardPos() + vehicle->nextStopDist();
1203 //std::cout << " oi2=" << i << " stopIndex=" << stopIndex << " bestOffset =" << preb[i].bestLaneOffset << " stopDist=" << vehicle->nextStopDist() << " length=" << preb[i].length << "\n";
1204 }
1205 }
1206#ifdef DEBUG_CHANGE_OPPOSITE
1207 if (DEBUG_COND) {
1208 std::cout << SIMTIME << " getBestLanesOpposite " << vehicle->getID() << " isOpposite=" << isOpposite << "\n";
1209 for (int i = 0; i < (int)preb.size(); i++) {
1210 std::cout << " i=" << i << " lane=" << preb[i].lane->getID() << " bestOffset=" << preb[i].bestLaneOffset << " length=" << preb[i].length << "\n";
1211 }
1212 }
1213#endif
1214 return preb;
1215}
1216
1217
1218bool
1219MSLaneChanger::changeOpposite(MSVehicle* vehicle, std::pair<MSVehicle*, double> leader, MSVehicle* lastStopped) {
1220 // Evaluate lane-changing between opposite direction lanes
1221 if (!myChangeToOpposite) {
1222 return false;
1223 }
1224 const bool isOpposite = vehicle->getLaneChangeModel().isOpposite();
1225 MSLane* source = vehicle->getMutableLane();
1226 MSLane* opposite = isOpposite ? source->getParallelLane(1) : source->getOpposite();
1227
1228#ifdef DEBUG_CHANGE_OPPOSITE
1230 if (DEBUG_COND) {
1231 std::cout << SIMTIME << " veh=" << vehicle->getID() << " considerChangeOpposite source=" << source->getID()
1232 << " opposite=" << Named::getIDSecure(opposite) << " lead=" << Named::getIDSecure(leader.first) << " isOpposite=" << isOpposite << "\n";
1233 }
1234#endif
1235 //There is no lane for opposite driving
1236 if (opposite == nullptr) {
1237 return false;
1238 }
1239 if (vehicle->isStopped()) {
1240 // stopped vehicles obviously should not change lanes. Usually this is
1241 // prevent by appropriate bestLane distances
1242 return false;
1243 }
1244 int ret = 0;
1245 ret = vehicle->influenceChangeDecision(ret);
1246 bool oppositeChangeByTraci = false;
1247 // Check whether a lane change to the opposite direction was requested via TraCI
1248 if ((ret & (LCA_TRACI)) != 0) {
1249 if (isOpposite && (ret & LCA_LEFT) != 0) {
1250 // stay on the opposite side
1251 return false;
1252 }
1253 oppositeChangeByTraci = true;
1254 }
1255 if (!isOpposite && !oppositeChangeByTraci && !source->allowsChangingLeft(vehicle->getVClass())) {
1256 // lane changing explicitly forbidden from this lane
1257#ifdef DEBUG_CHANGE_OPPOSITE
1258 if (DEBUG_COND) {
1259 std::cout << " not overtaking due to changeLeft restriction\n";
1260 }
1261#endif
1262 return false;
1263 }
1264
1265 //lane for opposite driving is not permitted
1266 if (!opposite->allowsVehicleClass(vehicle->getVClass())) {
1267 return false;
1268 }
1269
1270 const MSLane* oncomingLane = isOpposite ? source : opposite;
1271 //const MSLane* forwardLane = isOpposite ? opposite : source;
1272 // changing into the opposite direction is always to the left (XXX except for left-hand networkds)
1273 int direction = isOpposite ? -1 : 1;
1274 std::pair<MSVehicle*, double> neighLead(nullptr, -1);
1275
1276 // distance that can safely be driven on the opposite side
1277 double surplusGap = std::numeric_limits<double>::max();
1278
1279 // we need to find two vehicles:
1280 // 1) the leader that shall be overtaken (not necessarily the current leader but one of its leaders that has enough space in front)
1281 // 2) the oncoming vehicle (we need to look past vehicles that are currently overtaking through the opposite direction themselves)
1282 //
1283 // if the vehicle is driving normally, then the search for 1) starts on the current lane and 2) on the opposite lane
1284 // if the vehicle is driving on the opposite side then 1) is found on the neighboring lane and 2) on the current lane
1285
1286 std::pair<MSVehicle*, double> overtaken(nullptr, -1);
1287 // oncoming vehicle that is driving in the "correct" direction
1288 std::pair<MSVehicle*, double> oncoming(nullptr, -1);
1289 // oncoming vehicle that is driving against the flow
1290 std::pair<MSVehicle*, double> oncomingOpposite(nullptr, -1);
1291 // the maximum speed while overtaking (may be lowered if slow vehicles are
1292 // currently overtaking ahead of vehicle)
1293 double vMax = vehicle->getLane()->getVehicleMaxSpeed(vehicle);
1294 double oncomingSpeed = oncomingLane->getSpeedLimit();
1295 const bool isEmergency = vehicle->getVClass() == SVC_EMERGENCY;
1296
1297 // check for opposite direction stop
1298 if (!oppositeChangeByTraci && hasOppositeStop(vehicle)) {
1299 return checkOppositeStop(vehicle, oncomingLane, opposite, leader);
1300 }
1301
1302 if (!isOpposite && leader.first == nullptr && !oppositeChangeByTraci) {
1303 // no reason to change unless there is a leader
1304 // or we are changing back to the propper direction
1305 // XXX also check whether the leader is so far away as to be irrelevant
1306 return false;
1307 }
1308 if (!isOpposite && !oppositeChangeByTraci
1309 && !isEmergency
1310 && leader.first != nullptr) {
1311 if (leader.first->signalSet(MSGlobals::gLefthand
1313 // do not try to overtake a vehicle that is about to turn left or wants
1314 // to change left itself
1315#ifdef DEBUG_CHANGE_OPPOSITE
1316 if (DEBUG_COND) {
1317 std::cout << " not overtaking leader " << leader.first->getID() << " that has blinker set\n";
1318 }
1319#endif
1320 if (lastStopped != nullptr && vehicle->getWaitingSeconds() >= OPPOSITE_OVERTAKING_DEADLOCK_WAIT) {
1322 const double lastStoppedGap = lastStopped->getBackPositionOnLane() - vehicle->getPositionOnLane() - vehicle->getVehicleType().getMinGap();
1323 resolveDeadlock(vehicle, leader, neighLead, std::make_pair(lastStopped, lastStoppedGap));
1324 }
1325 return false;
1326 } else if (leader.second < 0) {
1327 // leaders is either a junction leader (that cannot be overtaken) or something else is wrong
1328#ifdef DEBUG_CHANGE_OPPOSITE
1329 if (DEBUG_COND) {
1330 std::cout << " not overtaking leader " << leader.first->getID() << " with gap " << leader.second << "\n";
1331 }
1332#endif
1333 return false;
1334 }
1335 }
1336
1337 // checks for overtaking space
1338 double timeToOvertake = std::numeric_limits<double>::max();
1339 double spaceToOvertake = std::numeric_limits<double>::max();
1340 double maxSpaceToOvertake = 0;
1341
1342 if (oppositeChangeByTraci) {
1343 timeToOvertake = STEPS2TIME(vehicle->getInfluencer().getLaneTimeLineDuration());//todo discuss concept
1344 spaceToOvertake = timeToOvertake * vehicle->getLane()->getVehicleMaxSpeed(vehicle);
1345 } else {
1346 if (isOpposite) {
1347 // -1 will use getMaximumBrakeDist() as look-ahead distance
1348 neighLead = opposite->getOppositeLeader(vehicle, -1, false);
1349 // make sure that overlapping vehicles on the neighboring lane are found by starting search at the back position
1350 overtaken = opposite->getLeader(vehicle, opposite->getOppositePos(vehicle->getBackPositionOnLane()), vehicle->getBestLanesContinuation(opposite));
1351 overtaken.second -= vehicle->getVehicleType().getLength();
1352 if (overtaken.first == nullptr && neighLead.first != nullptr) {
1353 overtaken = neighLead;
1354 }
1355 if (overtaken.first != nullptr) {
1356 overtaken = getColumnleader(maxSpaceToOvertake, vehicle, overtaken);
1357 }
1358#ifdef DEBUG_CHANGE_OPPOSITE
1359 if (DEBUG_COND) {
1360 std::cout << " leaderOnSource=" << Named::getIDSecure(oncoming.first) << " gap=" << oncoming.second << "\n";
1361 std::cout << " leaderOnTarget=" << Named::getIDSecure(neighLead.first) << " gap=" << neighLead.second << "\n";
1362 std::cout << " overtaken=" << Named::getIDSecure(overtaken.first) << " gap=" << overtaken.second << "\n";
1363 }
1364#endif
1365 } else {
1366 overtaken = getColumnleader(maxSpaceToOvertake, vehicle, leader);
1367 }
1368
1369 if (overtaken.first == 0) {
1370 if (!isOpposite) {
1371 // no reason to change to the opposite side
1372#ifdef DEBUG_CHANGE_OPPOSITE
1373 if (DEBUG_COND) {
1374 std::cout << " no leader found\n";
1375 }
1376#endif
1379 resolveDeadlock(vehicle, leader, neighLead, std::make_pair(nullptr, leader.second));
1380 }
1381 return false;
1382 }
1383 } else {
1384#ifdef DEBUG_CHANGE_OPPOSITE
1385 if (DEBUG_COND) {
1386 std::cout << " compute time/space to overtake for columnLeader=" << overtaken.first->getID() << " egoGap=" << overtaken.second << "\n";
1387 }
1388#endif
1389 // if we have limited space to overtake, we may have to limit our maximum maneuver speed
1390 vMax = MIN2(vMax, getMaxOvertakingSpeed(vehicle, maxSpaceToOvertake));
1391 // there might be leader vehicles on the opposite side that also drive
1392 // against the flow which are slower than ego (must be factored into
1393 // overtaking time)
1394 computeOvertakingTime(vehicle, vMax, overtaken.first, overtaken.second, timeToOvertake, spaceToOvertake);
1395#ifdef DEBUG_CHANGE_OPPOSITE
1396 if (DEBUG_COND) {
1397 std::cout << SIMTIME
1398 << " veh=" << vehicle->getID()
1399 << " changeOpposite opposite=" << opposite->getID()
1400 << " lead=" << Named::getIDSecure(leader.first)
1401 << " maxSpaceToOvertake=" << maxSpaceToOvertake
1402 << " vMax=" << vMax
1403 << " timeToOvertake=" << timeToOvertake
1404 << " spaceToOvertake=" << spaceToOvertake
1405 << "\n";
1406 }
1407#endif
1408
1409 if (!isOpposite && spaceToOvertake > OPPOSITE_OVERTAKING_MAX_SPACE_TO_OVERTAKE) {
1410#ifdef DEBUG_CHANGE_OPPOSITE
1411 if (DEBUG_COND) {
1412 std::cout << " cannot changeOpposite (cannot overtake fast leader " << Named::getIDSecure(overtaken.first) << " v=" << overtaken.first->getSpeed() << ")\n";
1413 }
1414#endif
1416 bool wait = false;
1418 wait = resolveDeadlock(vehicle, leader, neighLead, overtaken);
1419 }
1420 if (!wait && lastStopped != nullptr) {
1421 const double lastStoppedGap = lastStopped->getBackPositionOnLane() - vehicle->getPositionOnLane() - vehicle->getVehicleType().getMinGap();
1422#ifdef DEBUG_CHANGE_OPPOSITE
1423 if (DEBUG_COND) {
1424 std::cout << " lastStopped=" << Named::getIDSecure(lastStopped) << " gap=" << lastStoppedGap << "\n";
1425 }
1426#endif
1427 avoidDeadlock(vehicle, neighLead, std::make_pair(lastStopped, lastStoppedGap), leader);
1428 }
1429 return false;
1430 }
1431 }
1432
1433 // if we have a leader vehicle that is driving in the opposite
1434 // direction, it may slow us down (update vMax)
1435 if (!isOpposite) {
1436 assert(timeToOvertake != std::numeric_limits<double>::max());
1437 assert(spaceToOvertake != std::numeric_limits<double>::max());
1438 // we keep neighLead distinct from oncoming because it determines blocking on the neigh lane
1439 // but also look for an oncoming leader to compute safety constraint
1440 double searchDist = timeToOvertake * oncomingLane->getSpeedLimit() * 2 + spaceToOvertake;
1441 neighLead = oncomingLane->getOppositeLeader(vehicle, searchDist, true, MSLane::MinorLinkMode::FOLLOW_ONCOMING);
1442 oncoming = getOncomingVehicle(oncomingLane, neighLead, searchDist, vMax, overtaken.first, MSLane::MinorLinkMode::FOLLOW_ONCOMING);
1443 oncomingOpposite = getOncomingOppositeVehicle(vehicle, overtaken, searchDist);
1444 } else {
1445 double searchDist = OPPOSITE_OVERTAKING_ONCOMING_LOOKAHEAD;
1446 oncoming = oncomingLane->getOppositeLeader(vehicle, searchDist, true);
1447 oncoming = getOncomingVehicle(oncomingLane, oncoming, searchDist, vMax, overtaken.first);
1448 oncomingOpposite = getOncomingOppositeVehicle(vehicle, overtaken, searchDist);
1449 }
1450 if (oncoming.first != nullptr && (oncoming.first->isStopped()
1451 || oncoming.first->getWaitingSeconds() >= OPPOSITE_OVERTAKING_DEADLOCK_WAIT)) {
1452 // finish overtaking within the available space
1453 const double oncomingGap = oncoming.second - oncoming.first->getVehicleType().getMinGap();
1454 if (oncomingGap > 0) {
1455 vMax = MIN2(vMax, getMaxOvertakingSpeed(vehicle, oncomingGap));
1456 }
1457#ifdef DEBUG_CHANGE_OPPOSITE
1458 if (DEBUG_COND) {
1459 std::cout << " oncoming=" << oncoming.first->getID() << " stopped=" << oncoming.first->isStopped()
1460 << " halting=" << oncoming.first->getWaitingSeconds()
1461 << " oncomingGap=" << oncomingGap
1462 << " vMaxGap=" << getMaxOvertakingSpeed(vehicle, oncomingGap)
1463 << " vMax=" << vMax << "\n";
1464 }
1465#endif
1466 }
1467
1468 if (overtaken.first != nullptr && vMax != vehicle->getLane()->getVehicleMaxSpeed(vehicle)) {
1469 // recompute overtaking time with slow opposite leader
1470 computeOvertakingTime(vehicle, vMax, overtaken.first, overtaken.second, timeToOvertake, spaceToOvertake);
1471#ifdef DEBUG_CHANGE_OPPOSITE
1472 if (DEBUG_COND) {
1473 std::cout << " recomputed overtaking time with vMax=" << vMax
1474 << " timeToOvertake=" << timeToOvertake
1475 << " spaceToOvertake=" << spaceToOvertake
1476 << "\n";
1477 }
1478#endif
1479 }
1480 if (!isOpposite) {
1481 if (spaceToOvertake > OPPOSITE_OVERTAKING_MAX_SPACE_TO_OVERTAKE) {
1482#ifdef DEBUG_CHANGE_OPPOSITE
1483 if (DEBUG_COND) {
1484 std::cout << " cannot changeOpposite (check2: cannot overtake fast leader " << Named::getIDSecure(overtaken.first) << " v=" << overtaken.first->getSpeed() << ")\n";
1485 }
1486#endif
1487 resolveDeadlock(vehicle, leader, neighLead, overtaken);
1488 return false;
1489 }
1490 // check for upcoming stops
1491 if (vehicle->nextStopDist() < spaceToOvertake) {
1492#ifdef DEBUG_CHANGE_OPPOSITE
1493 if (DEBUG_COND) {
1494 std::cout << " cannot changeOpposite due to upcoming stop (dist=" << vehicle->nextStopDist() << " spaceToOvertake=" << spaceToOvertake << ")\n";
1495 }
1496#endif
1497 return false;
1498 }
1499 assert(timeToOvertake != std::numeric_limits<double>::max());
1500 assert(spaceToOvertake != std::numeric_limits<double>::max());
1501 }
1502
1503 // check for dangerous oncoming leader
1504 surplusGap = computeSurplusGap(vehicle, opposite, oncoming, timeToOvertake, spaceToOvertake, oncomingSpeed);
1505 if (oncomingOpposite.first != nullptr) {
1506 double oncomingSpeed2;
1507 const double conservativeTime = ceil(timeToOvertake / TS) * TS;
1508 const double conservativeSpace = conservativeTime * vehicle->getLane()->getVehicleMaxSpeed(vehicle);
1509 const double surplusGap2 = computeSurplusGap(vehicle, opposite, oncomingOpposite, conservativeTime, conservativeSpace, oncomingSpeed2, true);
1510#ifdef DEBUG_CHANGE_OPPOSITE
1511 if (DEBUG_COND) {
1512 std::cout << " oncomingOpposite=" << oncomingOpposite.first->getID() << " speed=" << oncomingSpeed2 << " gap=" << oncomingOpposite.second << " surplusGap2=" << surplusGap2 << "\n";
1513 }
1514#endif
1515 surplusGap = MIN2(surplusGap, surplusGap2);
1516 oncomingSpeed = MAX2(oncomingSpeed, oncomingSpeed2);
1517 if (!isOpposite && surplusGap >= 0 && oncoming.first != nullptr && oncoming.first->isStopped()
1518 && oncomingOpposite.second > oncoming.second) {
1519 // even if ego can change back and forth successfully, we have to
1520 // make sure that the oncoming vehicle can also finish its lane
1521 // change in time
1522 const double oSpeed = MAX2(oncomingOpposite.first->getSpeed(), NUMERICAL_EPS);
1523 // conservative estimate
1524 const double closingSpeed = (vehicle->getLane()->getVehicleMaxSpeed(vehicle)
1525 + oncomingOpposite.first->getLane()->getVehicleMaxSpeed(oncomingOpposite.first));
1526 const double ooSTO = oncomingOpposite.second - oncoming.second + oncomingOpposite.first->getVehicleType().getLengthWithGap();
1527 double ooTTO = ooSTO / oSpeed;
1528 // round to multiples of step length (TS)
1529 ooTTO = ceil(ooTTO / TS) * TS;
1530 const double surplusGap3 = oncomingOpposite.second - ooTTO * closingSpeed;
1531#ifdef DEBUG_CHANGE_OPPOSITE
1532 if (DEBUG_COND) {
1533 std::cout << " oSpeed=" << oSpeed << " ooSTO=" << ooSTO << " ooTTO=" << ooTTO << " surplusGap3=" << surplusGap3 << "\n";
1534 }
1535#endif
1536 surplusGap = MIN2(surplusGap, surplusGap3);
1537 }
1538 }
1539 if (!isOpposite && surplusGap < 0) {
1540#ifdef DEBUG_CHANGE_OPPOSITE
1541 if (DEBUG_COND) {
1542 std::cout << " cannot changeOpposite due to dangerous oncoming (surplusGap=" << surplusGap << ")\n";
1543 }
1544#endif
1545
1546#ifdef DEBUG_CHANGE_OPPOSITE
1547 if (DEBUG_COND) {
1548 if (oncoming.first->getLaneChangeModel().isOpposite()) {
1549 std::cout << SIMTIME << " ego=" << vehicle->getID() << " does not changeOpposite due to dangerous oncoming " << oncoming.first->getID() << " (but the leader is also opposite)\n";
1550 }
1551 }
1552#endif
1553 avoidDeadlock(vehicle, neighLead, overtaken, leader);
1554 return false;
1555 }
1556 }
1557 // compute remaining space on the opposite side
1558 // 1. the part that remains on the current lane
1559 double usableDist = isOpposite ? vehicle->getPositionOnLane() : source->getLength() - vehicle->getPositionOnLane();
1560
1561 if (usableDist < spaceToOvertake) {
1562 // look forward along the next lanes
1563 const std::vector<MSLane*>& bestLaneConts = vehicle->getBestLanesContinuation();
1564 assert(bestLaneConts.size() >= 1);
1565 std::vector<MSLane*>::const_iterator it = bestLaneConts.begin() + 1;
1566 while (usableDist < spaceToOvertake && it != bestLaneConts.end()) {
1567#ifdef DEBUG_CHANGE_OPPOSITE
1568 if (DEBUG_COND) {
1569 std::cout << " usableDist=" << usableDist << " opposite=" << Named::getIDSecure((*it)->getOpposite()) << "\n";
1570 }
1571#endif
1572 const MSLane* oppLane = (*it)->getOpposite();
1573 if ((oppLane == nullptr && !isEmergency) || (oppLane != nullptr && !oppLane->allowsVehicleClass(vehicle->getVClass()))) {
1574 // opposite lane ends
1575 break;
1576 }
1577 // do not overtake past a minor link or turn
1578 const MSLane* const prev = *(it - 1);
1579 if (prev != nullptr) {
1580 const MSLink* link = prev->getLinkTo(*it);
1581 if (link == nullptr || link->getState() == LINKSTATE_ZIPPER
1582 || (link->getDirection() != LinkDirection::STRAIGHT && !isEmergency)
1583 || (!link->havePriority()
1584 // consider traci-influence
1585 && (!vehicle->hasInfluencer() || vehicle->getInfluencer().getRespectJunctionPriority())
1586 // consider junction model parameters
1587 && ((!link->haveRed() && !link->haveYellow()) || !vehicle->ignoreRed(link, true)))) {
1588#ifdef DEBUG_CHANGE_OPPOSITE
1589 if (DEBUG_COND) {
1590 std::cout << " stop lookahead at link=" << (link == 0 ? "NULL" : link->getViaLaneOrLane()->getID()) << " state=" << (link == 0 ? "?" : toString(link->getState())) << " ignoreRed=" << vehicle->ignoreRed(link, true) << "\n";
1591 }
1592#endif
1593 break;
1594 }
1595 }
1596 usableDist += (*it)->getLength();
1597 ++it;
1598 }
1599 }
1600 if (!isOpposite && usableDist < spaceToOvertake) {
1601#ifdef DEBUG_CHANGE_OPPOSITE
1602 if (DEBUG_COND) {
1603 std::cout << " cannot changeOpposite due to insufficient space (seen=" << usableDist << " spaceToOvertake=" << spaceToOvertake << ")\n";
1604 }
1605#endif
1606 return false;
1607 }
1608 if (!isOpposite && MSNet::getInstance()->hasElevation() && !overtaken.first->isStopped()) {
1609 // do not overtake before the top of a hill
1610 double searchDist = timeToOvertake * oncomingLane->getSpeedLimit() * 1.5 * vehicle->getLaneChangeModel().getOppositeSafetyFactor() + spaceToOvertake;
1611 int view = vehicle->getLane()->isInternal() ? 1 : 0;
1612 bool foundHill = vehicle->getSlope() > 0;
1613 if (foundHilltop(vehicle, foundHill, searchDist, vehicle->getBestLanesContinuation(), view, vehicle->getPositionOnLane(), vehicle->getPosition().z(), OPPOSITE_OVERTAKING_HILLTOP_THRESHOHOLD)) {
1614 return false;
1615 }
1616 }
1617#ifdef DEBUG_CHANGE_OPPOSITE
1618 if (DEBUG_COND) {
1619 std::cout << " usableDist=" << usableDist << " spaceToOvertake=" << spaceToOvertake << " timeToOvertake=" << timeToOvertake << "\n";
1620 }
1621#endif
1622 // compute wish to change
1623 std::pair<MSVehicle* const, double> neighFollow = opposite->getOppositeFollower(vehicle);
1624 double oppositeLength = vehicle->getBestLanes().back().length;
1625 if (isOpposite) {
1626 const bool canOvertake = spaceToOvertake <= OPPOSITE_OVERTAKING_MAX_SPACE_TO_OVERTAKE;
1627 oppositeLength = computeSafeOppositeLength(vehicle, oppositeLength, source, usableDist, oncoming, vMax, oncomingSpeed, neighLead, overtaken, neighFollow, surplusGap, opposite, canOvertake);
1628 leader.first = nullptr;
1629 if (neighLead.first != nullptr && neighLead.first->getLaneChangeModel().isOpposite()) {
1630 // ignore oncoming vehicle on the target lane (it might even change back in this step)
1631 neighLead.first = nullptr;
1632 }
1633 } else {
1634 if (leader.first != nullptr && neighLead.first != nullptr && leader.first->getWaitingSeconds() >= OPPOSITE_OVERTAKING_DEADLOCK_WAIT && !isEmergency) {
1635#ifdef DEBUG_CHANGE_OPPOSITE
1636 if (DEBUG_COND) {
1637 std::cout << " not changing to avoid deadlock\n";
1638 }
1639#endif
1640 return false;
1641 }
1642 if (neighLead.first != nullptr && neighLead.first->isStopped()) {
1643 // do not start overtaking if the opposite side has been waitin for longer
1644 if (yieldToOppositeWaiting(vehicle, neighLead.first, 10)) {
1645 return false;
1646 }
1647 }
1648 if (oncoming.first != nullptr && oncoming.first != neighLead.first && oncoming.first->isStopped()) {
1649 // only abort the current column of overtaking vehicles if the opposite side has been waiting long enough
1650 if (yieldToOppositeWaiting(vehicle, oncoming.first, 10, TIME2STEPS(60))) {
1651 return false;
1652 }
1653 }
1654 }
1655 std::vector<MSVehicle::LaneQ> preb = getBestLanesOpposite(vehicle, nullptr, oppositeLength);
1656 return checkChangeOpposite(vehicle, direction, opposite, leader, neighLead, neighFollow, preb);
1657}
1658
1659
1660bool
1662 std::pair<MSVehicle*, double> neighLead,
1663 std::pair<MSVehicle*, double> overtaken,
1664 std::pair<MSVehicle*, double> leader) {
1665 assert(!vehicle->getLaneChangeModel().isOpposite());
1666#ifdef DEBUG_CHANGE_OPPOSITE_DEADLOCK
1667 if (DEBUG_COND) {
1668 std::cout << SIMTIME << " veh=" << vehicle->getID() << " avoidDeadlock"
1669 << " neighLead=" << Named::getIDSecure(neighLead.first)
1670 << " overtaken=" << Named::getIDSecure(overtaken.first)
1671 << " leader=" << Named::getIDSecure(leader.first)
1672 << "\n";
1673 }
1674#endif
1675 if (leader.first == nullptr || neighLead.first == nullptr || overtaken.first == nullptr) {
1676 return false;
1677 } else if (!neighLead.first->isStopped()
1679 // possibly there is an oncoming vehicle before the stoppled leader that
1680 // could drive due to our yielding
1681 auto neighLeadFollow = neighLead.first->getFollower(overtaken.second);
1682 neighLead.second += neighLead.first->getVehicleType().getLengthWithGap() + neighLeadFollow.second;
1683 neighLead.first = const_cast<MSVehicle*>(neighLeadFollow.first);
1684#ifdef DEBUG_CHANGE_OPPOSITE_DEADLOCK
1685 if (DEBUG_COND) {
1686 std::cout << " neighLead follower=" << Named::getIDSecure(neighLeadFollow.first) << "\n";
1687 }
1688#endif
1689 if (neighLead.first == nullptr) {
1690 return false;
1691 }
1692 }
1693
1694 const bool yield = (yieldToDeadlockOncoming(vehicle, neighLead.first, overtaken.second)
1695 || leader.first->getWaitingSeconds() >= OPPOSITE_OVERTAKING_DEADLOCK_WAIT);
1696 if (neighLead.first->isStopped()
1697 && (overtaken.first->isStopped()
1698 || leader.first->getLaneChangeModel().isOpposite()
1699 || yield)) {
1700
1701 // estimate required gap
1702 double requiredGap = MAX2(vehicle->getVehicleType().getLengthWithGap(), neighLead.first->getVehicleType().getLengthWithGap());
1703 requiredGap = MAX2(requiredGap, overtaken.first->getVehicleType().getLengthWithGap());
1704 requiredGap = MAX2(requiredGap, leader.first->getVehicleType().getLengthWithGap());
1705 requiredGap += 1;
1706 const double distToStop = neighLead.second - requiredGap;
1707
1708 // find the next non-stopped vehicle behind neighLead
1709 double neighStoppedBack = vehicle->getVehicleType().getMinGap();
1710 while (neighLead.first != nullptr && neighLead.first->isStopped()) {
1711 const double nextGap = neighLead.second + neighLead.first->getVehicleType().getLengthWithGap();
1712 if (neighStoppedBack + nextGap > overtaken.second) {
1713 break;
1714 }
1715 neighStoppedBack += nextGap;
1716 auto neighLeadFollow = neighLead.first->getFollower();
1717 neighLead.second = neighLeadFollow.second;
1718 neighLead.first = const_cast<MSVehicle*>(neighLeadFollow.first);
1719#ifdef DEBUG_CHANGE_OPPOSITE_DEADLOCK
1720 if (DEBUG_COND) {
1721 std::cout << " neighLeadFollower=" << Named::getIDSecure(neighLead.first) << "\n";
1722 }
1723#endif
1724 if (neighStoppedBack > overtaken.second) {
1725 break;
1726 }
1727 }
1728
1729 const double leaderBGap = leader.first->getBrakeGap();
1730 const double leaderFGap = leader.first->getLane()->getLeader(leader.first, leader.first->getPositionOnLane(), vehicle->getBestLanesContinuation(), overtaken.second, true).second;
1731 const double extraGap = MAX2(leaderBGap, leaderFGap);
1732 const double gapWithEgo = leader.second + extraGap - neighStoppedBack - vehicle->getVehicleType().getLengthWithGap();
1733#ifdef DEBUG_CHANGE_OPPOSITE_DEADLOCK
1734 if (DEBUG_COND) {
1735 std::cout << SIMTIME << " veh=" << vehicle->getID() << " avoidDeadlock"
1736 << " neighLeadGap=" << neighLead.second
1737 << " leaderGap=" << leader.second
1738 << " bGap=" << leaderBGap
1739 << " fGap=" << leaderFGap
1740 << " eGap=" << extraGap
1741 << " neighStoppedBack=" << neighStoppedBack
1742 << " neighStoppedBackPos=" << vehicle->getPositionOnLane() + neighStoppedBack
1743 << " requiredGap=" << requiredGap
1744 << " gapWithEgo=" << gapWithEgo
1745 << " yield=" << yield
1746 << "\n";
1747 }
1748#endif
1749 // vehicle must fit behind leader and still leave required gap
1750 if (leader.first->getLaneChangeModel().isOpposite() || yield || gapWithEgo < requiredGap) {
1751 const std::vector<MSVehicle::LaneQ>& preb = vehicle->getBestLanes();
1752 const double currentDist = preb[vehicle->getLane()->getIndex()].length;
1753 const double stopPos = vehicle->getPositionOnLane() + distToStop;
1754#ifdef DEBUG_CHANGE_OPPOSITE_DEADLOCK
1755 if (DEBUG_COND) {
1756 std::cout << " currentDist=" << currentDist << " stopPos=" << stopPos << " lGap+eGap=" << leader.second + extraGap << " distToStop=" << distToStop << "\n";
1757 }
1758#endif
1759 if (leader.second + leaderBGap + leader.first->getLength() > distToStop) {
1760 const double blockerLength = currentDist - stopPos;
1761 const bool reserved = vehicle->getLaneChangeModel().saveBlockerLength(blockerLength, -1);
1762#ifdef DEBUG_CHANGE_OPPOSITE_DEADLOCK
1763 if (DEBUG_COND) {
1764 std::cout << SIMTIME << " veh=" << vehicle->getID() << " avoidDeadlock"
1765 << " blockerLength=" << blockerLength
1766 << " reserved=" << reserved
1767 << "\n";
1768 }
1769#endif
1770 return reserved;
1771 }
1772 }
1773 }
1774 return false;
1775}
1776
1777
1778bool
1779MSLaneChanger::yieldToDeadlockOncoming(const MSVehicle* vehicle, const MSVehicle* stoppedNeigh, double dist) {
1780 if (vehicle->getWaitingSeconds() >= OPPOSITE_OVERTAKING_DEADLOCK_WAIT && stoppedNeigh != nullptr) {
1781 // is there a vehicle waiting behind stoppedNeigh that is encouraged by
1782 // halting ego? Due to edge-ordering it might change-opposite this step
1783 // and not be visible as leader
1784 std::pair<const MSVehicle*, double> follower = stoppedNeigh->getFollower(dist);
1785 double followerGap = stoppedNeigh->getVehicleType().getLengthWithGap();
1786 while (follower.first != nullptr && followerGap < dist && follower.first->isStopped()) {
1787 followerGap += follower.second + follower.first->getVehicleType().getLengthWithGap();
1788 follower = follower.first->getFollower(dist);
1789 };
1790 if (follower.first != nullptr) {
1791 followerGap += follower.second;
1792 }
1793#ifdef DEBUG_CHANGE_OPPOSITE_DEADLOCK
1794 if (DEBUG_COND) {
1795 std::cout << SIMTIME << " veh=" << vehicle->getID() << " yieldToDeadlockOncoming"
1796 << " dist=" << dist << " follower=" << Named::getIDSecure(follower.first) << " fGap=" << followerGap
1797 << "\n";
1798 }
1799#endif
1800 return follower.first != nullptr && followerGap < dist && !follower.first->isStopped();
1801 }
1802 return false;
1803}
1804
1805
1806bool
1807MSLaneChanger::yieldToOppositeWaiting(const MSVehicle* vehicle, const MSVehicle* stoppedNeigh, double dist, SUMOTime deltaWait) {
1808 std::pair<const MSVehicle*, double> follower = stoppedNeigh->getFollower(dist);
1809 while (follower.first != nullptr && follower.second < dist && follower.first->isStopped()) {
1810 follower = follower.first->getFollower(dist);
1811 };
1812#ifdef DEBUG_CHANGE_OPPOSITE_DEADLOCK
1813 if (DEBUG_COND && follower.first != nullptr) {
1814 std::cout << SIMTIME << " yieldToOppositeWaiting veh=" << vehicle->getID() << " stoppedNeigh=" << stoppedNeigh->getID()
1815 << " oncoming=" << follower.first->getID()
1816 << " wait=" << follower.first->getWaitingSeconds()
1817 << " vehWait=" << vehicle->getWaitingSeconds()
1818 << " deltaWait=" << STEPS2TIME(deltaWait)
1819 << "\n";
1820 }
1821#endif
1822 if (follower.first != nullptr && follower.second < dist && follower.first->getWaitingTime() > vehicle->getWaitingTime() + deltaWait) {
1823 return true;
1824 }
1825 return false;
1826}
1827
1828
1829bool
1831 std::pair<MSVehicle* const, double> leader,
1832 std::pair<MSVehicle*, double> neighLead,
1833 std::pair<MSVehicle*, double> overtaken) {
1834 const double deadLockZone = overtaken.second;
1835#ifdef DEBUG_CHANGE_OPPOSITE_DEADLOCK
1836 if (DEBUG_COND) {
1837 std::cout << SIMTIME << " veh=" << vehicle->getID() << " resolveDeadlock waiting=" << vehicle->getWaitingSeconds()
1838 << " leader=" << Named::getIDSecure(leader.first)
1839 << " gap=" << leader.second
1840 << "\n";
1841 }
1842#endif
1844 && leader.first != nullptr && leader.second > vehicle->getVehicleType().getLengthWithGap()) {
1845 // assume vehicle is halting to avoid deadlock (since there is enough
1846 // space to drive further)
1847 // keep halting as long as there is an oncoming vehicle
1848 std::pair<MSVehicle* const, double> oncomingOpposite = getOncomingOppositeVehicle(vehicle, std::make_pair(nullptr, -1), leader.second);
1849#ifdef DEBUG_CHANGE_OPPOSITE_DEADLOCK
1850 if (DEBUG_COND) {
1851 std::cout << SIMTIME << " veh=" << vehicle->getID() << " resolveDeadlock"
1852 << " leader=" << leader.first->getID()
1853 << " leaderGap=" << leader.second
1854 << " neighLead=" << Named::getIDSecure(neighLead.first)
1855 << " deadLockZone=" << deadLockZone
1856 << "\n";
1857 }
1858#endif
1859 if (neighLead.first != nullptr && !neighLead.first->isStopped()) {
1860 // possibly there is an oncoming vehicle before the stoppled leader that
1861 // could drive due to our yielding
1862 auto neighLeadFollow = neighLead.first->getFollower(deadLockZone);
1863 neighLead.second += neighLead.first->getVehicleType().getLengthWithGap() + neighLeadFollow.second;
1864 neighLead.first = const_cast<MSVehicle*>(neighLeadFollow.first);
1865#ifdef DEBUG_CHANGE_OPPOSITE_DEADLOCK
1866 if (DEBUG_COND) {
1867 std::cout << " neighLead follower=" << Named::getIDSecure(neighLeadFollow.first) << "\n";
1868 }
1869#endif
1870 }
1871
1872 if (oncomingOpposite.first != nullptr ||
1873 (neighLead.first != nullptr && neighLead.first->isStopped()
1874 && yieldToDeadlockOncoming(vehicle, neighLead.first, deadLockZone))) {
1875 const std::vector<MSVehicle::LaneQ>& preb = vehicle->getBestLanes();
1876 const double currentDist = preb[vehicle->getLane()->getIndex()].length;
1877 // mirror code in patchSpeed
1878 const double blockerLength = currentDist - vehicle->getPositionOnLane() - 1 - vehicle->getVehicleType().getMinGap() - NUMERICAL_EPS;
1879 const bool reserved = vehicle->getLaneChangeModel().saveBlockerLength(blockerLength, -1);
1880#ifdef DEBUG_CHANGE_OPPOSITE_DEADLOCK
1881 if (DEBUG_COND) {
1882 std::cout << SIMTIME << " veh=" << vehicle->getID() << " resolveDeadlock"
1883 << " leader=" << leader.first->getID()
1884 << " leaderGap=" << leader.second
1885 << " oncoming=" << Named::getIDSecure(oncomingOpposite.first)
1886 << " currentDist=" << currentDist
1887 << " blockerLength=" << blockerLength
1888 << " reserved=" << reserved
1889 << "\n";
1890 }
1891#else
1892 UNUSED_PARAMETER(reserved);
1893#endif
1894 return true;
1895 }
1896 }
1897 return false;
1898}
1899
1900
1901double
1902MSLaneChanger::computeSafeOppositeLength(MSVehicle* vehicle, double oppositeLength, const MSLane* source, double usableDist,
1903 std::pair<MSVehicle*, double> oncoming, double vMax, double oncomingSpeed,
1904 std::pair<MSVehicle*, double> neighLead,
1905 std::pair<MSVehicle*, double> overtaken,
1906 std::pair<MSVehicle*, double> neighFollow,
1907 double surplusGap, const MSLane* opposite,
1908 bool canOvertake) {
1909 // compute the remaining distance that can be driven on the opposite side
1910 // this value will put into oppositeLength of the opposite lanes
1911 // @note: length counts from the start of the current lane
1912 // @note: see MSLaneChangeModel::LC2013::_wantsChange @1092 (isOpposite()
1913 // position on the target lane
1914 const double forwardPos = source->getOppositePos(vehicle->getPositionOnLane());
1915
1916 // consider usableDist (due to minor links or end of opposite lanes)
1917 oppositeLength = MIN2(oppositeLength, usableDist + forwardPos);
1918 // consider upcoming stops
1919 oppositeLength = MIN2(oppositeLength, vehicle->nextStopDist() + forwardPos);
1920#ifdef DEBUG_CHANGE_OPPOSITE
1921 if (DEBUG_COND) {
1922 std::cout << " laneQLength=" << oppositeLength << " usableDist=" << usableDist << " forwardPos=" << forwardPos << " stopDist=" << vehicle->nextStopDist() << "\n";
1923 }
1924#endif
1925 // consider oncoming leaders
1926 const MSVehicle* oncomingVeh = oncoming.first;
1927 if (oncomingVeh != 0) {
1928 if (!oncomingVeh->getLaneChangeModel().isOpposite() && oncomingVeh->getLaneChangeModel().getShadowLane() != source) {
1929 double egoSpeedFraction = 0.5;
1930 if (oncomingSpeed > 0) {
1931 egoSpeedFraction = MIN2(egoSpeedFraction, vMax / (vMax + oncomingSpeed));
1932 }
1933 oppositeLength = MIN2(oppositeLength, forwardPos + oncoming.second * egoSpeedFraction);
1934#ifdef DEBUG_CHANGE_OPPOSITE
1935 if (DEBUG_COND) {
1936 std::cout << SIMTIME << " found oncoming leader=" << oncomingVeh->getID() << " gap=" << oncoming.second
1937 << " egoSpeedFraction=" << egoSpeedFraction << " newDist=" << oppositeLength << "\n";
1938 }
1939#endif
1940 } else {
1941#ifdef DEBUG_CHANGE_OPPOSITE
1942 if (DEBUG_COND) {
1943 std::cout << SIMTIME << " opposite leader=" << oncomingVeh->getID() << " gap=" << oncoming.second << " is driving against the flow\n";
1944 }
1945#endif
1946 }
1947 if (neighLead.first != nullptr) {
1948 if (overtaken.first == nullptr) {
1949#ifdef DEBUG_CHANGE_OPPOSITE
1950 if (DEBUG_COND) {
1951 std::cout << SIMTIME << " ego=" << vehicle->getID() << " did not find columnleader to overtake\n";
1952 }
1953#endif
1954 } else if (oncomingVeh != nullptr && oncomingVeh->isStopped()
1955 && neighLead.second > 0
1956 && neighFollow.second > 0
1957 && yieldToOppositeWaiting(vehicle, oncomingVeh, 10, TIME2STEPS(60))) {
1958 // merge back into the forward lane
1959 oppositeLength = forwardPos + neighLead.second;
1960 } else {
1961 if (surplusGap > 0) {
1962 // exaggerate remaining dist so that the vehicle continues
1963 // overtaking (otherwise the lane change model might abort prematurely)
1964 oppositeLength += 1000;
1965 } else {
1966 // return from the opposite side ahead of the unpassable column (unless overlapping)
1967 if (overtaken.second > 0) {
1968 oppositeLength = MIN2(oppositeLength, forwardPos + overtaken.second);
1969 }
1970 // (don't set the distance so low as to imply emergency braking)
1971 oppositeLength = MAX2(oppositeLength, forwardPos + vehicle->getCarFollowModel().brakeGap(vehicle->getSpeed()));
1972 }
1973#ifdef DEBUG_CHANGE_OPPOSITE
1974 if (DEBUG_COND) {
1975 std::cout << SIMTIME << " ego=" << vehicle->getID() << " is overtaking " << overtaken.first->getID()
1976 << " surplusGap=" << surplusGap
1977 << " final laneQLength=" << oppositeLength
1978 << "\n";
1979 }
1980#endif
1981 }
1982 }
1983 } else {
1984 if (overtaken.first == nullptr || !canOvertake) {
1985 // there is no reason to stay on the opposite side
1986 std::pair<MSVehicle* const, double> oppFollow = opposite->getOppositeFollower(vehicle);
1987 if (oppFollow.first == nullptr) {
1988 oppositeLength = forwardPos;
1989 } else {
1990 const double secureGap = oppFollow.first->getCarFollowModel().getSecureGap(
1991 oppFollow.first, vehicle, oppFollow.first->getSpeed(), vehicle->getSpeed(), vehicle->getCarFollowModel().getMaxDecel());
1992#ifdef DEBUG_CHANGE_OPPOSITE
1993 if (DEBUG_COND) {
1994 std::cout << SIMTIME << " ego=" << vehicle->getID() << " neighFollow=" << oppFollow.first->getID() << " gap=" << oppFollow.second << " secureGap=" << secureGap << "\n";
1995 }
1996#endif
1997 if (oppFollow.second > secureGap) {
1998 // back gap is safe for immidiate return
1999 oppositeLength = forwardPos;
2000 }
2001 }
2002 }
2003 }
2004#ifdef DEBUG_CHANGE_OPPOSITE
2005 if (DEBUG_COND) {
2006 std::cout << SIMTIME << " veh=" << vehicle->getID() << " remaining dist=" << oppositeLength - forwardPos << " forwardPos=" << forwardPos << " oppositeLength=" << oppositeLength << "\n";
2007 }
2008#endif
2009 return oppositeLength;
2010}
2011
2012
2013std::pair<MSVehicle* const, double>
2014MSLaneChanger::getOncomingVehicle(const MSLane* opposite, std::pair<MSVehicle*, double> oncoming,
2015 double searchDist, double& vMax, const MSVehicle* overtaken, MSLane::MinorLinkMode mLinkMode) {
2016 double gap = oncoming.second;
2017 while (oncoming.first != nullptr && (oncoming.first->getLaneChangeModel().isOpposite() || oncoming.first->getLaneChangeModel().getShadowLane() == opposite)) {
2018 searchDist -= (oncoming.first->getVehicleType().getLengthWithGap() + MAX2(0.0, oncoming.second));
2019 // leader is itself overtaking through the opposite side. find real oncoming vehicle
2020 gap += oncoming.first->getVehicleType().getLengthWithGap();
2021 if (oncoming.first != overtaken) {
2022 vMax = MIN2(vMax, oncoming.first->getSpeed());
2023 } // else: might be the case if we are overtaking a vehicle that is stopped on the opposite side
2024#ifdef DEBUG_CHANGE_OPPOSITE
2025 if (gDebugFlag5) {
2026 std::cout << SIMTIME << " oncoming=" << oncoming.first->getID() << " isOpposite gap=" << oncoming.second
2027 << " totalGap=" << gap << " searchDist=" << searchDist << " vMax=" << vMax << "\n";
2028 }
2029#endif
2030 if (searchDist < 0) {
2031 break;
2032 }
2033 // getOppositeLeader resets the search postion by ego length and may thus create cycles
2034 if (oncoming.first->getLaneChangeModel().getShadowLane() != opposite) {
2035 opposite = oncoming.first->getLane();
2036 }
2037 oncoming = opposite->getFollower(oncoming.first, oncoming.first->getPositionOnLane(opposite), searchDist, mLinkMode);
2038 if (oncoming.first != nullptr) {
2039 gap += oncoming.second + oncoming.first->getVehicleType().getLength();
2040#ifdef DEBUG_CHANGE_OPPOSITE
2041 if (gDebugFlag5) {
2042 std::cout << SIMTIME << " oncoming=" << oncoming.first->getID() << " gap=" << oncoming.second << " totalGap=" << gap << "\n";
2043 }
2044#endif
2045 }
2046 }
2047 oncoming.second = gap;
2048 return oncoming;
2049}
2050
2051
2052std::pair<MSVehicle* const, double>
2053MSLaneChanger::getOncomingOppositeVehicle(const MSVehicle* vehicle, std::pair<MSVehicle*, double> overtaken, double searchDist) {
2054 double gap = 0;
2055 const MSVehicle* front = nullptr;
2056 if (overtaken.first != nullptr) {
2057 gap += overtaken.second + overtaken.first->getVehicleType().getLengthWithGap();
2058 front = overtaken.first;
2059 } else {
2060 // only for special situations (i.e. traci-triggered)
2061 front = vehicle;
2062 }
2063 // we only need to look for the next leader: If it's driving in the forward
2064 // direction, it "protects" from oncoming opposite vehicles.
2065 // all leader vehicles on the current laneChanger edge are already moved into MSLane::myTmpVehicles
2066 const bool checkTmpVehicles = front->getLane() == vehicle->getLane();
2067 std::vector<MSLane*> conts = vehicle->getBestLanesContinuation();
2068 while (conts.size() > 0 && conts.front() != front->getLane()) {
2069 conts.erase(conts.begin());
2070 }
2071 std::pair<MSVehicle* const, double> oncoming = front->getLane()->getLeader(front, front->getPositionOnLane(), conts, searchDist, checkTmpVehicles);
2072 if (oncoming.first != nullptr) {
2073 const bool isOpposite = oncoming.first->getLaneChangeModel().isOpposite();
2074 const MSLane* shadowLane = oncoming.first->getLaneChangeModel().getShadowLane();
2075#ifdef DEBUG_CHANGE_OPPOSITE
2076 if (gDebugFlag5) {
2077 std::cout << SIMTIME
2078 << " front=" << front->getID() << " searchDist=" << searchDist
2079 << " oncomingOpposite=" << oncoming.first->getID()
2080 << " gap=" << oncoming.second
2081 << " isOpposite=" << isOpposite
2082 << " shadowLane=" << Named::getIDSecure(shadowLane)
2083 << "\n";
2084 }
2085#endif
2086 if (isOpposite && shadowLane != front->getLane()) {
2087 // distance was to back position (but the vehicle is oncoming)
2088 oncoming.second -= oncoming.first->getVehicleType().getLength();
2089 oncoming.second += gap;
2090 return oncoming;
2091 }
2092 }
2093 return std::make_pair(nullptr, -1);
2094}
2095
2096
2097double
2098MSLaneChanger::computeSurplusGap(const MSVehicle* vehicle, const MSLane* opposite, std::pair<MSVehicle*, double> oncoming,
2099 double timeToOvertake, double spaceToOvertake, double& oncomingSpeed, bool oncomingOpposite) {
2100 double surplusGap = std::numeric_limits<double>::max();
2101 const MSVehicle* oncomingVeh = oncoming.first;
2102 if (oncomingVeh != 0 && (oncomingOpposite
2103 || (!oncomingVeh->getLaneChangeModel().isOpposite()
2104 && oncomingVeh->getLaneChangeModel().getShadowLane() != opposite))) {
2105 // conservative: assume that the oncoming vehicle accelerates to its maximum speed
2106 // unless it has been standing (then assume it is trying to let us pass
2107 // to avoid deadlock)
2108 oncomingSpeed = (oncomingVeh->isStopped() || oncomingVeh->getWaitingSeconds() >= OPPOSITE_OVERTAKING_DEADLOCK_WAIT
2109 ? 0 : oncomingVeh->getLane()->getVehicleMaxSpeed(oncomingVeh));
2110 const double safetyGap = ((oncomingSpeed + vehicle->getLane()->getVehicleMaxSpeed(vehicle))
2111 * vehicle->getCarFollowModel().getHeadwayTime()
2113 surplusGap = oncoming.second - spaceToOvertake - timeToOvertake * oncomingSpeed - safetyGap;
2114#ifdef DEBUG_CHANGE_OPPOSITE
2115 if (DEBUG_COND) {
2116 std::cout << SIMTIME
2117 << " oncoming=" << oncomingVeh->getID()
2118 << " oGap=" << oncoming.second
2119 << " oSpeed=" << oncomingSpeed
2120 << " sto=" << spaceToOvertake
2121 << " tto=" << timeToOvertake
2122 << " safetyGap=" << safetyGap
2123 << " surplusGap=" << surplusGap
2124 << "\n";
2125 }
2126#endif
2127 }
2128 return surplusGap;
2129}
2130
2131bool
2132MSLaneChanger::foundHilltop(MSVehicle* vehicle, bool foundHill, double searchDist, const std::vector<MSLane*>& bestLanes, int view, double pos, double lastMax, double hilltopThreshold) {
2133 if (view >= (int)bestLanes.size()) {
2134 return false;
2135 }
2136 MSLane* lane = bestLanes[view];
2137 double laneDist = 0;
2138 const PositionVector& shape = lane->getShape();
2139 double lastZ = lastMax;
2140 for (int i = 1; i < (int)shape.size(); i++) {
2141 const double dist = lane->interpolateGeometryPosToLanePos(shape[i - 1].distanceTo(shape[i]));
2142 laneDist += dist;
2143 if (laneDist > pos) {
2144 const double z = shape[i].z();
2145 if (z > lastMax) {
2146 lastMax = z;
2147 }
2148 if (z > lastZ) {
2149 foundHill = true;
2150 }
2151 lastZ = z;
2152#ifdef DEBUG_CHANGE_OPPOSITE
2153 if (DEBUG_COND) {
2154 std::cout << SIMTIME << " foundHill=" << foundHill << " searchDist=" << searchDist << " lastMax=" << lastMax << " lane=" << lane->getID() << " laneDist=" << laneDist << " z=" << z << "\n";
2155 }
2156#endif
2157 if (foundHill && z < lastMax) {
2158 const double drop = lastMax - z;
2159 //std::cout << SIMTIME << " searchDist=" << searchDist << " hillDrop=" << drop << " lastMax=" << lastMax << " lane=" << lane->getID() << " laneDist=" << laneDist << " z=" << z << "\n";
2160 if (drop > hilltopThreshold) {
2161#ifdef DEBUG_CHANGE_OPPOSITE
2162 if (DEBUG_COND) {
2163 std::cout << " cannot changeOpposite before the top of a hill searchDist=" << searchDist << " hillDrop=" << drop
2164 << " lastMax=" << lastMax << " lane=" << lane->getID() << " laneDist=" << laneDist << " z=" << z << "\n";
2165 }
2166#endif
2167 return true;
2168 }
2169 }
2170 if (pos == 0) {
2171 searchDist -= dist;
2172 } else {
2173 searchDist -= laneDist - pos;
2174 pos = 0;
2175 }
2176 if (searchDist <= 0) {
2177 return false;
2178 }
2179 }
2180 }
2181 return foundHilltop(vehicle, foundHill, searchDist, bestLanes, view + 1, 0, lastMax, hilltopThreshold);
2182}
2183
2184
2185bool
2187 MSVehicle* vehicle,
2188 int laneOffset,
2189 MSLane* targetLane,
2190 const std::pair<MSVehicle* const, double>& leader,
2191 const std::pair<MSVehicle* const, double>& neighLead,
2192 const std::pair<MSVehicle* const, double>& neighFollow,
2193 const std::vector<MSVehicle::LaneQ>& preb) {
2194 const bool isOpposite = vehicle->getLaneChangeModel().isOpposite();
2195 MSLane* source = vehicle->getMutableLane();
2196 const std::pair<MSVehicle* const, double> follower(nullptr, -1);
2197 int state = checkChange(laneOffset, targetLane, leader, follower, neighLead, neighFollow, preb);
2198 vehicle->getLaneChangeModel().setOwnState(state);
2199 bool changingAllowed = (state & LCA_BLOCKED) == 0;
2200 // change if the vehicle wants to and is allowed to change
2201 if ((state & LCA_WANTS_LANECHANGE) != 0 && changingAllowed
2202 // do not change to the opposite direction for cooperative reasons
2203 && (isOpposite || (state & LCA_COOPERATIVE) == 0)) {
2204 const bool continuous = vehicle->getLaneChangeModel().startLaneChangeManeuver(source, targetLane, laneOffset);
2205#ifdef DEBUG_CHANGE_OPPOSITE
2206 if (DEBUG_COND) {
2207 std::cout << SIMTIME << " changing to opposite veh=" << vehicle->getID() << " dir=" << laneOffset << " opposite=" << Named::getIDSecure(targetLane)
2208 << " state=" << toString((LaneChangeAction)state) << "\n";
2209 }
2210#endif
2211 if (continuous) {
2212 continueChange(vehicle, myCandi);
2213 }
2214 return true;
2215 }
2216#ifdef DEBUG_CHANGE_OPPOSITE
2217 if (DEBUG_COND) {
2218 std::cout << SIMTIME << " not changing to opposite veh=" << vehicle->getID() << " dir=" << laneOffset
2219 << " opposite=" << Named::getIDSecure(targetLane) << " state=" << toString((LaneChangeAction)state) << "\n";
2220 }
2221#endif
2222 return false;
2223}
2224
2225
2226void
2227MSLaneChanger::computeOvertakingTime(const MSVehicle* vehicle, double vMax, const MSVehicle* leader, double gap, double& timeToOvertake, double& spaceToOvertake) {
2228 // Assumptions:
2229 // - leader maintains the current speed
2230 // - vehicle merges with maxSpeed ahead of leader
2231 // XXX affected by ticket #860 (the formula is invalid for the current position update rule)
2232
2233 // first compute these values for the case where vehicle is accelerating
2234 // without upper bound on speed
2235 const double v = vehicle->getSpeed();
2236 const double u = leader->getAcceleration() > 0 ? leader->getLane()->getVehicleMaxSpeed(leader) : leader->getSpeed();
2237 const double a = vehicle->getCarFollowModel().getMaxAccel();
2238 const double d = vehicle->getCarFollowModel().getMaxDecel();
2239 const double g = MAX2(0.0, (
2240 // drive up to the rear of leader
2241 gap + vehicle->getVehicleType().getMinGap()
2242 // drive head-to-head with the leader
2243 + leader->getVehicleType().getLengthWithGap()
2244 // drive past the leader
2245 + vehicle->getVehicleType().getLength()
2246 // allow for safe gap between leader and vehicle
2247 + leader->getCarFollowModel().getSecureGap(leader, vehicle, u, vMax, d))
2248 // time to move between lanes
2249 + (MSGlobals::gSublane ? vMax * vehicle->getLane()->getWidth() / vehicle->getVehicleType().getMaxSpeedLat() : 0));
2250 const double sign = -1; // XXX recheck
2251 // v*t + t*t*a*0.5 = g + u*t
2252 // solve t
2253 // t = ((u - v - (((((2.0*(u - v))**2.0) + (8.0*a*g))**(1.0/2.0))*sign/2.0))/a)
2254 double t = (u - v - sqrt(4 * (u - v) * (u - v) + 8 * a * g) * sign * 0.5) / a;
2255#ifdef DEBUG_CHANGE_OPPOSITE_OVERTAKINGTIME
2256 if (DEBUG_COND) {
2257 std::cout << " computeOvertakingTime v=" << v << " vMax=" << vMax << " u=" << u << " a=" << a << " d=" << d << " gap=" << gap << " g=" << g << " t=" << t
2258 << " distEgo=" << v* t + t* t* a * 0.5 << " distLead=" << g + u* t
2259 << "\n";
2260 }
2261#endif
2262 assert(t >= 0);
2263 if (vMax <= u) {
2264 // do not try to overtake faster leader
2265 timeToOvertake = std::numeric_limits<double>::max();
2266 spaceToOvertake = std::numeric_limits<double>::max();
2267 return;
2268 }
2269
2270 // allow for a safety time gap
2272 // round to multiples of step length (TS)
2273 if (u > 0) {
2274 t = ceil(t / TS) * TS;
2275 }
2276
2278 const double timeToMaxSpeed = (vMax - v) / a;
2279
2280#ifdef DEBUG_CHANGE_OPPOSITE_OVERTAKINGTIME
2281 if (DEBUG_COND) {
2282 std::cout << " t=" << t << " tvMax=" << timeToMaxSpeed << "\n";
2283 }
2284#endif
2285 if (t <= timeToMaxSpeed) {
2286 timeToOvertake = t;
2287 spaceToOvertake = v * t + t * t * a * 0.5;
2288#ifdef DEBUG_CHANGE_OPPOSITE_OVERTAKINGTIME
2289 if (DEBUG_COND) {
2290 std::cout << " sto=" << spaceToOvertake << "\n";
2291 }
2292#endif
2293 } else {
2294 // space until max speed is reached
2295 const double s = v * timeToMaxSpeed + timeToMaxSpeed * timeToMaxSpeed * a * 0.5;
2296 const double m = timeToMaxSpeed;
2297 // s + (t-m) * vMax = g + u*t
2298 // solve t
2299 t = (g - s + m * vMax) / (vMax - u);
2300 if (t < 0) {
2301 // cannot overtake in time
2302#ifdef DEBUG_CHANGE_OPPOSITE_OVERTAKINGTIME
2303 if (DEBUG_COND) {
2304 std::cout << " t2=" << t << "\n";
2305 }
2306#endif
2307 timeToOvertake = std::numeric_limits<double>::max();
2308 spaceToOvertake = std::numeric_limits<double>::max();
2309 return;
2310 } else {
2311 // allow for a safety time gap
2313 // round to multiples of step length (TS)
2314 if (u > 0) {
2315 t = ceil(t / TS) * TS;
2316 }
2317 timeToOvertake = t;
2318 spaceToOvertake = s + (t - m) * vMax;
2319#ifdef DEBUG_CHANGE_OPPOSITE_OVERTAKINGTIME
2320 if (DEBUG_COND) {
2321 std::cout << " t2=" << t << " s=" << s << " sto=" << spaceToOvertake << " m=" << m << "\n";
2322 }
2323#endif
2324 }
2325 }
2326 const double safetyFactor = OPPOSITE_OVERTAKING_SAFETY_FACTOR * vehicle->getLaneChangeModel().getOppositeSafetyFactor();
2327 timeToOvertake *= safetyFactor;
2328 if (STEPS2TIME(leader->getStopDuration()) < timeToOvertake) {
2329 spaceToOvertake *= safetyFactor;
2330 }
2331 double frac = fmod(timeToOvertake, TS);
2332 if (frac > 0) {
2333 // round to full sim step
2334 timeToOvertake += TS - frac;
2335 }
2336#ifdef DEBUG_CHANGE_OPPOSITE_OVERTAKINGTIME
2337 if (DEBUG_COND) {
2338 if (safetyFactor != 1) {
2339 std::cout << " applying safetyFactor=" << safetyFactor
2340 << " leaderStopTime=" << STEPS2TIME(leader->getStopDuration())
2341 << " tto=" << timeToOvertake << " sto=" << spaceToOvertake << "\n";
2342 }
2343 }
2344#endif
2345}
2346
2347
2348
2349std::pair<MSVehicle*, double>
2350MSLaneChanger::getColumnleader(double& maxSpace, MSVehicle* vehicle, std::pair<MSVehicle*, double> leader, double maxLookAhead) {
2351 assert(leader.first != 0);
2352 const bool isEmergency = vehicle->getVClass() == SVC_EMERGENCY;
2353 const MSLane* source = vehicle->getLane();
2354 // find a leader vehicle with sufficient space ahead for merging back
2355 const double overtakingSpeed = source->getVehicleMaxSpeed(vehicle); // just a guess
2356 const double mergeBrakeGap = vehicle->getCarFollowModel().brakeGap(overtakingSpeed);
2357 std::pair<MSVehicle*, double> columnLeader = leader;
2358 double egoGap = leader.second;
2359 bool foundSpaceAhead = false;
2360 double seen = leader.second + leader.first->getVehicleType().getLengthWithGap();
2361 std::vector<MSLane*> conts = vehicle->getBestLanesContinuation();
2362 if (maxLookAhead == std::numeric_limits<double>::max()) {
2363 maxLookAhead = (isEmergency
2366 maxLookAhead = MAX2(maxLookAhead, mergeBrakeGap + 10
2367 + vehicle->getVehicleType().getLengthWithGap()
2368 + leader.first->getVehicleType().getLengthWithGap());
2369 }
2370#ifdef DEBUG_CHANGE_OPPOSITE
2371 if (DEBUG_COND) {
2372 std::cout << " getColumnleader vehicle=" << vehicle->getID() << " leader=" << leader.first->getID() << " gap=" << leader.second << " maxLookAhead=" << maxLookAhead << "\n";
2373 }
2374#endif
2375 const double safetyFactor = OPPOSITE_OVERTAKING_SAFETY_FACTOR * vehicle->getLaneChangeModel().getOppositeSafetyFactor();
2376 while (!foundSpaceAhead) {
2377 const double requiredSpaceAfterLeader = (columnLeader.first->getCarFollowModel().getSecureGap(
2378 columnLeader.first, vehicle,
2379 columnLeader.first->getSpeed(), overtakingSpeed, vehicle->getCarFollowModel().getMaxDecel())
2380 + columnLeader.first->getVehicleType().getMinGap()
2381 + vehicle->getVehicleType().getLengthWithGap());
2382
2383
2384 // all leader vehicles on the current laneChanger edge are already moved into MSLane::myTmpVehicles
2385 const bool checkTmpVehicles = (&columnLeader.first->getLane()->getEdge() == &source->getEdge());
2386 double searchStart = columnLeader.first->getPositionOnLane();
2387 std::pair<MSVehicle*, double> leadLead = columnLeader.first->getLane()->getLeader(
2388 columnLeader.first, searchStart, conts, requiredSpaceAfterLeader + mergeBrakeGap,
2389 checkTmpVehicles);
2390 std::set<MSVehicle*> seenLeaders;
2391 while (leadLead.first != nullptr && leadLead.first->getLaneChangeModel().isOpposite()) {
2392#ifdef DEBUG_CHANGE_OPPOSITE
2393 if (DEBUG_COND) {
2394 std::cout << " skipping opposite leadLead=" << leadLead.first->getID() << " gap=" << leadLead.second << "\n";
2395 }
2396#endif
2397 if (leadLead.second + seen > maxLookAhead || seenLeaders.count(leadLead.first) > 0) {
2398 leadLead.first = nullptr;
2399 break;
2400 }
2401 seenLeaders.insert(leadLead.first);
2402 // found via shadow lane, skip it
2403 const double searchStart2 = searchStart + MAX2(0.0, leadLead.second) + leadLead.first->getVehicleType().getLengthWithGap();
2404 leadLead = columnLeader.first->getLane()->getLeader(
2405 columnLeader.first, searchStart2, conts, requiredSpaceAfterLeader + mergeBrakeGap,
2406 checkTmpVehicles);
2407 leadLead.second += (searchStart2 - searchStart);
2408 }
2409 if (leadLead.first == nullptr) {
2410 double availableSpace = columnLeader.first->getLane()->getLength() - columnLeader.first->getPositionOnLane();
2411 double requiredSpace = safetyFactor * requiredSpaceAfterLeader;
2412 if (!columnLeader.first->isStopped()) {
2413 // if the leader is stopped we can trade space for time
2414 requiredSpace += safetyFactor * mergeBrakeGap;
2415 }
2416#ifdef DEBUG_CHANGE_OPPOSITE
2417 if (DEBUG_COND) {
2418 std::cout << " no direct leader found after columnLeader " << columnLeader.first->getID()
2419 << " availableSpace=" << availableSpace
2420 << " reqAfterLeader=" << requiredSpaceAfterLeader
2421 << " ovSpeed=" << overtakingSpeed
2422 << " reqBGap=" << mergeBrakeGap
2423 << " reqMin=" << requiredSpace / safetyFactor
2424 << " req=" << requiredSpace
2425 << "\n";
2426 }
2427#endif
2428 if (availableSpace > requiredSpace) {
2429 foundSpaceAhead = true;
2430 } else {
2431 // maybe the columnleader is stopped before a junction or takes a different turn.
2432 // try to find another columnleader on successive lanes
2433 bool contsEnd = false;
2434 const MSLane* next = getLaneAfter(columnLeader.first->getLane(), conts, isEmergency, contsEnd);
2435#ifdef DEBUG_CHANGE_OPPOSITE
2436 if (DEBUG_COND) {
2437 std::cout << " look for another leader on lane " << Named::getIDSecure(next) << "\n";
2438 }
2439#endif
2440 while (next != nullptr && seen < maxLookAhead) {
2441 seen += next->getLength();
2442 MSVehicle* cand = next->getLastAnyVehicle();
2443 if (cand == nullptr) {
2444 availableSpace += next->getLength();
2445 if (availableSpace > requiredSpace) {
2446 foundSpaceAhead = true;
2447 break;
2448 }
2449 next = getLaneAfter(next, conts, isEmergency, contsEnd);
2450 } else {
2451 availableSpace += cand->getBackPositionOnLane();
2452 if (availableSpace > requiredSpace) {
2453 foundSpaceAhead = true;
2454 break;
2455 } else {
2456 return getColumnleader(maxSpace, vehicle, std::make_pair(cand, availableSpace + cand->getPositionOnLane()), maxLookAhead - seen);
2457 }
2458 }
2459 }
2460#ifdef DEBUG_CHANGE_OPPOSITE
2461 if (DEBUG_COND) {
2462 std::cout << " foundSpaceAhead=" << foundSpaceAhead << " availableSpace=" << availableSpace << " next=" << Named::getIDSecure(next) << " contsEnd=" << contsEnd << " conts=" << toString(conts) << "\n";
2463 }
2464#endif
2465 if (!foundSpaceAhead && contsEnd) {
2466 foundSpaceAhead = true;
2467 availableSpace = requiredSpace;
2468 }
2469 if (!foundSpaceAhead) {
2470 return std::make_pair(nullptr, -1);
2471 }
2472 }
2473 maxSpace = egoGap + columnLeader.first->getVehicleType().getLength() + availableSpace;
2474 } else {
2475 const double sGap = vehicle->getCarFollowModel().getSecureGap(vehicle, leadLead.first,
2476 overtakingSpeed, leadLead.first->getSpeed(), leadLead.first->getCarFollowModel().getMaxDecel());
2477 double requiredSpace = safetyFactor * requiredSpaceAfterLeader;
2478 if (!columnLeader.first->isStopped()) {
2479 // if the leader is stopped we can trade space for time
2480 requiredSpace += safetyFactor * sGap;
2481 }
2482#ifdef DEBUG_CHANGE_OPPOSITE
2483 if (DEBUG_COND) {
2484 std::cout << " leader's leader " << leadLead.first->getID() << " space=" << leadLead.second
2485 << " reqAfterLeader=" << requiredSpaceAfterLeader
2486 << " ovSpeed=" << overtakingSpeed
2487 << " reqSGap=" << sGap
2488 << " reqMin=" << requiredSpace / safetyFactor
2489 << " req=" << requiredSpace
2490 << "\n";
2491 }
2492#endif
2493 if (leadLead.second > requiredSpace) {
2494 foundSpaceAhead = true;
2495 maxSpace = egoGap + columnLeader.first->getVehicleType().getLength() + leadLead.second;
2496 } else {
2497
2498 if (leadLead.second < 0) {
2499 // must be a junction leader or some other dangerous situation
2500#ifdef DEBUG_CHANGE_OPPOSITE
2501 if (DEBUG_COND) {
2502 std::cout << " leader's leader " << leadLead.first->getID() << " gap=" << leadLead.second << " is junction leader (aborting)\n";
2503 }
2504#endif
2505 return std::make_pair(nullptr, -1);
2506 }
2507
2508#ifdef DEBUG_CHANGE_OPPOSITE
2509 if (DEBUG_COND) {
2510 std::cout << " not enough space after columnLeader=" << columnLeader.first->getID() << " required=" << requiredSpace << "\n";
2511 }
2512#endif
2513 seen += MAX2(0., leadLead.second) + leadLead.first->getVehicleType().getLengthWithGap();
2514 if (seen > maxLookAhead) {
2515#ifdef DEBUG_CHANGE_OPPOSITE
2516 if (DEBUG_COND) {
2517 std::cout << " cannot changeOpposite due to insufficient free space after columnLeader (seen=" << seen << " columnLeader=" << columnLeader.first->getID() << ")\n";
2518 }
2519#endif
2520 return std::make_pair(nullptr, -1);
2521 }
2522 // see if merging after leadLead is possible
2523 egoGap += columnLeader.first->getVehicleType().getLengthWithGap() + leadLead.second;
2524 columnLeader = leadLead;
2525#ifdef DEBUG_CHANGE_OPPOSITE
2526 if (DEBUG_COND) {
2527 std::cout << " new columnLeader=" << columnLeader.first->getID() << "\n";
2528 }
2529#endif
2530 }
2531 }
2532 }
2533 columnLeader.second = egoGap;
2534 return columnLeader;
2535}
2536
2537
2538const MSLane*
2539MSLaneChanger::getLaneAfter(const MSLane* lane, const std::vector<MSLane*>& conts, bool allowMinor, bool& contsEnd) {
2540 for (auto it = conts.begin(); it != conts.end(); ++it) {
2541 if (*it == lane) {
2542 if (it + 1 != conts.end()) {
2543 // abort on minor link
2544 const MSLane* next = *(it + 1);
2545 const MSLink* link = lane->getLinkTo(next);
2546 if (link == nullptr || (!allowMinor && !link->havePriority())) {
2547 return nullptr;
2548 }
2549 return next;
2550 } else {
2551 contsEnd = true;
2552 return nullptr;
2553 }
2554 }
2555 }
2556 return nullptr;
2557}
2558
2559double
2560MSLaneChanger::getMaxOvertakingSpeed(const MSVehicle* vehicle, double maxSpaceToOvertake) {
2561 // v*v/2*a + v*v/2*d = maxSpaceToOvertake
2562 const double a = vehicle->getCarFollowModel().getMaxAccel();
2563 const double d = vehicle->getCarFollowModel().getMaxDecel();
2564 const double v = sqrt(2 * maxSpaceToOvertake * a * d / (a + d));
2565 return v;
2566}
2567
2568/****************************************************************************/
long long int SUMOTime
Definition GUI.h:36
#define OPPOSITE_OVERTAKING_HILLTOP_THRESHOHOLD
#define OPPOSITE_OVERTAKING_MAX_LOOKAHEAD
#define OPPOSITE_OVERTAKING_SAFETYGAP_HEADWAY_FACTOR
#define OPPOSITE_OVERTAKING_MAX_LOOKAHEAD_EMERGENCY
#define OPPOSITE_OVERTAKING_DEADLOCK_WAIT
#define OPPOSITE_OVERTAKING_ONCOMING_LOOKAHEAD
#define OPPOSITE_OVERTAKING_SAFETY_FACTOR
#define OPPOSITE_OVERTAKING_SAFE_TIMEGAP
#define OPPOSITE_OVERTAKING_MAX_SPACE_TO_OVERTAKE
std::pair< const MSVehicle *, double > CLeaderDist
std::pair< const MSPerson *, double > PersonDist
Definition MSPModel.h:41
SUMOTime DELTA_T
Definition SUMOTime.cpp:38
#define STEPS2TIME(x)
Definition SUMOTime.h:55
#define SPEED2DIST(x)
Definition SUMOTime.h:45
#define ACCEL2SPEED(x)
Definition SUMOTime.h:51
#define TS
Definition SUMOTime.h:42
#define SIMTIME
Definition SUMOTime.h:62
#define TIME2STEPS(x)
Definition SUMOTime.h:57
SUMOVehicleClass
Definition of vehicle classes to differ between different lane usage and authority types.
@ SVC_EMERGENCY
public emergency vehicles
@ RIGHT
The link is a (hard) right direction.
@ LEFT
The link is a (hard) left direction.
@ STRAIGHT
The link is a straight direction.
@ LINKSTATE_ZIPPER
This is an uncontrolled, zipper-merge link.
LaneChangeAction
The state of a vehicle's lane-change behavior.
@ LCA_BLOCKED
blocked in all directions
@ LCA_URGENT
The action is urgent (to be defined by lc-model)
@ LCA_BLOCKED_BY_RIGHT_LEADER
The vehicle is blocked by right leader.
@ LCA_INSUFFICIENT_SPACE
The vehicle does not have enough space to complete a continuous change before the next turn.
@ LCA_BLOCKED_BY_LEFT_FOLLOWER
The vehicle is blocked by left follower.
@ LCA_COOPERATIVE
The action is done to help someone else.
@ LCA_INSUFFICIENT_SPEED
Vehicle is too slow to complete a continuous lane change (in case that maxSpeedLatStanding==0)
@ LCA_OVERLAPPING
The vehicle is blocked being overlapping.
@ LCA_LEFT
Wants go to the left.
@ LCA_BLOCKED_BY_RIGHT_FOLLOWER
The vehicle is blocked by right follower.
@ LCA_TRACI
The action is due to a TraCI request.
@ LCA_WANTS_LANECHANGE
lane can change
@ LCA_RIGHT
Wants go to the right.
@ LCA_BLOCKED_BY_LEFT_LEADER
bool gDebugFlag5
Definition StdDefs.cpp:41
const double SUMO_const_laneWidth
Definition StdDefs.h:48
T MIN2(T a, T b)
Definition StdDefs.h:76
T MAX2(T a, T b)
Definition StdDefs.h:82
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
Definition ToString.h:46
A class responsible for exchanging messages between cars involved in lane-change interaction.
Interface for lane-change models.
double getLaneChangeCompletion() const
Get the current lane change completion ratio.
double getForwardPos() const
get vehicle position relative to the forward direction lane
void setFollowerGaps(CLeaderDist follower, double secGap)
virtual void setOwnState(const int state)
virtual double getAssumedDecelForLaneChangeDuration() const
Returns a deceleration value which is used for the estimation of the duration of a lane change.
virtual double estimateLCDuration(const double speed, const double remainingManeuverDist, const double decel, bool urgent) const
Calculates the maximal time needed to complete a lane change maneuver if lcMaxSpeedLatFactor and lcMa...
int getLaneChangeDirection() const
return the direction of the current lane change maneuver
MSLane * getShadowLane() const
Returns the lane the vehicle's shadow is on during continuous/sublane lane change.
bool startLaneChangeManeuver(MSLane *source, MSLane *target, int direction)
start the lane change maneuver and return whether it continues
void endLaneChangeManeuver(const MSMoveReminder::Notification reason=MSMoveReminder::NOTIFICATION_LANE_CHANGE)
virtual double getSafetyFactor() const
return factor for modifying the safety constraints of the car-following model
void saveLCState(const int dir, int stateWithoutTraCI, const int state)
virtual bool saveBlockerLength(double, double)
reserve space at the end of the lane to avoid dead locks
virtual 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)
Called to examine whether the vehicle wants to change using the given laneOffset. This method gets th...
virtual double getOppositeSafetyFactor() const
return factor for modifying the safety constraints for opposite-diretction overtaking of the car-foll...
void setLeaderGaps(CLeaderDist, double secGap)
void setOrigLeaderGaps(CLeaderDist, double secGap)
int getNormalizedLaneIndex()
brief return lane index that treats opposite lanes like normal lanes to the left of the forward lanes
virtual int checkChangeBeforeCommitting(const MSVehicle *veh, int state) const
Informs the vehicle that it is about to be moved on an adjacent lane. The method can be used to re-ev...
void checkTraCICommands()
Check for commands issued for the vehicle via TraCI and apply the appropriate state changes For the s...
void primaryLaneChanged(MSLane *source, MSLane *target, int direction)
called once when the vehicles primary lane changes
double getSpeedLat() const
return the lateral speed of the current lane change maneuver
bool alreadyChanged() const
reset the flag whether a vehicle already moved to false
bool isChangingLanes() const
return true if the vehicle currently performs a lane change maneuver
void clearNeighbors()
Clear info on neighboring vehicle from previous step.
void saveNeighbors(const int dir, const MSLeaderDistanceInfo &followers, const MSLeaderDistanceInfo &leaders)
Saves the lane change relevant vehicles, which are currently on neighboring lanes in the given direct...
double getWaitingSeconds() const
Returns the number of seconds waited (speed was lesser than 0.1m/s)
bool hasStops() const
Returns whether the vehicle has to stop somewhere.
const MSStop & getNextStop() const
SUMOVehicleClass getVClass() const
Returns the vehicle's access class.
SUMOTime getStopDuration() const
get remaining stop duration or 0 if the vehicle isn't stopped
const MSVehicleType & getVehicleType() const
Returns the vehicle's type definition.
bool isStopped() const
Returns whether the vehicle is at a stop.
virtual double getSecureGap(const MSVehicle *const veh, const MSVehicle *const, const double speed, const double leaderSpeed, const double leaderMaxDecel) const
Returns the minimum gap to reserve if the leader is braking at maximum (>=0)
double getMaxAccel() const
Get the vehicle type's maximum acceleration [m/s^2].
Definition MSCFModel.h:261
double brakeGap(const double speed) const
Returns the distance the vehicle needs to halt including driver's reaction time tau (i....
Definition MSCFModel.h:408
double getMaxDecel() const
Get the vehicle type's maximal comfortable deceleration [m/s^2].
Definition MSCFModel.h:269
virtual double getHeadwayTime() const
Get the driver's desired headway [s].
Definition MSCFModel.h:339
A road/street connecting two junctions.
Definition MSEdge.h:77
const std::vector< MSLane * > & getLanes() const
Returns this edge's lanes.
Definition MSEdge.h:168
const MSEdge * getOppositeEdge() const
Returns the opposite direction edge if on exists else a nullptr.
Definition MSEdge.cpp:1340
const MSEdge * getNormalSuccessor() const
if this edge is an internal edge, return its first normal successor, otherwise the edge itself
Definition MSEdge.cpp:947
int getNumLanes() const
Definition MSEdge.h:172
bool isInternal() const
return whether this edge is an internal edge
Definition MSEdge.h:268
static double gLateralResolution
Definition MSGlobals.h:100
static bool gLefthand
Whether lefthand-drive is being simulated.
Definition MSGlobals.h:174
static bool gSublane
whether sublane simulation is enabled (sublane model or continuous lanechanging)
Definition MSGlobals.h:165
static SUMOTime gLaneChangeDuration
Definition MSGlobals.h:97
virtual ~MSLaneChanger()
Destructor.
bool applyTraCICommands(MSVehicle *vehicle)
Execute TraCI LC-commands.
bool continueChange(MSVehicle *vehicle, ChangerIt &from)
continue a lane change maneuver and return whether the vehicle has completely moved onto the new lane...
const bool myChangeToOpposite
whether this edge allows changing to the opposite direction edge
bool checkOppositeStop(MSVehicle *vehicle, const MSLane *oncomingLane, const MSLane *opposite, std::pair< MSVehicle *, double > leader)
decide whether to change (back or forth) for an opposite stop
bool changeOpposite(MSVehicle *vehicle, std::pair< MSVehicle *, double > leader, MSVehicle *lastStopped)
MSLaneChanger()
Default constructor.
static bool hasOppositeStop(MSVehicle *vehicle)
whether vehicle has an opposite-direction stop within relevant range
void checkTraCICommands(MSVehicle *vehicle)
Take into account traci LC-commands.
void laneChange(SUMOTime t)
Start lane-change-process for all vehicles on the edge'e lanes.
virtual void initChanger()
Initialize the changer before looping over all vehicles.
bool vehInChanger() const
Check if there is a single change-candidate in the changer. Returns true if there is one.
std::pair< MSVehicle *const, double > getRealFollower(const ChangerIt &target) const
virtual bool change()
static const MSLane * getLaneAfter(const MSLane *lane, const std::vector< MSLane * > &conts, bool allowMinor, bool &contsEnd)
return the next lane in conts beyond lane or nullptr
std::pair< MSVehicle *const, double > getOncomingOppositeVehicle(const MSVehicle *vehicle, std::pair< MSVehicle *, double > overtaken, double searchDist)
MSVehicle * veh(ConstChangerIt ce) const
std::pair< MSVehicle *const, double > getOncomingVehicle(const MSLane *opposite, std::pair< MSVehicle *, double > neighOncoming, double searchDist, double &vMax, const MSVehicle *overtaken=nullptr, MSLane::MinorLinkMode mLinkMode=MSLane::MinorLinkMode::FOLLOW_NEVER)
bool startChange(MSVehicle *vehicle, ChangerIt &from, int direction)
const bool myAllowsChanging
double computeSafeOppositeLength(MSVehicle *vehicle, double oppositeLength, const MSLane *source, double usableDist, std::pair< MSVehicle *, double > oncoming, double vMax, double oncomingSpeed, std::pair< MSVehicle *, double > neighLead, std::pair< MSVehicle *, double > overtaken, std::pair< MSVehicle *, double > neighFollow, double surplusGap, const MSLane *opposite, bool canOvertake)
determine for how long the vehicle can drive safely on the opposite side
int checkChangeWithinEdge(int laneOffset, const std::pair< MSVehicle *const, double > &leader, const std::vector< MSVehicle::LaneQ > &preb) const
static bool foundHilltop(MSVehicle *vehicle, bool foundHill, double searchDist, const std::vector< MSLane * > &bestLanes, int view, double pos, double lastMax, double hilltopThreshold)
Changer myChanger
Container for ChangeElemements, one for every lane in the edge.
static double computeSurplusGap(const MSVehicle *vehicle, const MSLane *opposite, std::pair< MSVehicle *, double > oncoming, double timeToOvertake, double spaceToOvertake, double &oncomingSpeed, bool oncomingOpposite=false)
ChangerIt findCandidate()
Find current candidate. If there is none, myChanger.end() is returned.
bool mayChange(int direction) const
whether changing to the lane in the given direction should be considered
bool yieldToOppositeWaiting(const MSVehicle *vehicle, const MSVehicle *stoppedNeigh, double dist, SUMOTime deltaWait=0)
check whether to yield for oncoming vehicles that have waited longer for opposite overtaking
static MSVehicle * getCloserFollower(const double maxPos, MSVehicle *follow1, MSVehicle *follow2)
return the closer follower of ego
void registerUnchanged(MSVehicle *vehicle)
void updateLanes(SUMOTime t)
bool avoidDeadlock(MSVehicle *vehicle, std::pair< MSVehicle *, double > neighLead, std::pair< MSVehicle *, double > overtaken, std::pair< MSVehicle *, double > leader)
avoid opposite-diretion deadlock when vehicles are stopped on both sides of the road The method may c...
static std::pair< MSVehicle *, double > getColumnleader(double &maxSpace, MSVehicle *vehicle, std::pair< MSVehicle *, double > leader, double maxLookAhead=std::numeric_limits< double >::max())
return leader vehicle that is to be overtaken
static double getMaxOvertakingSpeed(const MSVehicle *vehicle, double maxSpaceToOvertake)
compute maximum maneuver speed
ChangerIt myCandi
bool resolveDeadlock(MSVehicle *vehicle, std::pair< MSVehicle *const, double > leader, std::pair< MSVehicle *, double > neighLead, std::pair< MSVehicle *, double > overtaken)
keep stopping to resolve opposite-diretion deadlock while there is oncoming traffic The method may ca...
std::pair< MSVehicle *const, double > getRealLeader(const ChangerIt &target) const
bool yieldToDeadlockOncoming(const MSVehicle *vehicle, const MSVehicle *stoppedNeigh, double dist)
check whether to keep stopping for oncoming vehicles in the deadlock zone
Changer::iterator ChangerIt
the iterator moving over the ChangeElems
int checkChange(int laneOffset, const MSLane *targetLane, const std::pair< MSVehicle *const, double > &leader, const std::pair< MSVehicle *const, double > &follower, const std::pair< MSVehicle *const, double > &neighLead, const std::pair< MSVehicle *const, double > &neighFollow, const std::vector< MSVehicle::LaneQ > &preb) const
virtual bool checkChangeOpposite(MSVehicle *vehicle, int laneOffset, MSLane *targetLane, const std::pair< MSVehicle *const, double > &leader, const std::pair< MSVehicle *const, double > &neighLead, const std::pair< MSVehicle *const, double > &neighFollow, const std::vector< MSVehicle::LaneQ > &preb)
static void computeOvertakingTime(const MSVehicle *vehicle, double vMax, const MSVehicle *leader, double gap, double &timeToOvertake, double &spaceToOvertake)
Compute the time and space required for overtaking the given leader.
static std::vector< MSVehicle::LaneQ > getBestLanesOpposite(MSVehicle *vehicle, const MSLane *stopLane, double oppositeLength)
add LaneQ for opposite lanes
virtual void updateChanger(bool vehHasChanged)
Representation of a lane in the micro simulation.
Definition MSLane.h:84
std::pair< MSVehicle *const, double > getFollower(const MSVehicle *ego, double egoPos, double dist, MinorLinkMode mLinkMode) const
Find follower vehicle for the given ego vehicle (which may be on the opposite direction lane)
Definition MSLane.cpp:4368
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:4542
MSLane * getParallelLane(int offset, bool includeOpposite=true) const
Returns the lane with the given offset parallel to this one or 0 if it does not exist.
Definition MSLane.cpp:2824
static std::vector< MSLink * >::const_iterator succLinkSec(const SUMOVehicle &veh, int nRouteSuccs, const MSLane &succLinkSource, const std::vector< MSLane * > &conts)
Definition MSLane.cpp:2668
const MSLink * getLinkTo(const MSLane *const) const
returns the link to the given lane or nullptr, if it is not connected
Definition MSLane.cpp:2719
double getSpeedLimit() const
Returns the lane's maximum allowed speed.
Definition MSLane.h:592
std::vector< MSVehicle * > VehCont
Container for vehicles.
Definition MSLane.h:119
std::pair< MSVehicle *const, double > getOppositeLeader(const MSVehicle *ego, double dist, bool oppositeDir, MinorLinkMode mLinkMode=MinorLinkMode::FOLLOW_NEVER) const
Definition MSLane.cpp:4391
const std::vector< IncomingLaneInfo > & getIncomingLanes() const
Definition MSLane.h:950
double getLength() const
Returns the lane's length.
Definition MSLane.h:606
bool allowsChangingLeft(SUMOVehicleClass vclass) const
Returns whether the given vehicle class may change left from this lane.
Definition MSLane.h:932
std::pair< MSVehicle *const, double > getCriticalLeader(double dist, double seen, double speed, const MSVehicle &veh) const
Returns the most dangerous leader and the distance to him.
Definition MSLane.cpp:3106
bool isLinkEnd(std::vector< MSLink * >::const_iterator &i) const
Definition MSLane.h:853
bool allowsVehicleClass(SUMOVehicleClass vclass) const
Definition MSLane.h:925
double getVehicleMaxSpeed(const SUMOTrafficObject *const veh) const
Returns the lane's maximum speed, given a vehicle's speed limit adaptation.
Definition MSLane.h:574
std::pair< MSVehicle *const, double > getOppositeFollower(const MSVehicle *ego) const
Definition MSLane.cpp:4419
bool hasPedestrians() const
whether the lane has pedestrians on it
Definition MSLane.cpp:4535
int getIndex() const
Returns the lane's index.
Definition MSLane.h:642
void requireCollisionCheck()
require another collision check due to relevant changes in the simulation
Definition MSLane.h:710
double getOppositePos(double pos) const
return the corresponding position on the opposite lane
Definition MSLane.cpp:4363
MSVehicle * getLastAnyVehicle() const
returns the last vehicle that is fully or partially on this lane
Definition MSLane.cpp:2635
bool isInternal() const
Definition MSLane.cpp:2594
VehCont myPartialVehicles
The lane's partial vehicles. This container holds all vehicles that are partially on this lane but wh...
Definition MSLane.h:1473
MinorLinkMode
determine whether/how getFollowers looks upstream beyond minor links
Definition MSLane.h:973
@ FOLLOW_ONCOMING
Definition MSLane.h:976
double interpolateGeometryPosToLanePos(double geometryPos) const
Definition MSLane.h:566
std::pair< MSVehicle *const, double > getLeader(const MSVehicle *veh, const double vehPos, const std::vector< MSLane * > &bestLaneConts, double dist=-1, bool checkTmpVehicles=false) const
Returns the immediate leader of veh and the distance to veh starting on this lane.
Definition MSLane.cpp:2893
MSLane * getOpposite() const
return the neighboring opposite direction lane for lane changing or nullptr
Definition MSLane.cpp:4351
virtual const PositionVector & getShape(bool) const
Definition MSLane.h:294
MSEdge & getEdge() const
Returns the lane's edge.
Definition MSLane.h:764
double getWidth() const
Returns the lane's width.
Definition MSLane.h:635
const std::vector< MSLink * > & getLinkCont() const
returns the container with all links !!!
Definition MSLane.h:724
static MSNet * getInstance()
Returns the pointer to the unique instance of MSNet (singleton).
Definition MSNet.cpp:186
bool hasElevation() const
return whether the network contains elevation data
Definition MSNet.h:795
const MSLane * lane
The lane to stop at (microsim only)
Definition MSStop.h:50
bool isOpposite
whether this an opposite-direction stop
Definition MSStop.h:87
bool getRespectJunctionPriority() const
Returns whether junction priority rules shall be respected (concerns approaching vehicles outside the...
Definition MSVehicle.h:1511
SUMOTime getLaneTimeLineDuration()
double myPosLat
the stored lateral position
Definition MSVehicle.h:140
Representation of a vehicle in the micro simulation.
Definition MSVehicle.h:77
void updateBestLanes(bool forceRebuild=false, const MSLane *startLane=0)
computes the best lanes to use in order to continue the route
double computeAngle() const
compute the current vehicle angle
bool isStoppedOnLane() const
bool isActive() const
Returns whether the current simulation step is an action point for the vehicle.
Definition MSVehicle.h:628
SUMOTime getWaitingTime(const bool accumulated=false) const
Returns the SUMOTime waited (speed was lesser than 0.1m/s)
Definition MSVehicle.h:670
bool isFrontOnLane(const MSLane *lane) const
Returns the information whether the front of the vehicle is on the given lane.
MSAbstractLaneChangeModel & getLaneChangeModel()
int influenceChangeDecision(int state)
allow TraCI to influence a lane change decision
bool isRemoteControlled() const
Returns the information whether the vehicle is fully controlled via TraCI.
double nextStopDist() const
return the distance to the next stop or doubleMax if there is none.
Definition MSVehicle.h:1035
void adaptBestLanesOccupation(int laneIndex, double density)
update occupation from MSLaneChanger
double getAcceleration() const
Returns the vehicle's acceleration in m/s (this is computed as the last step's mean acceleration in c...
Definition MSVehicle.h:514
Position getPosition(const double offset=0) const
Return current position (x/y, cartesian)
const std::vector< MSLane * > & getBestLanesContinuation() const
Returns the best sequence of lanes to continue the route starting at myLane.
double getBackPositionOnLane(const MSLane *lane) const
Get the vehicle's position relative to the given lane.
Definition MSVehicle.h:398
bool unsafeLinkAhead(const MSLane *lane, double zipperDist) const
whether the vehicle may safely move to the given lane with regard to upcoming links
@ VEH_SIGNAL_BLINKER_RIGHT
Right blinker lights are switched on.
Definition MSVehicle.h:1109
@ VEH_SIGNAL_BLINKER_LEFT
Left blinker lights are switched on.
Definition MSVehicle.h:1111
SUMOTime getActionStepLength() const
Returns the vehicle's action step length in millisecs, i.e. the interval between two action points.
Definition MSVehicle.h:525
const MSLane * getLane() const
Returns the lane the vehicle is on.
Definition MSVehicle.h:581
std::pair< const MSVehicle *const, double > getFollower(double dist=0) const
Returns the follower of the vehicle looking for a fixed distance.
MSLane * getMutableLane() const
Returns the lane the vehicle is on Non const version indicates that something volatile is going on.
Definition MSVehicle.h:589
Influencer & getInfluencer()
double getRightSideOnLane() const
Get the lateral position of the vehicles right side on the lane:
double getLateralPositionOnLane() const
Get the vehicle's lateral position on the lane.
Definition MSVehicle.h:413
double getSlope() const
Returns the slope of the road at vehicle's position in degrees.
double getSpeed() const
Returns the vehicle's current speed.
Definition MSVehicle.h:490
Position myCachedPosition
Definition MSVehicle.h:1943
const std::vector< LaneQ > & getBestLanes() const
Returns the description of best lanes to use in order to continue the route.
const MSCFModel & getCarFollowModel() const
Returns the vehicle's car following model definition.
Definition MSVehicle.h:969
double myAngle
the angle in radians (
Definition MSVehicle.h:1935
bool ignoreRed(const MSLink *link, bool canBrake) const
decide whether a red (or yellow light) may be ignored
double getPositionOnLane() const
Get the vehicle's position along the lane.
Definition MSVehicle.h:374
bool hasInfluencer() const
whether the vehicle is individually influenced (via TraCI or special parameters)
Definition MSVehicle.h:1690
double getBrakeGap(bool delayed=false) const
get distance for coming to a stop (used for rerouting checks)
State myState
This Vehicles driving state (pos and speed)
Definition MSVehicle.h:1873
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
static const Position INVALID
used to indicate that a position is valid
Definition Position.h:319
double z() const
Returns the z-position.
Definition Position.h:62
A list of positions.
#define UNUSED_PARAMETER(x)
#define DEBUG_COND
#define M_PI
Definition odrSpiral.cpp:45
double zipperDist
visibility distance to the closest zipper link that may be encountered when driving on this lane
MSLane * lane
the lane corresponding to this ChangeElem (the current change candidate is on this lane)
void registerHop(MSVehicle *vehicle)
Register that vehicle belongs to Changer Item to after LC decisions.