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