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