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