Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
eclipse
GitHub Repository: eclipse/sumo
Path: blob/main/src/microsim/MSLaneChangerSublane.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 MSLaneChangerSublane.cpp
15
/// @author Jakob Erdmann
16
/// @author Leonhard Luecken
17
/// @date Oct 2015
18
///
19
// Performs sub-lane changing of vehicles
20
/****************************************************************************/
21
#include <config.h>
22
23
#include "MSLaneChangerSublane.h"
24
#include "MSNet.h"
25
#include "MSLink.h"
26
#include "MSVehicle.h"
27
#include "MSVehicleType.h"
28
#include "MSVehicleTransfer.h"
29
#include "MSGlobals.h"
30
#include <cassert>
31
#include <iterator>
32
#include <cstdlib>
33
#include <cmath>
34
#include <microsim/lcmodels/MSAbstractLaneChangeModel.h>
35
#include <utils/common/MsgHandler.h>
36
#include <utils/geom/GeomHelper.h>
37
38
39
// ===========================================================================
40
// DEBUG constants
41
// ===========================================================================
42
#define DEBUG_COND (vehicle->getLaneChangeModel().debugVehicle())
43
//#define DEBUG_COND (vehicle->getID() == "disabled")
44
//#define DEBUG_COND true
45
//#define DEBUG_DECISION
46
//#define DEBUG_ACTIONSTEPS
47
//#define DEBUG_STATE
48
//#define DEBUG_MANEUVER
49
//#define DEBUG_SURROUNDING
50
//#define DEBUG_CHANGE_OPPOSITE
51
52
// ===========================================================================
53
// member method definitions
54
// ===========================================================================
55
MSLaneChangerSublane::MSLaneChangerSublane(const std::vector<MSLane*>* lanes, bool allowChanging) :
56
MSLaneChanger(lanes, allowChanging) {
57
// initialize siblings
58
if (myChanger.front().lane->isInternal()) {
59
for (ChangerIt ce = myChanger.begin(); ce != myChanger.end(); ++ce) {
60
for (ChangerIt ce2 = myChanger.begin(); ce2 != myChanger.end(); ++ce2) {
61
if (ce != ce2 && ce->lane->getIncomingLanes().front().lane == ce2->lane->getIncomingLanes().front().lane) {
62
//std::cout << "addSibling lane=" << ce->lane->getID() << " offset=" << ce2->lane->getIndex() - ce->lane->getIndex() << "\n";
63
ce->siblings.push_back(ce2->lane->getIndex() - ce->lane->getIndex());
64
}
65
}
66
}
67
}
68
}
69
70
71
MSLaneChangerSublane::~MSLaneChangerSublane() {}
72
73
void
74
MSLaneChangerSublane::initChanger() {
75
MSLaneChanger::initChanger();
76
// Prepare myChanger with a safe state.
77
for (ChangerIt ce = myChanger.begin(); ce != myChanger.end(); ++ce) {
78
ce->ahead = ce->lane->getPartialBeyond();
79
ce->outsideBounds.clear();
80
// std::cout << SIMTIME << " initChanger lane=" << ce->lane->getID() << " vehicles=" << toString(ce->lane->myVehicles) << "\n";
81
// std::cout << SIMTIME << " initChanger lane=" << ce->lane->getID() << " partial vehicles=" << toString(ce->lane->myPartialVehicles) << "\n";
82
// std::cout << SIMTIME << " initChanger lane=" << ce->lane->getID() << " partial vehicles beyond=" << toString(ce->ahead.toString()) << "\n";
83
}
84
}
85
86
87
88
void
89
MSLaneChangerSublane::updateChanger(bool vehHasChanged) {
90
MSLaneChanger::updateChanger(vehHasChanged);
91
if (!vehHasChanged) {
92
MSVehicle* lead = myCandi->lead;
93
//std::cout << SIMTIME << " updateChanger lane=" << myCandi->lane->getID() << " lead=" << Named::getIDSecure(lead) << " lsol=" << lead->getLeftSideOnLane() << " rsol=" << lead->getRightSideOnLane() << "\n";
94
if (lead->getLeftSideOnLane() < 0 || lead->getRightSideOnLane() > myCandi->lane->getWidth()) {
95
myCandi->outsideBounds.push_back(lead);
96
} else {
97
myCandi->ahead.addLeader(lead, false, 0);
98
}
99
MSLane* shadowLane = lead->getLaneChangeModel().getShadowLane();
100
if (shadowLane != nullptr && &shadowLane->getEdge() == &lead->getLane()->getEdge()) {
101
assert(shadowLane->getIndex() < (int)myChanger.size());
102
const double latOffset = lead->getLane()->getRightSideOnEdge() - shadowLane->getRightSideOnEdge();
103
//std::cout << SIMTIME << " updateChanger shadowLane=" << shadowLane->getID() << " lead=" << Named::getIDSecure(lead) << "\n";
104
(myChanger.begin() + shadowLane->getIndex())->ahead.addLeader(lead, false, latOffset);
105
}
106
}
107
//std::cout << SIMTIME << " updateChanger: lane=" << myCandi->lane->getID() << " lead=" << Named::getIDSecure(myCandi->lead) << " ahead=" << myCandi->ahead.toString() << " vehHasChanged=" << vehHasChanged << "\n";
108
//for (ChangerIt ce = myChanger.begin(); ce != myChanger.end(); ++ce) {
109
// std::cout << " lane=" << ce->lane->getID() << " vehicles=" << toString(ce->lane->myVehicles) << "\n";
110
//}
111
}
112
113
114
bool
115
MSLaneChangerSublane::change() {
116
// variant of change() for the sublane case
117
myCandi = findCandidate();
118
MSVehicle* vehicle = veh(myCandi);
119
vehicle->getLaneChangeModel().clearNeighbors();
120
#ifdef DEBUG_ACTIONSTEPS
121
if (DEBUG_COND) {
122
std::cout << "\n" << SIMTIME << " CHANGE veh=" << vehicle->getID() << " lane=" << vehicle->getLane()->getID() << "\n";
123
}
124
#endif
125
assert(vehicle->getLane() == (*myCandi).lane);
126
assert(!vehicle->getLaneChangeModel().isChangingLanes());
127
if (/*!myAllowsChanging*/ vehicle->getLaneChangeModel().alreadyChanged() || vehicle->isStoppedOnLane()) {
128
registerUnchanged(vehicle);
129
if (vehicle->isStoppedOnLane()) {
130
myCandi->lastStopped = vehicle;
131
}
132
return false;
133
}
134
if (!vehicle->isActive()) {
135
#ifdef DEBUG_ACTIONSTEPS
136
if (DEBUG_COND) {
137
std::cout << SIMTIME << " veh '" << vehicle->getID() << "' skips regular change checks." << std::endl;
138
}
139
#endif
140
141
bool changed;
142
// let TraCI influence the wish to change lanes during non-actionsteps
143
checkTraCICommands(vehicle);
144
145
// Resume change
146
changed = continueChangeSublane(vehicle, myCandi);
147
#ifdef DEBUG_ACTIONSTEPS
148
if (DEBUG_COND) {
149
std::cout << SIMTIME << " veh '" << vehicle->getID() << "' lcm->maneuverDist=" << vehicle->getLaneChangeModel().getManeuverDist()
150
<< " lcm->speedLat=" << vehicle->getLaneChangeModel().getSpeedLat() << std::endl;
151
}
152
#endif
153
if (!changed) {
154
registerUnchanged(vehicle);
155
}
156
return changed;
157
}
158
159
#ifdef DEBUG_ACTIONSTEPS
160
if (DEBUG_COND) {
161
std::cout << "\n" << SIMTIME << " veh '" << vehicle->getID() << "' plans lanechange maneuver." << std::endl;
162
}
163
#endif
164
vehicle->updateBestLanes(); // needed?
165
const bool isOpposite = vehicle->getLaneChangeModel().isOpposite();
166
if (!isOpposite) {
167
for (int i = 0; i < (int) myChanger.size(); ++i) {
168
vehicle->adaptBestLanesOccupation(i, myChanger[i].dens);
169
}
170
}
171
// update leaders beyond the current edge for all lanes
172
for (ChangerIt ce = myChanger.begin(); ce != myChanger.end(); ++ce) {
173
ce->aheadNext = getLeaders(ce, vehicle);
174
}
175
// update expected speeds
176
int sublaneIndex = 0;
177
for (ChangerIt ce = myChanger.begin(); ce != myChanger.end(); ++ce) {
178
vehicle->getLaneChangeModel().updateExpectedSublaneSpeeds(ce->aheadNext, sublaneIndex, ce->lane->getIndex());
179
for (int offset : ce->siblings) {
180
// treat sibling lanes (internal lanes with the same origin lane) as if they have the same geometry
181
ChangerIt ceSib = ce + offset;
182
if (ceSib->lane->allowsVehicleClass(vehicle->getVClass())) {
183
vehicle->getLaneChangeModel().updateExpectedSublaneSpeeds(ceSib->aheadNext, sublaneIndex, ceSib->lane->getIndex());
184
}
185
}
186
sublaneIndex += ce->ahead.numSublanes();
187
}
188
189
// Check for changes to the opposite lane if vehicle is active
190
#ifdef DEBUG_ACTIONSTEPS
191
if (DEBUG_COND) {
192
std::cout << " myChangeToOpposite=" << myChangeToOpposite << " isOpposite=" << isOpposite << " mayChangeRight=" << mayChange(-1) << " mayChangeLeft=" << mayChange(1) << "\n";
193
}
194
#endif
195
196
const bool stopOpposite = hasOppositeStop(vehicle);
197
const int traciState = vehicle->influenceChangeDecision(0);
198
const bool traciRequestOpposite = !mayChange(1) && (traciState & LCA_LEFT) != 0;
199
200
if (myChangeToOpposite && (
201
// cannot overtake since there is only one usable lane (or emergency)
202
((!mayChange(-1) && !mayChange(1)) || vehicle->getVClass() == SVC_EMERGENCY)
203
|| traciRequestOpposite
204
|| stopOpposite
205
// can alway come back from the opposite side
206
|| isOpposite)) {
207
const MSLeaderDistanceInfo& leaders = myCandi->aheadNext;
208
if (leaders.hasVehicles() || isOpposite || stopOpposite || traciRequestOpposite) {
209
std::pair<MSVehicle*, double> leader = findClosestLeader(leaders, vehicle);
210
myCheckedChangeOpposite = false;
211
if ((leader.first != nullptr || isOpposite || stopOpposite || traciRequestOpposite)
212
&& changeOpposite(vehicle, leader, myCandi->lastStopped)) {
213
return true;
214
} else if (myCheckedChangeOpposite) {
215
registerUnchanged(vehicle);
216
return false;
217
}
218
// try sublane change within current lane otherwise
219
}
220
}
221
222
LaneChangeAction alternatives = (LaneChangeAction)((mayChange(-1) ? LCA_RIGHT : LCA_NONE)
223
| (mayChange(1) ? LCA_LEFT : LCA_NONE));
224
225
StateAndDist right = checkChangeHelper(vehicle, -1, alternatives);
226
StateAndDist left = checkChangeHelper(vehicle, 1, alternatives);
227
StateAndDist current = checkChangeHelper(vehicle, 0, alternatives);
228
229
StateAndDist decision = vehicle->getLaneChangeModel().decideDirection(current,
230
vehicle->getLaneChangeModel().decideDirection(right, left));
231
#ifdef DEBUG_DECISION
232
if (vehicle->getLaneChangeModel().debugVehicle()) {
233
std::cout << "\n" << SIMTIME << " decision=" << toString((LaneChangeAction)decision.state) << " dir=" << decision.dir << " latDist=" << decision.latDist << " maneuverDist=" << decision.maneuverDist << "\n";
234
}
235
#endif
236
vehicle->getLaneChangeModel().setOwnState(decision.state);
237
if ((decision.state & LCA_WANTS_LANECHANGE) != 0 && (decision.state & LCA_BLOCKED) == 0) {
238
// change if the vehicle wants to and is allowed to change
239
#ifdef DEBUG_MANEUVER
240
if (DEBUG_COND) {
241
std::cout << SIMTIME << " veh '" << vehicle->getID() << "' performing sublane change..." << std::endl;
242
}
243
#endif
244
const bool changed = startChangeSublane(vehicle, myCandi, decision.latDist, decision.maneuverDist);
245
if (!changed) {
246
registerUnchanged(vehicle);
247
}
248
return changed;
249
}
250
// @note this assumes vehicles can instantly abort any maneuvre in case of emergency
251
abortLCManeuver(vehicle);
252
registerUnchanged(vehicle);
253
254
if ((right.state & (LCA_URGENT)) != 0 && (left.state & (LCA_URGENT)) != 0) {
255
// ... wants to go to the left AND to the right
256
// just let them go to the right lane...
257
left.state = 0;
258
}
259
return false;
260
}
261
262
263
void
264
MSLaneChangerSublane::abortLCManeuver(MSVehicle* vehicle) {
265
#ifdef DEBUG_MANEUVER
266
if (DEBUG_COND) {
267
std::cout << SIMTIME << " veh '" << vehicle->getID() << "' aborts LC-continuation."
268
<< std::endl;
269
}
270
#endif
271
const int priorReason = vehicle->getLaneChangeModel().getPrevState() & LCA_CHANGE_REASONS & ~LCA_SUBLANE;
272
const int reason = vehicle->getLaneChangeModel().getOwnState() & LCA_CHANGE_REASONS & ~LCA_SUBLANE;
273
if (priorReason != 0 && priorReason != reason && vehicle->getLaneChangeModel().getPreviousManeuverDist() != 0) {
274
// original from cannot be reconstructed
275
const int priorDirection = vehicle->getLaneChangeModel().getPreviousManeuverDist() > 0 ? 1 : -1;
276
#ifdef DEBUG_MANEUVER
277
if (DEBUG_COND) {
278
std::cout << SIMTIME << " abortLCManeuver priorReason=" << toString((LaneChangeAction)priorReason)
279
<< " reason=" << toString((LaneChangeAction)reason) << " veh=" << vehicle->getID() << "\n";
280
}
281
#endif
282
outputLCEnded(vehicle, myCandi, myCandi, priorDirection);
283
}
284
const double updatedSpeedLat = vehicle->getLaneChangeModel().getSpeedLat() != 0;
285
vehicle->getLaneChangeModel().setSpeedLat(0);
286
vehicle->getLaneChangeModel().setManeuverDist(0.);
287
vehicle->getLaneChangeModel().updateTargetLane();
288
if (updatedSpeedLat) {
289
// update angle after having reset lateral speed
290
vehicle->setAngle(vehicle->computeAngle());
291
}
292
}
293
294
295
MSLaneChangerSublane::StateAndDist
296
MSLaneChangerSublane::checkChangeHelper(MSVehicle* vehicle, int laneOffset, LaneChangeAction alternatives) {
297
StateAndDist result = StateAndDist(0, 0, 0, 0);
298
if (mayChange(laneOffset)) {
299
if (laneOffset != 0 && vehicle->getLaneChangeModel().isOpposite()) {
300
return result;
301
}
302
const std::vector<MSVehicle::LaneQ>& preb = (vehicle->getLaneChangeModel().isOpposite()
303
? getBestLanesOpposite(vehicle, nullptr, 1000)
304
: vehicle->getBestLanes());
305
result.state = checkChangeSublane(laneOffset, alternatives, preb, result.latDist, result.maneuverDist);
306
result.dir = laneOffset;
307
if ((result.state & LCA_WANTS_LANECHANGE) != 0 && (result.state & LCA_URGENT) != 0 && (result.state & LCA_BLOCKED) != 0) {
308
(myCandi + laneOffset)->lastBlocked = vehicle;
309
if ((myCandi + laneOffset)->firstBlocked == nullptr) {
310
(myCandi + laneOffset)->firstBlocked = vehicle;
311
}
312
}
313
}
314
return result;
315
}
316
317
318
/// @brief Continue a sublane-lane change maneuver and return whether the midpoint was passed in this step
319
// (used to continue sublane changing in non-action steps).
320
bool
321
MSLaneChangerSublane::continueChangeSublane(MSVehicle* vehicle, ChangerIt& from) {
322
// lateral distance to complete maneuver
323
double remLatDist = vehicle->getLaneChangeModel().getManeuverDist();
324
if (remLatDist == 0) {
325
return false;
326
}
327
const bool urgent = (vehicle->getLaneChangeModel().getOwnState() & LCA_URGENT) != 0;
328
const double nextLatDist = SPEED2DIST(vehicle->getLaneChangeModel().computeSpeedLat(remLatDist, remLatDist, urgent));
329
#ifdef DEBUG_MANEUVER
330
if (DEBUG_COND) {
331
std::cout << SIMTIME << " vehicle '" << vehicle->getID() << "' continueChangeSublane()"
332
<< " remLatDist=" << remLatDist << " nextLatDist=" << nextLatDist
333
<< std::endl;
334
}
335
#endif
336
337
const bool changed = startChangeSublane(vehicle, from, nextLatDist, remLatDist);
338
return changed;
339
}
340
341
342
bool
343
MSLaneChangerSublane::startChangeSublane(MSVehicle* vehicle, ChangerIt& from, double latDist, double maneuverDist) {
344
if (vehicle->isRemoteControlled()) {
345
return false;
346
}
347
MSLane* source = from->lane;
348
// Prevent continuation of LC beyond lane borders if change is not allowed
349
double distToRightLaneBorder = vehicle->getLane()->getWidth() * 0.5 + vehicle->getLateralPositionOnLane() - vehicle->getWidth() * 0.5;
350
double distToLeftLaneBorder = vehicle->getLane()->getWidth() * 0.5 - vehicle->getLateralPositionOnLane() - vehicle->getWidth() * 0.5;
351
if (vehicle->getLaneChangeModel().isOpposite()) {
352
std::swap(distToRightLaneBorder, distToLeftLaneBorder);
353
}
354
// determine direction of LC
355
int direction = 0;
356
if (latDist > 0 && latDist > distToLeftLaneBorder) {
357
direction = 1;
358
} else if (latDist < 0 && -latDist > distToRightLaneBorder) {
359
direction = -1;
360
}
361
const int changerDirection = vehicle->getLaneChangeModel().isOpposite() ? -direction : direction;
362
ChangerIt to = from;
363
#ifdef DEBUG_MANEUVER
364
if (DEBUG_COND) {
365
std::cout << SIMTIME << " vehicle '" << vehicle->getID() << "' latDist=" << latDist << " maneuverDist=" << maneuverDist
366
<< " distRight=" << distToRightLaneBorder << " distLeft=" << distToLeftLaneBorder
367
<< " dir=" << direction << " cDir=" << changerDirection << " mayChange=" << mayChange(changerDirection) << "\n";
368
}
369
#endif
370
if (mayChange(changerDirection)) {
371
to = from + changerDirection;
372
} else if (changerDirection == 1 && source->getOpposite() != nullptr) {
373
// change to the opposite direction lane
374
to = (source->getOpposite()->getEdge().myLaneChanger->getChanger().end() - 1);
375
} else {
376
// This may occur during maneuver continuation in non-actionsteps.
377
// TODO: Understand better why and test later if additional sublane actionstep debugging resolves this
378
// (XXX: perhaps one should try to extrapolate check for this case before to avoid maneuver initialization
379
// similar as for continuous LC in MSLaneChanger::checkChange())
380
//assert(false);
381
abortLCManeuver(vehicle);
382
return false;
383
}
384
385
// The following does:
386
// 1) update vehicles lateral position according to latDist and target lane
387
// 2) distinguish several cases
388
// a) vehicle moves completely within the same lane
389
// b) vehicle intersects another lane
390
// - vehicle must be moved to the lane where its midpoint is (either old or new)
391
// - shadow vehicle must be created/moved to the other lane if the vehicle intersects it
392
// 3) updated dens of all lanes that hold the vehicle or its shadow
393
394
vehicle->myState.myPosLat += latDist * (vehicle->getLaneChangeModel().isOpposite() ? -1 : 1);
395
for (int i = 0; i < (int)vehicle->myFurtherLanesPosLat.size(); i++) {
396
vehicle->myFurtherLanesPosLat[i] += latDist * (vehicle->getLaneChangeModel().isOpposite() ? -1 : 1);
397
}
398
vehicle->myCachedPosition = Position::INVALID;
399
vehicle->getLaneChangeModel().setSpeedLat(DIST2SPEED(latDist));
400
#ifdef DEBUG_MANEUVER
401
if (DEBUG_COND) {
402
std::cout << SIMTIME << " vehicle '" << vehicle->getID() << "' with maneuverDist=" << maneuverDist
403
<< " and committedSpeed=" << vehicle->getLaneChangeModel().getCommittedSpeed()
404
<< " increments lateral position by latDist=" << latDist << std::endl;
405
}
406
#endif
407
#ifdef DEBUG_SURROUNDING
408
if (DEBUG_COND) {
409
std::cout << SIMTIME << " vehicle '" << vehicle->getID() << "'\n to->ahead=" << to->ahead.toString()
410
<< "'\n to->aheadNext=" << to->aheadNext.toString()
411
<< std::endl;
412
}
413
#endif
414
const bool completedPriorManeuver = fabs(vehicle->getLaneChangeModel().getPreviousManeuverDist()) < NUMERICAL_EPS;
415
const bool completedManeuver = fabs(maneuverDist - latDist) < NUMERICAL_EPS;
416
vehicle->getLaneChangeModel().updateSafeLatDist(latDist);
417
418
// current maneuver is aborted when direction or reason changes
419
const int priorReason = vehicle->getLaneChangeModel().getPrevState() & LCA_CHANGE_REASONS & ~LCA_SUBLANE;
420
const int reason = vehicle->getLaneChangeModel().getOwnState() & LCA_CHANGE_REASONS & ~LCA_SUBLANE;
421
#ifdef DEBUG_MANEUVER
422
if (DEBUG_COND) {
423
std::cout << SIMTIME << " vehicle '" << vehicle->getID()
424
<< "' completedPriorManeuver=" << completedPriorManeuver
425
<< " completedManeuver=" << completedManeuver
426
<< " priorReason=" << toString((LaneChangeAction)priorReason)
427
<< " reason=" << toString((LaneChangeAction)reason)
428
<< " priorManeuverDist=" << vehicle->getLaneChangeModel().getPreviousManeuverDist()
429
<< " maneuverDist=" << maneuverDist
430
<< " latDist=" << latDist
431
<< std::endl;
432
}
433
#endif
434
if (!completedManeuver && !completedPriorManeuver && priorReason != 0 &&
435
(vehicle->getLaneChangeModel().getPreviousManeuverDist() * latDist < 0
436
|| priorReason != reason)) {
437
const int priorDirection = vehicle->getLaneChangeModel().getPreviousManeuverDist() > 0 ? 1 : -1;
438
// original from cannot be reconstructed
439
#ifdef DEBUG_MANEUVER
440
if (DEBUG_COND) {
441
std::cout << SIMTIME << " startChangeSublane abort priorReason=" << toString((LaneChangeAction)priorReason)
442
<< " reason=" << toString((LaneChangeAction)reason) << " veh=" << vehicle->getID() << "\n";
443
}
444
#endif
445
outputLCEnded(vehicle, from, from, priorDirection);
446
}
447
448
outputLCStarted(vehicle, from, to, direction, maneuverDist);
449
vehicle->getLaneChangeModel().setManeuverDist(maneuverDist - latDist);
450
const bool changedToNewLane = checkChangeToNewLane(vehicle, direction, from, to);
451
452
MSLane* oldShadowLane = vehicle->getLaneChangeModel().getShadowLane();
453
vehicle->getLaneChangeModel().updateShadowLane();
454
MSLane* shadowLane = vehicle->getLaneChangeModel().getShadowLane();
455
if (shadowLane != nullptr && shadowLane != oldShadowLane
456
&& &shadowLane->getEdge() == &source->getEdge()) {
457
assert(oldShadowLane == 0 || vehicle->getLaneChangeModel().isOpposite() || to != from);
458
const double latOffset = vehicle->getLane()->getRightSideOnEdge() - shadowLane->getRightSideOnEdge();
459
(myChanger.begin() + shadowLane->getIndex())->ahead.addLeader(vehicle, false, latOffset);
460
}
461
if (completedManeuver) {
462
outputLCEnded(vehicle, from, to, direction);
463
}
464
465
// Update maneuver reservations on target lanes
466
MSLane* targetLane = vehicle->getLaneChangeModel().updateTargetLane();
467
if (!changedToNewLane && targetLane != nullptr
468
&& vehicle->getActionStepLength() > DELTA_T
469
&& &targetLane->getEdge() == &source->getEdge()
470
) {
471
const int dir = (vehicle->getLaneChangeModel().getManeuverDist() > 0 ? 1 : -1);
472
ChangerIt target = from + dir;
473
const double actionStepDist = dir * vehicle->getVehicleType().getMaxSpeedLat() * vehicle->getActionStepLengthSecs();
474
const double latOffset = vehicle->getLatOffset(targetLane) + actionStepDist;
475
target->ahead.addLeader(vehicle, false, latOffset);
476
//std::cout << SIMTIME << " veh=" << vehicle->getID() << " target=" << targetLane->getID()
477
// << " actionStepDist=" << actionStepDist << " latOffset=" << latOffset
478
// << " targetAhead=" << target->ahead.toString() << "\n";
479
}
480
481
// compute new angle of the vehicle from the x- and y-distances travelled within last time step
482
// (should happen last because primaryLaneChanged() also triggers angle computation)
483
// this part of the angle comes from the orientation of our current lane
484
double laneAngle = vehicle->computeAngle();
485
if (vehicle->getLaneChangeModel().isOpposite()) {
486
// reverse lane angle
487
laneAngle += M_PI;
488
}
489
#ifdef DEBUG_MANEUVER
490
if (DEBUG_COND) {
491
std::cout << SIMTIME << " startChangeSublane"
492
<< " oldLane=" << from->lane->getID()
493
<< " newLane=" << to->lane->getID()
494
<< " shadowLane=" << (shadowLane != nullptr ? shadowLane->getID() : "NULL")
495
<< " targetLane=" << (targetLane != nullptr ? targetLane->getID() : "NULL")
496
<< " maneuverDist=" << vehicle->getLaneChangeModel().getManeuverDist()
497
<< " latDist=" << latDist
498
<< " oldShadowLane=" << Named::getIDSecure(oldShadowLane)
499
<< " newShadowLane=" << Named::getIDSecure(vehicle->getLaneChangeModel().getShadowLane())
500
<< " laneA=" << RAD2DEG(laneAngle)
501
<< " oldA=" << RAD2DEG(vehicle->getAngle())
502
<< " oppposite=" << vehicle->getLaneChangeModel().isOpposite()
503
<< " changedToNewLane=" << changedToNewLane
504
<< "\n";
505
}
506
#endif
507
vehicle->setAngle(laneAngle, completedManeuver);
508
509
// check if a traci maneuver must continue
510
// getOwnState is reset to 0 when changing lanes so we use the stored reason
511
if ((reason & LCA_TRACI) != 0) {
512
#ifdef DEBUG_MANEUVER
513
if (DEBUG_COND) {
514
std::cout << SIMTIME << " continue TraCI-maneuver remainingLatDist=" << vehicle->getLaneChangeModel().getManeuverDist() << "\n";
515
}
516
#endif
517
vehicle->getInfluencer().setSublaneChange(vehicle->getLaneChangeModel().getManeuverDist());
518
}
519
from->lane->requireCollisionCheck();
520
to->lane->requireCollisionCheck();
521
return changedToNewLane;
522
}
523
524
bool
525
MSLaneChangerSublane::checkChangeToNewLane(MSVehicle* vehicle, const int direction, ChangerIt from, ChangerIt to) {
526
const int oppositeSign = vehicle->getLaneChangeModel().isOpposite() ? -1 : 1;
527
const bool opposite = (&from->lane->getEdge() != &to->lane->getEdge());
528
const bool changedToNewLane = (to->lane != from->lane
529
&& fabs(vehicle->getLateralPositionOnLane()) > 0.5 * vehicle->getLane()->getWidth()
530
&& (mayChange(direction * oppositeSign) || opposite));
531
if (changedToNewLane) {
532
vehicle->myState.myPosLat -= direction * 0.5 * (from->lane->getWidth() + to->lane->getWidth()) * oppositeSign;
533
if (!opposite) {
534
to->lane->myTmpVehicles.insert(to->lane->myTmpVehicles.begin(), vehicle);
535
to->dens += vehicle->getVehicleType().getLengthWithGap();
536
}
537
if (MSAbstractLaneChangeModel::haveLCOutput()) {
538
if (!vehicle->isActive()) {
539
// update leaders beyond the current edge for all lanes
540
// @note to->aheadNext and from->aheadNext are only needed for output in non-action steps.
541
to->aheadNext = getLeaders(to, vehicle);
542
from->aheadNext = getLeaders(from, vehicle);
543
}
544
vehicle->getLaneChangeModel().setLeaderGaps(to->aheadNext);
545
vehicle->getLaneChangeModel().setFollowerGaps(to->lane->getFollowersOnConsecutive(vehicle, vehicle->getBackPositionOnLane(), true));
546
vehicle->getLaneChangeModel().setOrigLeaderGaps(from->aheadNext);
547
}
548
vehicle->getLaneChangeModel().startLaneChangeManeuver(from->lane, to->lane, direction);
549
if (!opposite) {
550
to->ahead.addLeader(vehicle, false, 0);
551
}
552
} else {
553
from->ahead.addLeader(vehicle, false, 0);
554
}
555
return changedToNewLane;
556
}
557
558
void
559
MSLaneChangerSublane::outputLCStarted(MSVehicle* vehicle, ChangerIt& from, ChangerIt& to, int direction, double maneuverDist) {
560
if (MSAbstractLaneChangeModel::haveLCOutput() && MSAbstractLaneChangeModel::outputLCStarted()
561
// non-sublane change started
562
&& ((vehicle->getLaneChangeModel().getOwnState() & (LCA_CHANGE_REASONS & ~LCA_SUBLANE)) != 0)
563
&& ((vehicle->getLaneChangeModel().getOwnState() & LCA_STAY) == 0)
564
// no changing for the same reason in previous step (either not wanted or blocked)
565
&& ((vehicle->getLaneChangeModel().getPrevState() & LCA_CHANGE_REASONS & ~LCA_SUBLANE) !=
566
(vehicle->getLaneChangeModel().getOwnState() & LCA_CHANGE_REASONS & ~LCA_SUBLANE)
567
|| ((vehicle->getLaneChangeModel().getPrevState() & LCA_STAY) != 0)
568
|| ((vehicle->getLaneChangeModel().getPrevState() & LCA_BLOCKED) != 0))
569
) {
570
#ifdef DEBUG_STATE
571
if (DEBUG_COND) {
572
std::cout << SIMTIME << " veh=" << vehicle->getID() << " laneChangeStarted state=" << toString((LaneChangeAction)vehicle->getLaneChangeModel().getOwnState())
573
<< " prevState=" << toString((LaneChangeAction)vehicle->getLaneChangeModel().getPrevState())
574
<< " filter=" << toString((LaneChangeAction)(LCA_CHANGE_REASONS & ~LCA_SUBLANE))
575
<< " filtered=" << toString((LaneChangeAction)(vehicle->getLaneChangeModel().getOwnState() & (LCA_CHANGE_REASONS & ~LCA_SUBLANE)))
576
<< "\n";
577
}
578
#endif
579
vehicle->getLaneChangeModel().setLeaderGaps(to->aheadNext);
580
vehicle->getLaneChangeModel().setFollowerGaps(to->lane->getFollowersOnConsecutive(vehicle, vehicle->getBackPositionOnLane(), true));
581
vehicle->getLaneChangeModel().setOrigLeaderGaps(from->aheadNext);
582
vehicle->getLaneChangeModel().laneChangeOutput("changeStarted", from->lane, to->lane, direction, maneuverDist);
583
}
584
}
585
586
void
587
MSLaneChangerSublane::outputLCEnded(MSVehicle* vehicle, ChangerIt& from, ChangerIt& to, int direction) {
588
if (MSAbstractLaneChangeModel::haveLCOutput() && MSAbstractLaneChangeModel::outputLCEnded()
589
// non-sublane change ended
590
&& ((vehicle->getLaneChangeModel().getOwnState() & (LCA_CHANGE_REASONS & ~LCA_SUBLANE)) != 0)) {
591
vehicle->getLaneChangeModel().setLeaderGaps(to->aheadNext);
592
vehicle->getLaneChangeModel().setFollowerGaps(to->lane->getFollowersOnConsecutive(vehicle, vehicle->getBackPositionOnLane(), true));
593
vehicle->getLaneChangeModel().setOrigLeaderGaps(from->aheadNext);
594
vehicle->getLaneChangeModel().laneChangeOutput("changeEnded", from->lane, to->lane, direction);
595
}
596
}
597
598
599
MSLeaderDistanceInfo
600
MSLaneChangerSublane::getLeaders(const ChangerIt& target, const MSVehicle* vehicle) const {
601
// get the leading vehicle on the lane to change to
602
#ifdef DEBUG_SURROUNDING
603
if (DEBUG_COND) {
604
std::cout << SIMTIME << " getLeaders lane=" << target->lane->getID() << " ego=" << vehicle->getID() << " ahead=" << target->ahead.toString() << "\n";
605
}
606
#endif
607
MSLeaderDistanceInfo result(target->lane->getWidth(), nullptr, 0);
608
int sublaneShift = 0;
609
if (target->lane == vehicle->getLane()) {
610
if (vehicle->getLeftSideOnLane() < -MSGlobals::gLateralResolution) {
611
sublaneShift = int(-vehicle->getLeftSideOnLane() / MSGlobals::gLateralResolution);
612
} else if (vehicle->getRightSideOnLane() > target->lane->getWidth() + MSGlobals::gLateralResolution) {
613
sublaneShift = -int((vehicle->getRightSideOnLane() - target->lane->getWidth()) / MSGlobals::gLateralResolution);
614
}
615
result.setSublaneOffset(sublaneShift);
616
}
617
for (int i = 0; i < target->ahead.numSublanes(); ++i) {
618
const MSVehicle* veh = target->ahead[i];
619
if (veh != nullptr) {
620
const double gap = veh->getBackPositionOnLane(target->lane) - vehicle->getPositionOnLane() - vehicle->getVehicleType().getMinGap();
621
#ifdef DEBUG_SURROUNDING
622
if (DEBUG_COND) {
623
std::cout << " ahead lead=" << veh->getID() << " leadBack=" << veh->getBackPositionOnLane() << " gap=" << gap << " sublaneShift=" << sublaneShift << "\n";
624
}
625
#endif
626
if (i + sublaneShift >= 0 && i + sublaneShift < result.numSublanes()) {
627
result.addLeader(veh, gap, 0, i + sublaneShift);
628
}
629
}
630
}
631
if (sublaneShift != 0) {
632
for (MSVehicle* cand : target->outsideBounds) {
633
const double gap = cand->getBackPositionOnLane() - vehicle->getPositionOnLane() - vehicle->getVehicleType().getMinGap();
634
result.addLeader(cand, gap);
635
}
636
}
637
#ifdef DEBUG_SURROUNDING
638
if (DEBUG_COND) {
639
std::cout << " outsideBounds=" << toString(target->outsideBounds) << " result=" << result.toString() << "\n";
640
}
641
#endif
642
// @note use the exact same vehiclePos as in getLastVehicleInformation() to avoid missing vehicles
643
target->lane->addLeaders(vehicle, vehicle->getPositionOnLane(vehicle->getLane()), result);
644
return result;
645
}
646
647
648
int
649
MSLaneChangerSublane::checkChangeSublane(
650
int laneOffset,
651
LaneChangeAction alternatives,
652
const std::vector<MSVehicle::LaneQ>& preb,
653
double& latDist,
654
double& maneuverDist) const {
655
656
ChangerIt target = myCandi + laneOffset;
657
MSVehicle* vehicle = veh(myCandi);
658
const MSLane& neighLane = *(target->lane);
659
int blocked = 0;
660
661
MSLeaderDistanceInfo neighLeaders = target->aheadNext;
662
MSLeaderDistanceInfo neighFollowers = target->lane->getFollowersOnConsecutive(vehicle, vehicle->getBackPositionOnLane(), true);
663
MSLeaderDistanceInfo neighBlockers(neighLane.getWidth(), vehicle, vehicle->getLane()->getRightSideOnEdge() - neighLane.getRightSideOnEdge());
664
MSLeaderDistanceInfo leaders = myCandi->aheadNext;
665
addOutsideLeaders(vehicle, leaders);
666
MSLeaderDistanceInfo followers = myCandi->lane->getFollowersOnConsecutive(vehicle, vehicle->getBackPositionOnLane(), true);
667
MSLeaderDistanceInfo blockers(vehicle->getLane()->getWidth(), vehicle, 0);
668
669
// consider sibling lanes of the origin and target lane
670
for (int offset : myCandi->siblings) {
671
// treat sibling lanes (internal lanes with the same origin lane) as if they have the same geometry
672
ChangerIt ceSib = myCandi + offset;
673
MSLeaderDistanceInfo sibFollowers = ceSib->lane->getFollowersOnConsecutive(vehicle, vehicle->getBackPositionOnLane(), true);
674
if (sibFollowers.hasVehicles()) {
675
followers.addLeaders(sibFollowers);
676
}
677
if (ceSib->aheadNext.hasVehicles()) {
678
leaders.addLeaders(ceSib->aheadNext);
679
}
680
#ifdef DEBUG_SURROUNDING
681
if (DEBUG_COND) {
682
std::cout << SIMTIME << " ego=" << vehicle->getID() << " ahead=" << myCandi->aheadNext.toString() << " sib=" << ceSib->lane->getID() << " sibAhead=" << ceSib->aheadNext.toString() << " leaders=" << leaders.toString() << "\n";
683
}
684
#endif
685
}
686
for (int offset : target->siblings) {
687
// treat sibling lanes (internal lanes with the same origin lane) as if they have the same geometry
688
ChangerIt ceSib = target + offset;
689
MSLeaderDistanceInfo sibFollowers = ceSib->lane->getFollowersOnConsecutive(vehicle, vehicle->getBackPositionOnLane(), true);
690
if (sibFollowers.hasVehicles()) {
691
neighFollowers.addLeaders(sibFollowers);
692
}
693
if (ceSib->aheadNext.hasVehicles()) {
694
neighLeaders.addLeaders(ceSib->aheadNext);
695
}
696
#ifdef DEBUG_SURROUNDING
697
if (DEBUG_COND) {
698
std::cout << SIMTIME << " ego=" << vehicle->getID() << " neighAhead=" << target->aheadNext.toString() << " sib=" << ceSib->lane->getID() << " sibAhead=" << ceSib->aheadNext.toString() << " neighLeaders=" << neighLeaders.toString() << "\n";
699
}
700
#endif
701
}
702
703
// break leader symmetry
704
if (laneOffset == -1 && neighLeaders.hasVehicles()) {
705
neighLeaders.moveSamePosTo(vehicle, neighFollowers);
706
}
707
708
#ifdef DEBUG_SURROUNDING
709
if (DEBUG_COND) std::cout << SIMTIME
710
<< " checkChangeSublane: veh=" << vehicle->getID()
711
<< " laneOffset=" << laneOffset
712
<< "\n leaders=" << leaders.toString()
713
<< "\n neighLeaders=" << neighLeaders.toString()
714
<< "\n followers=" << followers.toString()
715
<< "\n neighFollowers=" << neighFollowers.toString()
716
<< "\n";
717
#endif
718
719
720
const int wish = vehicle->getLaneChangeModel().wantsChangeSublane(
721
laneOffset, alternatives,
722
leaders, followers, blockers,
723
neighLeaders, neighFollowers, neighBlockers,
724
neighLane, preb,
725
&(myCandi->lastBlocked), &(myCandi->firstBlocked), latDist, maneuverDist, blocked);
726
727
728
if (checkOpened && (blocked & LCA_BLOCKED) == 0 && (wish & LCA_WANTS_LANECHANGE) != 0
729
&& vehicle->getLane()->isNormal()
730
&& vehicle->getBestLanesContinuation().size() > 1) {
731
const MSLink* link = vehicle->getLane()->getLinkTo(vehicle->getBestLanesContinuation()[1]);
732
if (link != nullptr && link->isEntryLink()) {
733
const MSLink* link2 = link->getParallelLink(laneOffset);
734
if (link2 != nullptr) {
735
auto api = link->getApproachingPtr(vehicle);
736
if (api != nullptr) {
737
if (!link2->opened(api->arrivalTime, api->arrivalSpeed, api->leaveSpeed, vehicle->getLength(),
738
vehicle->getImpatience(), vehicle->getCarFollowModel().getMaxDecel(), vehicle->getWaitingTime(), vehicle->getLateralPositionOnLane(),
739
nullptr, false, vehicle, api->dist)) {
740
//std::cout << SIMTIME << " unsafeLC " << vehicle->getID() << "\n";
741
blocked |= LCA_BLOCKED;
742
}
743
}
744
}
745
}
746
}
747
748
int state = blocked | wish;
749
750
// XXX
751
// do are more careful (but expensive) check to ensure that a
752
// safety-critical leader is not being overlooked
753
754
// let TraCI influence the wish to change lanes and the security to take
755
const int oldstate = state;
756
state = vehicle->influenceChangeDecision(state);
757
#ifdef DEBUG_STATE
758
if (DEBUG_COND && state != oldstate) {
759
std::cout << SIMTIME << " veh=" << vehicle->getID() << " stateAfterTraCI=" << toString((LaneChangeAction)state) << " original=" << toString((LaneChangeAction)oldstate) << "\n";
760
}
761
#endif
762
vehicle->getLaneChangeModel().getCanceledState(laneOffset) |= blocked;
763
vehicle->getLaneChangeModel().saveLCState(laneOffset, oldstate, state);
764
if (laneOffset != 0) {
765
vehicle->getLaneChangeModel().saveNeighbors(laneOffset, neighFollowers, neighLeaders);
766
}
767
return state;
768
}
769
770
771
bool
772
MSLaneChangerSublane::checkChangeOpposite(
773
MSVehicle* vehicle,
774
int laneOffset,
775
MSLane* targetLane,
776
const std::pair<MSVehicle* const, double>& leader,
777
const std::pair<MSVehicle* const, double>& neighLead,
778
const std::pair<MSVehicle* const, double>& neighFollow,
779
const std::vector<MSVehicle::LaneQ>& preb) {
780
myCheckedChangeOpposite = true;
781
782
UNUSED_PARAMETER(leader);
783
UNUSED_PARAMETER(neighLead);
784
UNUSED_PARAMETER(neighFollow);
785
786
const MSLane& neighLane = *targetLane;
787
MSLane* curLane = myCandi->lane;
788
789
MSLeaderDistanceInfo neighLeaders(targetLane->getWidth(), nullptr, 0);
790
MSLeaderDistanceInfo neighFollowers(targetLane->getWidth(), nullptr, 0);
791
MSLeaderDistanceInfo neighBlockers(targetLane->getWidth(), nullptr, 0);
792
MSLeaderDistanceInfo leaders(curLane->getWidth(), nullptr, 0);
793
MSLeaderDistanceInfo followers(curLane->getWidth(), nullptr, 0);
794
MSLeaderDistanceInfo blockers(curLane->getWidth(), nullptr, 0);
795
796
const double backPosOnTarget = vehicle->getLane()->getOppositePos(vehicle->getBackPositionOnLane());
797
if (vehicle->getLaneChangeModel().isOpposite()) {
798
leaders = curLane->getFollowersOnConsecutive(vehicle, vehicle->getPositionOnLane(), true, -1, MSLane::MinorLinkMode::FOLLOW_ONCOMING);
799
leaders.fixOppositeGaps(false);
800
curLane->addLeaders(vehicle, vehicle->getBackPositionOnLane(), followers);
801
followers.fixOppositeGaps(true);
802
neighFollowers = targetLane->getFollowersOnConsecutive(vehicle, backPosOnTarget, true);
803
neighFollowers.fixOppositeGaps(false);
804
// artificially increase the position to ensure that ego is not added as a leader
805
const double posOnTarget = backPosOnTarget + vehicle->getVehicleType().getLength() + POSITION_EPS;
806
targetLane->addLeaders(vehicle, posOnTarget, neighLeaders);
807
neighLeaders.patchGaps(2 * POSITION_EPS);
808
int sublaneIndex = 0;
809
for (int i = 0; i < targetLane->getIndex(); i++) {
810
sublaneIndex += MSLeaderInfo(targetLane->getEdge().getLanes()[i]->getWidth()).numSublanes();
811
}
812
vehicle->getLaneChangeModel().updateExpectedSublaneSpeeds(neighLeaders, sublaneIndex, targetLane->getIndex());
813
} else {
814
leaders = myCandi->aheadNext;
815
followers = myCandi->lane->getFollowersOnConsecutive(vehicle, vehicle->getBackPositionOnLane(), true);
816
const double posOnTarget = backPosOnTarget - vehicle->getVehicleType().getLength();
817
targetLane->addLeaders(vehicle, backPosOnTarget, neighFollowers, true);
818
neighFollowers.fixOppositeGaps(true);
819
neighLeaders = targetLane->getFollowersOnConsecutive(vehicle, posOnTarget, true);
820
neighLeaders.fixOppositeGaps(false);
821
}
822
823
824
#ifdef DEBUG_CHANGE_OPPOSITE
825
if (DEBUG_COND) std::cout << SIMTIME
826
<< " checkChangeOppositeSublane: veh=" << vehicle->getID()
827
<< " isOpposite=" << vehicle->getLaneChangeModel().isOpposite()
828
<< " laneOffset=" << laneOffset
829
<< "\n leaders=" << leaders.toString()
830
<< "\n neighLeaders=" << neighLeaders.toString()
831
<< "\n followers=" << followers.toString()
832
<< "\n neighFollowers=" << neighFollowers.toString()
833
<< "\n";
834
#endif
835
836
LaneChangeAction alternatives = (LaneChangeAction)((mayChange(-1) ? LCA_RIGHT : LCA_NONE)
837
| (mayChange(1) ? LCA_LEFT : LCA_NONE));
838
839
int blocked = 0;
840
double latDist = 0;
841
double maneuverDist = 0;
842
const int wish = vehicle->getLaneChangeModel().wantsChangeSublane(
843
laneOffset, alternatives,
844
leaders, followers, blockers,
845
neighLeaders, neighFollowers, neighBlockers,
846
neighLane, preb,
847
&(myCandi->lastBlocked), &(myCandi->firstBlocked), latDist, maneuverDist, blocked);
848
int state = blocked | wish;
849
850
const int oldstate = state;
851
state = vehicle->influenceChangeDecision(state);
852
#ifdef DEBUG_CHANGE_OPPOSITE
853
if (DEBUG_COND && state != oldstate) {
854
std::cout << SIMTIME << " veh=" << vehicle->getID() << " stateAfterTraCI=" << toString((LaneChangeAction)state) << " original=" << toString((LaneChangeAction)oldstate) << "\n";
855
}
856
#endif
857
vehicle->getLaneChangeModel().saveLCState(laneOffset, oldstate, state);
858
if (laneOffset != 0) {
859
vehicle->getLaneChangeModel().saveNeighbors(laneOffset, neighFollowers, neighLeaders);
860
}
861
862
if ((state & LCA_WANTS_LANECHANGE) != 0 && (state & LCA_BLOCKED) == 0) {
863
// change if the vehicle wants to and is allowed to change
864
#ifdef DEBUG_CHANGE_OPPOSITE
865
if (DEBUG_COND) {
866
std::cout << SIMTIME << " veh '" << vehicle->getID() << "' performing sublane change latDist=" << latDist << " maneuverDist=" << maneuverDist << "\n";
867
}
868
#endif
869
vehicle->getLaneChangeModel().setOwnState(state);
870
return startChangeSublane(vehicle, myCandi, latDist, maneuverDist);
871
} else {
872
vehicle->getLaneChangeModel().setSpeedLat(0);
873
return false;
874
}
875
}
876
877
std::pair<MSVehicle*, double>
878
MSLaneChangerSublane::findClosestLeader(const MSLeaderDistanceInfo& leaders, const MSVehicle* vehicle) {
879
const double egoWidth = vehicle->getVehicleType().getWidth() + vehicle->getVehicleType().getMinGapLat();
880
std::pair<MSVehicle*, double> leader(nullptr, std::numeric_limits<double>::max());
881
for (int i = 0; i < leaders.numSublanes(); ++i) {
882
CLeaderDist cand = leaders[i];
883
if (cand.first != nullptr) {
884
double rightSide = cand.first->getRightSideOnLane();
885
if (cand.first->getLane() != vehicle->getLane()) {
886
// the candidate may be a parial (sideways) occupier so getRightSideOnLane() cannot be used
887
rightSide += (cand.first->getCenterOnEdge(cand.first->getLane())
888
- vehicle->getCenterOnEdge(vehicle->getLane()));
889
}
890
#ifdef DEBUG_CHANGE_OPPOSITE
891
if (vehicle->isSelected()) {
892
std::cout << SIMTIME << " cand=" << cand.first->getID() << " rightSide=" << rightSide << "\n";
893
}
894
#endif
895
if (cand.second < leader.second
896
&& rightSide < egoWidth
897
&& vehicle->getLane()->getWidth() - rightSide - cand.first->getVehicleType().getWidth() < egoWidth) {
898
leader.first = const_cast<MSVehicle*>(cand.first);
899
leader.second = cand.second;
900
}
901
}
902
}
903
return leader;
904
}
905
906
907
void
908
MSLaneChangerSublane::addOutsideLeaders(const MSVehicle* vehicle, MSLeaderDistanceInfo& leaders) const {
909
if (vehicle->getLaneChangeModel().getShadowLane() == nullptr) {
910
const MSLane* lane = vehicle->getLane();
911
const double rightOL = vehicle->getRightSideOnLane(lane);
912
const double leftOL = vehicle->getLeftSideOnLane(lane);
913
const bool outsideLeft = rightOL > lane->getWidth();
914
#ifdef DEBUG_SURROUNDING
915
if (DEBUG_COND) {
916
std::cout << SIMTIME << " addOutsideLeaders veh=" << vehicle->getID() << " lane=" << lane->getID() << " rightOL=" << rightOL << " leftOL=" << leftOL << "\n";
917
}
918
#endif
919
if (leftOL < 0 || outsideLeft) {
920
int sublaneOffset = 0;
921
if (outsideLeft) {
922
sublaneOffset = MIN2(0, -(int)ceil((leftOL - lane->getWidth()) / MSGlobals::gLateralResolution) + 1);
923
} else {
924
sublaneOffset = MAX2(0, (int)ceil(-rightOL / MSGlobals::gLateralResolution) - 1);
925
}
926
if (sublaneOffset != 0) {
927
leaders.setSublaneOffset(sublaneOffset);
928
#ifdef DEBUG_SURROUNDING
929
if (DEBUG_COND) {
930
std::cout << " sublaneOffset=" << sublaneOffset << " outsideLeft=" << outsideLeft << "\n";
931
}
932
#endif
933
for (const MSVehicle* cand : lane->myTmpVehicles) {
934
#ifdef DEBUG_SURROUNDING
935
if (DEBUG_COND) {
936
std::cout << " cand=" << cand->getID() << " cLOE=" << cand->getLeftSideOnEdge() << " cROE=" << cand->getRightSideOnEdge() << "\n";
937
}
938
#endif
939
if (cand->getPositionOnLane() > vehicle->getPositionOnLane()
940
&& ((!outsideLeft && cand->getLeftSideOnEdge() < 0)
941
|| (outsideLeft && cand->getLeftSideOnEdge() > lane->getEdge().getWidth()))) {
942
const double gap = cand->getPositionOnLane() - vehicle->getPositionOnLane() - cand->getLength() - vehicle->getVehicleType().getMinGap();
943
leaders.addLeader(cand, gap);
944
#ifdef DEBUG_SURROUNDING
945
if (DEBUG_COND) {
946
std::cout << " outsideLeader=" << cand->getID() << " ahead=" << leaders.toString() << "\n";
947
}
948
#endif
949
}
950
}
951
}
952
}
953
}
954
}
955
956
/****************************************************************************/
957
958