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