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