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