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