1 /****************************************************************************/
2 // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.org/sumo
3 // Copyright (C) 2002-2019 German Aerospace Center (DLR) and others.
4 // This program and the accompanying materials
5 // are made available under the terms of the Eclipse Public License v2.0
6 // which accompanies this distribution, and is available at
7 // http://www.eclipse.org/legal/epl-v20.html
8 // SPDX-License-Identifier: EPL-2.0
9 /****************************************************************************/
10 /// @file MSLaneChangerSublane.cpp
11 /// @author Jakob Erdmann
12 /// @author Leonhard Luecken
13 /// @date Oct 2015
14 /// @version $Id$
15 ///
16 // Performs sub-lane changing of vehicles
17 /****************************************************************************/
18
19 // ===========================================================================
20 // included modules
21 // ===========================================================================
22 #include <config.h>
23
24 #include "MSLaneChangerSublane.h"
25 #include "MSNet.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_DECISION
45 //#define DEBUG_ACTIONSTEPS
46 //#define DEBUG_STATE
47 //#define DEBUG_MANEUVER
48 //#define DEBUG_SURROUNDING
49
50 // ===========================================================================
51 // member method definitions
52 // ===========================================================================
MSLaneChangerSublane(const std::vector<MSLane * > * lanes,bool allowChanging)53 MSLaneChangerSublane::MSLaneChangerSublane(const std::vector<MSLane*>* lanes, bool allowChanging) :
54 MSLaneChanger(lanes, allowChanging) {
55 // initialize siblings
56 if (myChanger.front().lane->isInternal()) {
57 for (ChangerIt ce = myChanger.begin(); ce != myChanger.end(); ++ce) {
58 for (ChangerIt ce2 = myChanger.begin(); ce2 != myChanger.end(); ++ce2) {
59 if (ce != ce2 && ce->lane->getIncomingLanes().front().lane == ce2->lane->getIncomingLanes().front().lane) {
60 //std::cout << "addSibling lane=" << ce->lane->getID() << " offset=" << ce2->lane->getIndex() - ce->lane->getIndex() << "\n";
61 ce->siblings.push_back(ce2->lane->getIndex() - ce->lane->getIndex());
62 }
63 }
64 }
65 }
66 }
67
68
~MSLaneChangerSublane()69 MSLaneChangerSublane::~MSLaneChangerSublane() {}
70
71 void
initChanger()72 MSLaneChangerSublane::initChanger() {
73 MSLaneChanger::initChanger();
74 // Prepare myChanger with a safe state.
75 for (ChangerIt ce = myChanger.begin(); ce != myChanger.end(); ++ce) {
76 ce->ahead = ce->lane->getPartialBeyond();
77 // std::cout << SIMTIME << " initChanger lane=" << ce->lane->getID() << " vehicles=" << toString(ce->lane->myVehicles) << "\n";
78 // std::cout << SIMTIME << " initChanger lane=" << ce->lane->getID() << " partial vehicles=" << toString(ce->lane->myPartialVehicles) << "\n";
79 // std::cout << SIMTIME << " initChanger lane=" << ce->lane->getID() << " partial vehicles beyond=" << toString(ce->ahead.toString()) << "\n";
80 }
81 }
82
83
84
85 void
updateChanger(bool vehHasChanged)86 MSLaneChangerSublane::updateChanger(bool vehHasChanged) {
87 MSLaneChanger::updateChanger(vehHasChanged);
88 if (!vehHasChanged) {
89 MSVehicle* lead = myCandi->lead;
90 //std::cout << SIMTIME << " updateChanger lane=" << myCandi->lane->getID() << " lead=" << Named::getIDSecure(lead) << "\n";
91 myCandi->ahead.addLeader(lead, false, 0);
92 MSLane* shadowLane = lead->getLaneChangeModel().getShadowLane();
93 if (shadowLane != nullptr) {
94 const double latOffset = lead->getLane()->getRightSideOnEdge() - shadowLane->getRightSideOnEdge();
95 //std::cout << SIMTIME << " updateChanger shadowLane=" << shadowLane->getID() << " lead=" << Named::getIDSecure(lead) << "\n";
96 (myChanger.begin() + shadowLane->getIndex())->ahead.addLeader(lead, false, latOffset);
97 }
98 }
99 //std::cout << SIMTIME << " updateChanger: lane=" << myCandi->lane->getID() << " lead=" << Named::getIDSecure(myCandi->lead) << " ahead=" << myCandi->ahead.toString() << " vehHasChanged=" << vehHasChanged << "\n";
100 //for (ChangerIt ce = myChanger.begin(); ce != myChanger.end(); ++ce) {
101 // std::cout << " lane=" << ce->lane->getID() << " vehicles=" << toString(ce->lane->myVehicles) << "\n";
102 //}
103 }
104
105
106 bool
change()107 MSLaneChangerSublane::change() {
108 // variant of change() for the sublane case
109 myCandi = findCandidate();
110 MSVehicle* vehicle = veh(myCandi);
111 vehicle->getLaneChangeModel().clearNeighbors();
112 #ifdef DEBUG_ACTIONSTEPS
113 if DEBUG_COND {
114 std::cout << "\nCHANGE" << std::endl;
115 }
116 #endif
117 assert(vehicle->getLane() == (*myCandi).lane);
118 assert(!vehicle->getLaneChangeModel().isChangingLanes());
119 if (/*!myAllowsChanging || vehicle->getLaneChangeModel().alreadyChanged() ||*/ vehicle->isStoppedOnLane()) {
120 registerUnchanged(vehicle);
121 return false;
122 }
123 if (!vehicle->isActive()) {
124 #ifdef DEBUG_ACTIONSTEPS
125 if DEBUG_COND {
126 std::cout << SIMTIME << " veh '" << vehicle->getID() << "' skips regular change checks." << std::endl;
127 }
128 #endif
129
130 bool changed;
131 // let TraCI influence the wish to change lanes during non-actionsteps
132 checkTraCICommands(vehicle);
133
134 // Resume change
135 changed = continueChangeSublane(vehicle, myCandi);
136 #ifdef DEBUG_ACTIONSTEPS
137 if DEBUG_COND {
138 std::cout << SIMTIME << " veh '" << vehicle->getID() << "' lcm->maneuverDist=" << vehicle->getLaneChangeModel().getManeuverDist()
139 << " lcm->speedLat=" << vehicle->getLaneChangeModel().getSpeedLat() << std::endl;
140 }
141 #endif
142 return changed;
143 }
144
145 #ifdef DEBUG_ACTIONSTEPS
146 if DEBUG_COND {
147 std::cout << "\n" << SIMTIME << " veh '" << vehicle->getID() << "' at plans sublane maneuver."
148 << std::endl;
149 }
150 #endif
151 vehicle->updateBestLanes(); // needed?
152 for (int i = 0; i < (int) myChanger.size(); ++i) {
153 vehicle->adaptBestLanesOccupation(i, myChanger[i].dens);
154 }
155 // update leaders beyond the current edge for all lanes
156 for (ChangerIt ce = myChanger.begin(); ce != myChanger.end(); ++ce) {
157 ce->aheadNext = getLeaders(ce, vehicle);
158 }
159
160 // update expected speeds
161 int sublaneIndex = 0;
162 for (ChangerIt ce = myChanger.begin(); ce != myChanger.end(); ++ce) {
163 vehicle->getLaneChangeModel().updateExpectedSublaneSpeeds(ce->aheadNext, sublaneIndex, ce->lane->getIndex());
164 for (int offset : ce->siblings) {
165 // treat sibling lanes (internal lanes with the same origin lane) as if they have the same geometry
166 ChangerIt ceSib = ce + offset;
167 vehicle->getLaneChangeModel().updateExpectedSublaneSpeeds(ceSib->aheadNext, sublaneIndex, ceSib->lane->getIndex());
168 }
169 sublaneIndex += ce->ahead.numSublanes();
170 }
171
172 LaneChangeAction alternatives = (LaneChangeAction)((mayChange(-1) ? LCA_RIGHT : LCA_NONE)
173 | (mayChange(1) ? LCA_LEFT : LCA_NONE));
174
175 StateAndDist right = checkChangeHelper(vehicle, -1, alternatives);
176 StateAndDist left = checkChangeHelper(vehicle, 1, alternatives);
177 StateAndDist current = checkChangeHelper(vehicle, 0, alternatives);
178
179 StateAndDist decision = vehicle->getLaneChangeModel().decideDirection(current,
180 vehicle->getLaneChangeModel().decideDirection(right, left));
181 #ifdef DEBUG_DECISION
182 if (vehicle->getLaneChangeModel().debugVehicle()) {
183 std::cout << "\n" << SIMTIME << " decision=" << toString((LaneChangeAction)decision.state) << " dir=" << decision.dir << " latDist=" << decision.latDist << " maneuverDist=" << decision.maneuverDist << "\n";
184 }
185 #endif
186 vehicle->getLaneChangeModel().setOwnState(decision.state);
187 vehicle->getLaneChangeModel().setManeuverDist(decision.maneuverDist);
188 if ((decision.state & LCA_WANTS_LANECHANGE) != 0 && (decision.state & LCA_BLOCKED) == 0) {
189 // change if the vehicle wants to and is allowed to change
190 #ifdef DEBUG_MANEUVER
191 if DEBUG_COND {
192 std::cout << SIMTIME << " veh '" << vehicle->getID() << "' performing sublane change..." << std::endl;
193 }
194 #endif
195 return startChangeSublane(vehicle, myCandi, decision.latDist);
196 }
197 // @note this assumes vehicles can instantly abort any maneuvre in case of emergency
198 abortLCManeuver(vehicle);
199
200 if ((right.state & (LCA_URGENT)) != 0 && (left.state & (LCA_URGENT)) != 0) {
201 // ... wants to go to the left AND to the right
202 // just let them go to the right lane...
203 left.state = 0;
204 }
205 return false;
206 }
207
208
209 void
210 MSLaneChangerSublane::abortLCManeuver(MSVehicle* vehicle) {
211 #ifdef DEBUG_MANEUVER
212 if DEBUG_COND {
213 std::cout << SIMTIME << " veh '" << vehicle->getID() << "' aborts LC-continuation."
214 << std::endl;
215 }
216 #endif
217 vehicle->getLaneChangeModel().setSpeedLat(0);
218 vehicle->getLaneChangeModel().setManeuverDist(0.);
219 registerUnchanged(vehicle);
220 }
221
222
223 MSLaneChangerSublane::StateAndDist
224 MSLaneChangerSublane::checkChangeHelper(MSVehicle* vehicle, int laneOffset, LaneChangeAction alternatives) {
225 StateAndDist result = StateAndDist(0, 0, 0, 0);
226 if (mayChange(laneOffset)) {
227 const std::vector<MSVehicle::LaneQ>& preb = vehicle->getBestLanes();
228 result.state = checkChangeSublane(laneOffset, alternatives, preb, result.latDist, result.maneuverDist);
229 result.dir = laneOffset;
230 if ((result.state & LCA_WANTS_LANECHANGE) != 0 && (result.state & LCA_URGENT) != 0 && (result.state & LCA_BLOCKED) != 0) {
231 (myCandi + laneOffset)->lastBlocked = vehicle;
232 if ((myCandi + laneOffset)->firstBlocked == nullptr) {
233 (myCandi + laneOffset)->firstBlocked = vehicle;
234 }
235 }
236 }
237 return result;
238 }
239
240
241 /// @brief Continue a sublane-lane change maneuver and return whether the midpoint was passed in this step
242 // (used to continue sublane changing in non-action steps).
243 bool
244 MSLaneChangerSublane::continueChangeSublane(MSVehicle* vehicle, ChangerIt& from) {
245 // lateral distance to complete maneuver
246 double remLatDist = vehicle->getLaneChangeModel().getManeuverDist();
247 if (remLatDist == 0) {
248 registerUnchanged(vehicle);
249 return false;
250 }
251 const double nextLatDist = SPEED2DIST(vehicle->getLaneChangeModel().computeSpeedLat(remLatDist, remLatDist));
252 #ifdef DEBUG_MANEUVER
253 if DEBUG_COND {
254 std::cout << SIMTIME << " vehicle '" << vehicle->getID() << "' continueChangeSublane()"
255 << " remLatDist=" << remLatDist << " nextLatDist=" << nextLatDist
256 << std::endl;
257 }
258 #endif
259
260 const bool changed = startChangeSublane(vehicle, from, nextLatDist);
261 return changed;
262 }
263
264
265 bool
266 MSLaneChangerSublane::startChangeSublane(MSVehicle* vehicle, ChangerIt& from, double latDist) {
267 if (vehicle->isRemoteControlled()) {
268 registerUnchanged(vehicle);
269 return false;
270 }
271 // Prevent continuation of LC beyond lane borders if change is not allowed
272 const double distToRightLaneBorder = latDist < 0 ? vehicle->getLane()->getWidth() * 0.5 + vehicle->getLateralPositionOnLane() - vehicle->getWidth() * 0.5 : 0.;
273 const double distToLeftLaneBorder = latDist > 0 ? vehicle->getLane()->getWidth() * 0.5 - vehicle->getLateralPositionOnLane() - vehicle->getWidth() * 0.5 : 0.;
274 // determine direction of LC
275 const int direction = (latDist >= -distToRightLaneBorder && latDist <= distToLeftLaneBorder) ? 0 : (latDist < 0 ? -1 : 1);
276 ChangerIt to = from;
277 if (mayChange(direction)) {
278 to = from + direction;
279 } else {
280 // This may occur during maneuver continuation in non-actionsteps.
281 // TODO: Understand better why and test later if additional sublane actionstep debugging resolves this
282 // (XXX: perhaps one should try to extrapolate check for this case before to avoid maneuver initialization
283 // similar as for continuous LC in MSLaneChanger::checkChange())
284 //assert(false);
285 abortLCManeuver(vehicle);
286 return false;
287 }
288
289 // The following does:
290 // 1) update vehicles lateral position according to latDist and target lane
291 // 2) distinguish several cases
292 // a) vehicle moves completely within the same lane
293 // b) vehicle intersects another lane
294 // - vehicle must be moved to the lane where it's midpoint is (either old or new)
295 // - shadow vehicle must be created/moved to the other lane if the vehicle intersects it
296 // 3) updated dens of all lanes that hold the vehicle or its shadow
297
298 vehicle->myState.myPosLat += latDist;
299 vehicle->myCachedPosition = Position::INVALID;
300 vehicle->getLaneChangeModel().setSpeedLat(DIST2SPEED(latDist));
301 #ifdef DEBUG_MANEUVER
302 if DEBUG_COND {
303 std::cout << SIMTIME << " vehicle '" << vehicle->getID() << "' with maneuverDist=" << vehicle->getLaneChangeModel().getManeuverDist()
304 << " and committedSpeed=" << vehicle->getLaneChangeModel().getCommittedSpeed()
305 << " increments lateral position by latDist=" << latDist << std::endl;
306 }
307 #endif
308 #ifdef DEBUG_SURROUNDING
309 if DEBUG_COND {
310 std::cout << SIMTIME << " vehicle '" << vehicle->getID() << "'\n to->ahead=" << to->ahead.toString()
311 << "'\n to->aheadNext=" << to->aheadNext.toString()
312 << std::endl;
313 }
314 #endif
315 const bool completedManeuver = vehicle->getLaneChangeModel().getManeuverDist() - latDist == 0.;
316 vehicle->getLaneChangeModel().updateSafeLatDist(latDist);
317
318 outputLCStarted(vehicle, from, to, direction);
319 vehicle->getLaneChangeModel().setManeuverDist(vehicle->getLaneChangeModel().getManeuverDist() - latDist);
320 const bool changedToNewLane = checkChangeToNewLane(vehicle, direction, from, to);
321
322 MSLane* oldShadowLane = vehicle->getLaneChangeModel().getShadowLane();
323 vehicle->getLaneChangeModel().updateShadowLane();
324 MSLane* shadowLane = vehicle->getLaneChangeModel().getShadowLane();
325 if (shadowLane != nullptr && shadowLane != oldShadowLane) {
326 assert(to != from || oldShadowLane == 0);
327 const double latOffset = vehicle->getLane()->getRightSideOnEdge() - shadowLane->getRightSideOnEdge();
328 (myChanger.begin() + shadowLane->getIndex())->ahead.addLeader(vehicle, false, latOffset);
329 }
330 if (completedManeuver) {
331 outputLCEnded(vehicle, from, to, direction);
332 }
333
334 // Update maneuver reservations on target lanes
335 MSLane* targetLane = vehicle->getLaneChangeModel().updateTargetLane();
336 if (!changedToNewLane && targetLane != nullptr
337 && vehicle->getActionStepLength() > DELTA_T) {
338 const int dir = (vehicle->getLaneChangeModel().getManeuverDist() > 0 ? 1 : -1);
339 ChangerIt target = from + dir;
340 const double actionStepDist = dir * vehicle->getVehicleType().getMaxSpeedLat() * vehicle->getActionStepLengthSecs();
341 const double latOffset = vehicle->getLatOffset(targetLane) + actionStepDist;
342 target->ahead.addLeader(vehicle, false, latOffset);
343 //std::cout << SIMTIME << " veh=" << vehicle->getID() << " target=" << targetLane->getID()
344 // << " actionStepDist=" << actionStepDist << " latOffset=" << latOffset
345 // << " targetAhead=" << target->ahead.toString() << "\n";
346 }
347
348 // compute new angle of the vehicle from the x- and y-distances travelled within last time step
349 // (should happen last because primaryLaneChanged() also triggers angle computation)
350 // this part of the angle comes from the orientation of our current lane
351 double laneAngle = vehicle->getLane()->getShape().rotationAtOffset(vehicle->getLane()->interpolateLanePosToGeometryPos(vehicle->getPositionOnLane())) ;
352 if (vehicle->getLane()->getShape().length2D() == 0) {
353 if (vehicle->getFurtherLanes().size() == 0) {
354 laneAngle = vehicle->getAngle();
355 } else {
356 laneAngle = vehicle->getFurtherLanes().front()->getShape().rotationAtOffset(-NUMERICAL_EPS);
357 }
358 }
359 // this part of the angle comes from the vehicle's lateral movement
360 double changeAngle = 0;
361 // avoid flicker
362 if (fabs(latDist) > NUMERICAL_EPS) {
363 // angle is between vehicle front and vehicle back (and depending on travelled distance)
364 changeAngle = atan2(latDist, vehicle->getVehicleType().getLength() + SPEED2DIST(vehicle->getSpeed()));
365 }
366 #ifdef DEBUG_MANEUVER
367 if (vehicle->getLaneChangeModel().debugVehicle()) {
368 std::cout << SIMTIME << " startChangeSublane()"
369 << " shadowLane=" << (shadowLane != nullptr ? shadowLane->getID() : "NULL")
370 << " targetLane=" << (targetLane != nullptr ? targetLane->getID() : "NULL")
371 << " maneuverDist=" << vehicle->getLaneChangeModel().getManeuverDist()
372 << " latDist=" << latDist
373 << " old=" << Named::getIDSecure(oldShadowLane)
374 << " new=" << Named::getIDSecure(vehicle->getLaneChangeModel().getShadowLane())
375 << " laneA=" << RAD2DEG(laneAngle)
376 << " changeA=" << RAD2DEG(changeAngle)
377 << " oldA=" << RAD2DEG(vehicle->getAngle())
378 << " newA=" << RAD2DEG(laneAngle + changeAngle)
379 << "\n";
380 }
381 #endif
382 vehicle->setAngle(laneAngle + changeAngle, completedManeuver);
383
384 // check if a traci maneuver must continue
385 if ((vehicle->getLaneChangeModel().getOwnState() & LCA_TRACI) != 0) {
386 if (vehicle->getLaneChangeModel().debugVehicle()) {
387 std::cout << SIMTIME << " continue TraCI-maneuver remainingLatDist=" << vehicle->getLaneChangeModel().getManeuverDist() << "\n";
388 }
389 vehicle->getInfluencer().setSublaneChange(vehicle->getLaneChangeModel().getManeuverDist());
390 }
391 from->lane->requireCollisionCheck();
392 to->lane->requireCollisionCheck();
393 return changedToNewLane;
394 }
395
396 bool
397 MSLaneChangerSublane::checkChangeToNewLane(MSVehicle* vehicle, const int direction, ChangerIt from, ChangerIt to) {
398 const bool changedToNewLane = to != from && fabs(vehicle->getLateralPositionOnLane()) > 0.5 * vehicle->getLane()->getWidth() && mayChange(direction);
399 if (changedToNewLane) {
400 vehicle->myState.myPosLat -= direction * 0.5 * (from->lane->getWidth() + to->lane->getWidth());
401 to->lane->myTmpVehicles.insert(to->lane->myTmpVehicles.begin(), vehicle);
402 to->dens += vehicle->getVehicleType().getLengthWithGap();
403 if (MSAbstractLaneChangeModel::haveLCOutput()) {
404 if (!vehicle->isActive()) {
405 // update leaders beyond the current edge for all lanes
406 // @note to->aheadNext and from->aheadNext are only needed for output in non-action steps.
407 to->aheadNext = getLeaders(to, vehicle);
408 from->aheadNext = getLeaders(from, vehicle);
409 }
410 vehicle->getLaneChangeModel().setLeaderGaps(to->aheadNext);
411 vehicle->getLaneChangeModel().setFollowerGaps(to->lane->getFollowersOnConsecutive(vehicle, vehicle->getBackPositionOnLane(), true));
412 vehicle->getLaneChangeModel().setOrigLeaderGaps(from->aheadNext);
413 }
414 vehicle->getLaneChangeModel().startLaneChangeManeuver(from->lane, to->lane, direction);
415 to->ahead.addLeader(vehicle, false, 0);
416 } else {
417 registerUnchanged(vehicle);
418 from->ahead.addLeader(vehicle, false, 0);
419 }
420 return changedToNewLane;
421 }
422
423 void
424 MSLaneChangerSublane::outputLCStarted(MSVehicle* vehicle, ChangerIt& from, ChangerIt& to, int direction) {
425 if (MSAbstractLaneChangeModel::haveLCOutput() && MSAbstractLaneChangeModel::outputLCStarted()
426 // non-sublane change started
427 && ((vehicle->getLaneChangeModel().getOwnState() & (LCA_CHANGE_REASONS & ~LCA_SUBLANE)) != 0)
428 && ((vehicle->getLaneChangeModel().getOwnState() & LCA_STAY) == 0)
429 // no changing in previous step (either not wanted or blocked)
430 && (((vehicle->getLaneChangeModel().getPrevState() & (LCA_CHANGE_REASONS & ~LCA_SUBLANE)) == 0)
431 || ((vehicle->getLaneChangeModel().getPrevState() & LCA_STAY) != 0)
432 || ((vehicle->getLaneChangeModel().getPrevState() & LCA_BLOCKED) != 0))
433 ) {
434 #ifdef DEBUG_STATE
435 if DEBUG_COND {
436 std::cout << SIMTIME << " veh=" << vehicle->getID() << " laneChangeStarted state=" << toString((LaneChangeAction)vehicle->getLaneChangeModel().getOwnState())
437 << " prevState=" << toString((LaneChangeAction)vehicle->getLaneChangeModel().getPrevState())
438 << " filter=" << toString((LaneChangeAction)(LCA_CHANGE_REASONS & ~LCA_SUBLANE))
439 << " filtered=" << toString((LaneChangeAction)(vehicle->getLaneChangeModel().getOwnState() & (LCA_CHANGE_REASONS & ~LCA_SUBLANE)))
440 << "\n";
441 }
442 #endif
443 vehicle->getLaneChangeModel().setLeaderGaps(to->aheadNext);
444 vehicle->getLaneChangeModel().setFollowerGaps(to->lane->getFollowersOnConsecutive(vehicle, vehicle->getBackPositionOnLane(), true));
445 vehicle->getLaneChangeModel().setOrigLeaderGaps(from->aheadNext);
446 vehicle->getLaneChangeModel().laneChangeOutput("changeStarted", from->lane, to->lane, direction, vehicle->getLaneChangeModel().getManeuverDist());
447 }
448 }
449
450 void
451 MSLaneChangerSublane::outputLCEnded(MSVehicle* vehicle, ChangerIt& from, ChangerIt& to, int direction) {
452 if (MSAbstractLaneChangeModel::haveLCOutput() && MSAbstractLaneChangeModel::outputLCEnded()
453 // non-sublane change ended
454 && ((vehicle->getLaneChangeModel().getOwnState() & (LCA_CHANGE_REASONS & ~LCA_SUBLANE)) != 0)) {
455 vehicle->getLaneChangeModel().setLeaderGaps(to->aheadNext);
456 vehicle->getLaneChangeModel().setFollowerGaps(to->lane->getFollowersOnConsecutive(vehicle, vehicle->getBackPositionOnLane(), true));
457 vehicle->getLaneChangeModel().setOrigLeaderGaps(from->aheadNext);
458 vehicle->getLaneChangeModel().laneChangeOutput("changeEnded", from->lane, to->lane, direction);
459 }
460 }
461
462
463 MSLeaderDistanceInfo
464 MSLaneChangerSublane::getLeaders(const ChangerIt& target, const MSVehicle* vehicle) const {
465 // get the leading vehicle on the lane to change to
466 #ifdef DEBUG_SURROUNDING
467 if (DEBUG_COND) {
468 std::cout << SIMTIME << " getLeaders lane=" << target->lane->getID() << " ego=" << vehicle->getID() << " ahead=" << target->ahead.toString() << "\n";
469 }
470 #endif
471 MSLeaderDistanceInfo result(target->lane, nullptr, 0);
472 for (int i = 0; i < target->ahead.numSublanes(); ++i) {
473 const MSVehicle* veh = target->ahead[i];
474 if (veh != nullptr) {
475 const double gap = veh->getBackPositionOnLane(target->lane) - vehicle->getPositionOnLane() - vehicle->getVehicleType().getMinGap();
476 #ifdef DEBUG_SURROUNDING
477 if (DEBUG_COND) {
478 std::cout << " ahead lead=" << veh->getID() << " leadBack=" << veh->getBackPositionOnLane() << " gap=" << gap << "\n";
479 }
480 #endif
481 result.addLeader(veh, gap, 0, i);
482 }
483 }
484 // if there are vehicles on the target lane with the same position as ego,
485 // they may not have been added to 'ahead' yet
486 const MSLeaderInfo& aheadSamePos = target->lane->getLastVehicleInformation(nullptr, 0, vehicle->getPositionOnLane(), false);
487 for (int i = 0; i < aheadSamePos.numSublanes(); ++i) {
488 const MSVehicle* veh = aheadSamePos[i];
489 if (veh != nullptr && veh != vehicle) {
490 const double gap = veh->getBackPositionOnLane(target->lane) - vehicle->getPositionOnLane() - vehicle->getVehicleType().getMinGap();
491 #ifdef DEBUG_SURROUNDING
492 if (DEBUG_COND) {
493 std::cout << " further lead=" << veh->getID() << " leadBack=" << veh->getBackPositionOnLane(target->lane) << " gap=" << gap << "\n";
494 }
495 #endif
496 result.addLeader(veh, gap, 0, i);
497 }
498 }
499
500 if (result.numFreeSublanes() > 0) {
501 MSLane* targetLane = target->lane;
502
503 double seen = vehicle->getLane()->getLength() - vehicle->getPositionOnLane();
504 double speed = vehicle->getSpeed();
505 double dist = vehicle->getCarFollowModel().brakeGap(speed) + vehicle->getVehicleType().getMinGap();
506 if (seen > dist) {
507 #ifdef DEBUG_SURROUNDING
508 if (DEBUG_COND) {
509 std::cout << " aborting forward search. dist=" << dist << " seen=" << seen << "\n";
510 }
511 #endif
512 return result;
513 }
514 const std::vector<MSLane*>& bestLaneConts = veh(myCandi)->getBestLanesContinuation(targetLane);
515 #ifdef DEBUG_SURROUNDING
516 if (DEBUG_COND) {
517 std::cout << " add consecutive before=" << result.toString() << " dist=" << dist;
518 }
519 #endif
520 target->lane->getLeadersOnConsecutive(dist, seen, speed, vehicle, bestLaneConts, result);
521 #ifdef DEBUG_SURROUNDING
522 if (DEBUG_COND) {
523 std::cout << " after=" << result.toString() << "\n";
524 }
525 #endif
526 }
527 return result;
528 }
529
530
531 int
532 MSLaneChangerSublane::checkChangeSublane(
533 int laneOffset,
534 LaneChangeAction alternatives,
535 const std::vector<MSVehicle::LaneQ>& preb,
536 double& latDist,
537 double& maneuverDist) const {
538
539 ChangerIt target = myCandi + laneOffset;
540 MSVehicle* vehicle = veh(myCandi);
541 const MSLane& neighLane = *(target->lane);
542 int blocked = 0;
543
544 MSLeaderDistanceInfo neighLeaders = target->aheadNext;
545 MSLeaderDistanceInfo neighFollowers = target->lane->getFollowersOnConsecutive(vehicle, vehicle->getBackPositionOnLane(), true);
546 MSLeaderDistanceInfo neighBlockers(&neighLane, vehicle, vehicle->getLane()->getRightSideOnEdge() - neighLane.getRightSideOnEdge());
547 MSLeaderDistanceInfo leaders = myCandi->aheadNext;
548 MSLeaderDistanceInfo followers = myCandi->lane->getFollowersOnConsecutive(vehicle, vehicle->getBackPositionOnLane(), true);
549 MSLeaderDistanceInfo blockers(vehicle->getLane(), vehicle, 0);
550
551 #ifdef DEBUG_SURROUNDING
552 if (DEBUG_COND) std::cout << SIMTIME
553 << " checkChangeSublane: veh=" << vehicle->getID()
554 << " laneOffset=" << laneOffset
555 << "\n leaders=" << leaders.toString()
556 << "\n neighLeaders=" << neighLeaders.toString()
557 << "\n followers=" << followers.toString()
558 << "\n neighFollowers=" << neighFollowers.toString()
559 << "\n";
560 #endif
561
562
563 const int wish = vehicle->getLaneChangeModel().wantsChangeSublane(
564 laneOffset, alternatives,
565 leaders, followers, blockers,
566 neighLeaders, neighFollowers, neighBlockers,
567 neighLane, preb,
568 &(myCandi->lastBlocked), &(myCandi->firstBlocked), latDist, maneuverDist, blocked);
569 int state = blocked | wish;
570
571 // XXX
572 // do are more careful (but expensive) check to ensure that a
573 // safety-critical leader is not being overlooked
574
575 // XXX
576 // ensure that a continuous lane change manoeuvre can be completed
577 // before the next turning movement
578
579 // let TraCI influence the wish to change lanes and the security to take
580 const int oldstate = state;
581 state = vehicle->influenceChangeDecision(state);
582 #ifdef DEBUG_STATE
583 if (DEBUG_COND && state != oldstate) {
584 std::cout << SIMTIME << " veh=" << vehicle->getID() << " stateAfterTraCI=" << toString((LaneChangeAction)state) << " original=" << toString((LaneChangeAction)oldstate) << "\n";
585 }
586 #endif
587 vehicle->getLaneChangeModel().saveLCState(laneOffset, oldstate, state);
588 if (laneOffset != 0) {
589 vehicle->getLaneChangeModel().saveNeighbors(laneOffset, neighFollowers, neighLeaders);
590 }
591 return state;
592 }
593
594 /****************************************************************************/
595
596