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