Eclipse SUMO - Simulation of Urban MObility
Loading...
Searching...
No Matches
MSLCM_DK2008.cpp
Go to the documentation of this file.
1/****************************************************************************/
2// Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
3// Copyright (C) 2005-2024 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/****************************************************************************/
22// A lane change model developed by D. Krajzewicz between 2004 and 2010
23/****************************************************************************/
24#include <config.h>
25
26#include <iostream>
28#include <microsim/MSEdge.h>
29#include <microsim/MSLane.h>
30#include <microsim/MSLink.h>
31#include <microsim/MSNet.h>
32#include "MSLCM_DK2008.h"
33
34// ===========================================================================
35// variable definitions
36// ===========================================================================
37// 80km/h will be the threshold for dividing between long/short foresight
38#define LOOK_FORWARD_SPEED_DIVIDER 14.
39
40#define LOOK_FORWARD_FAR 15.
41#define LOOK_FORWARD_NEAR 5.
42
43
44
45#define JAM_FACTOR 2.
46#define JAM_FACTOR2 1.
47
48
49// ===========================================================================
50// member method definitions
51// ===========================================================================
54 myChangeProbability(0),
55 myLeadingBlockerLength(0), myLeftSpace(0) {}
56
60
61int
63 int laneOffset,
64 MSAbstractLaneChangeModel::MSLCMessager& msgPass, int blocked,
65 const std::pair<MSVehicle*, double>& leader,
66 const std::pair<MSVehicle*, double>& /*follower*/,
67 const std::pair<MSVehicle*, double>& neighLead,
68 const std::pair<MSVehicle*, double>& neighFollow,
69 const MSLane& neighLane,
70 const std::vector<MSVehicle::LaneQ>& preb,
71 MSVehicle** lastBlocked,
72 MSVehicle** firstBlocked) {
73 UNUSED_PARAMETER(firstBlocked);
74 return (laneOffset == -1 ?
75 wantsChangeToRight(msgPass, blocked, leader, neighLead, neighFollow, neighLane, preb, lastBlocked, firstBlocked)
76 : wantsChangeToLeft(msgPass, blocked, leader, neighLead, neighFollow, neighLane, preb, lastBlocked, firstBlocked));
77
78}
79
80
81int
83 int blocked,
84 const std::pair<MSVehicle*, double>& leader,
85 const std::pair<MSVehicle*, double>& neighLead,
86 const std::pair<MSVehicle*, double>& neighFollow,
87 const MSLane& neighLane,
88 const std::vector<MSVehicle::LaneQ>& preb,
89 MSVehicle** lastBlocked,
90 MSVehicle** firstBlocked) {
91 UNUSED_PARAMETER(firstBlocked);
92 MSVehicle::LaneQ curr, best;
93 int bestLaneOffset = 0;
94 double currentDist = 0;
95 double neighDist = 0;
96 double neighExtDist = 0;
97 double currExtDist = 0;
98 int currIdx = 0;
99 const MSLane* prebLane = myVehicle.getLane();
100 if (prebLane->getEdge().isInternal()) {
101 // internal edges are not kept inside the bestLanes structure
102 prebLane = prebLane->getLinkCont()[0]->getLane();
103 }
104 for (int p = 0; p < (int) preb.size(); ++p) {
105 if (preb[p].lane == prebLane && p > 0) {
106 curr = preb[p];
107 bestLaneOffset = curr.bestLaneOffset;
108 currentDist = curr.length;
109 currExtDist = curr.lane->getLength();
110 neighDist = preb[p - 1].length;
111 neighExtDist = preb[p - 1].lane->getLength();
112 best = preb[p + bestLaneOffset];
113 currIdx = p;
114 break;
115 }
116 }
117
118 // keep information about being a leader/follower
119 int ret = (myOwnState & 0xffff0000);
120
121 if (leader.first != 0
122 &&
124 &&
125 (leader.first->getLaneChangeModel().getOwnState()&LCA_AMBLOCKINGFOLLOWER_DONTBRAKE) != 0) {
126
130 } else {
131 ret |= LCA_AMBACKBLOCKER;
132 myDontBrake = true;
133 }
134 }
135
136 // process information about the last blocked vehicle
137 // if this vehicle is blocking someone in front, we maybe decelerate to let him in
138 if ((*lastBlocked) != nullptr) {
139 double gap = (*lastBlocked)->getPositionOnLane() - (*lastBlocked)->getVehicleType().getLength() - myVehicle.getPositionOnLane() - myVehicle.getVehicleType().getMinGap();
140 if (gap > 0.1) {
142 if ((*lastBlocked)->getSpeed() < SUMO_const_haltingSpeed) {
144 } else {
145 ret |= LCA_AMBACKBLOCKER;
146 }
147 myVSafes.push_back(getCarFollowModel().followSpeed(&myVehicle, myVehicle.getSpeed(), (double)(gap - 0.1), (*lastBlocked)->getSpeed(), (*lastBlocked)->getCarFollowModel().getMaxDecel()));
148 (*lastBlocked) = nullptr;
149 }
150 return ret;
151 }
152 }
153
154 // we try to estimate the distance which is necessary to get on a lane
155 // we have to get on in order to keep our route
156 // we assume we need something that depends on our velocity
157 // and compare this with the free space on our wished lane
158 //
159 // if the free space is somehow less than the space we need, we should
160 // definitely try to get to the desired lane
161 //
162 // this rule forces our vehicle to change the lane if a lane changing is necessary soon
164 ? myVehicle.getSpeed() * (double) LOOK_FORWARD_FAR
165 : myVehicle.getSpeed() * (double) LOOK_FORWARD_NEAR;
166 rv += myVehicle.getVehicleType().getLengthWithGap() * (double) 2.;
167
168 double tdist = currentDist - myVehicle.getPositionOnLane() - best.occupation * (double) JAM_FACTOR2;
169
170 // assert(best.length > curr.length);
171 // XXX if (curr.length != best.length) && ...
172 if (fabs(best.length - curr.length) > MIN2((double) .1, best.lane->getLength()) && bestLaneOffset < 0 && currentDistDisallows(tdist/*currentDist*/, bestLaneOffset, rv)) {
173 informBlocker(msgPass, blocked, LCA_MRIGHT, neighLead, neighFollow);
174 if (neighLead.second > 0 && neighLead.second > leader.second) {
175 myVSafes.push_back(getCarFollowModel().followSpeed(&myVehicle, myVehicle.getSpeed(), neighLead.second, neighLead.first->getSpeed(), neighLead.first->getCarFollowModel().getMaxDecel()) - (double) 0.5);
176 }
177
178 // letting vehicles merge in at the end of the lane in case of counter-lane change, step#1, right
179 // if there is a leader and he wants to change to left (we want to change to right)
180 if (neighLead.first != 0 && (neighLead.first->getLaneChangeModel().getOwnState()&LCA_LEFT) != 0) {
181 // save at least his length in myLeadingBlockerLength
182 myLeadingBlockerLength = MAX2(neighLead.first->getVehicleType().getLengthWithGap(), myLeadingBlockerLength);
183 // save the left space
184 myLeftSpace = currentDist - myVehicle.getPositionOnLane();
185 }
186 //
187
188 return ret | LCA_RIGHT | LCA_STRATEGIC | LCA_URGENT;
189 }
190
191
192 // the opposite lane-changing direction should be done than the one examined herein
193 // we'll check whether we assume we could change anyhow and get back in time...
194 //
195 // this rule prevents the vehicle from moving in opposite direction of the best lane
196 // unless the way till the end where the vehicle has to be on the best lane
197 // is long enough
198 double maxJam = MAX2(preb[currIdx - 1].occupation, preb[currIdx].occupation);
199 double neighLeftPlace = MAX2((double) 0, neighDist - myVehicle.getPositionOnLane() - maxJam);
200 if (bestLaneOffset >= 0 && (currentDistDisallows(neighLeftPlace, bestLaneOffset + 2, rv))) {
201 // ...we will not change the lane if not
202 return ret | LCA_STAY | LCA_STRATEGIC;
203 }
204
205
206 // if the current lane is the best and a lane-changing would cause a situation
207 // of which we assume we will not be able to return to the lane we have to be on...
208 //
209 // this rule prevents the vehicle from leaving the current, best lane when it is
210 // close to this lane's end
211 if (currExtDist > neighExtDist && (neighLeftPlace * 2. < rv/*||currE[currIdx+1].length<currentDist*/)) {
212 return ret | LCA_STAY | LCA_STRATEGIC;
213 }
214
215 // let's also regard the case where the vehicle is driving on a highway...
216 // in this case, we do not want to get to the dead-end of an on-ramp
217 //
218 // THIS RULE APPLIES ONLY TO CHANGING TO THE RIGHT LANE
219 if (bestLaneOffset == 0 && preb[currIdx - 1].bestLaneOffset != 0 && myVehicle.getLane()->getSpeedLimit() > 80. / 3.6) {
220 return ret | LCA_STAY | LCA_STRATEGIC;
221 }
222 // --------
223
224 // -------- make place on current lane if blocking follower
226 &&
227 (currentDistAllows(neighDist, bestLaneOffset, rv) || neighDist >= currentDist)) {
228
229 return ret | LCA_RIGHT | LCA_COOPERATIVE | LCA_URGENT;
230 }
231 // --------
232
233
234 // -------- security checks for krauss
235 // (vsafe fails when gap<0)
236 if ((blocked & LCA_BLOCKED) != 0) {
237 return ret;
238 }
239 // --------
240
241 // -------- higher speed
242 if ((congested(neighLead.first) && neighLead.second < 20) || predInteraction(leader)) {
243 return ret;
244 }
245 double thisLaneVSafe = myVehicle.getLane()->getVehicleMaxSpeed(&myVehicle);
246 double neighLaneVSafe = neighLane.getVehicleMaxSpeed(&myVehicle);
247 if (neighLead.first == 0) {
248 neighLaneVSafe = MIN2(neighLaneVSafe, getCarFollowModel().followSpeed(&myVehicle, myVehicle.getSpeed(), neighDist, 0, 0));
249 } else {
250 // @todo: what if leader is below safe gap?!!!
251 neighLaneVSafe = MIN2(neighLaneVSafe, getCarFollowModel().followSpeed(&myVehicle, myVehicle.getSpeed(), neighLead.second, neighLead.first->getSpeed(), neighLead.first->getCarFollowModel().getMaxDecel()));
252 }
253 if (leader.first == 0) {
254 thisLaneVSafe = MIN2(thisLaneVSafe, getCarFollowModel().followSpeed(&myVehicle, myVehicle.getSpeed(), currentDist, 0, 0));
255 } else {
256 // @todo: what if leader is below safe gap?!!!
257 thisLaneVSafe = MIN2(thisLaneVSafe, getCarFollowModel().followSpeed(&myVehicle, myVehicle.getSpeed(), leader.second, leader.first->getSpeed(), leader.first->getCarFollowModel().getMaxDecel()));
258 }
259
260 thisLaneVSafe = MIN2(thisLaneVSafe, myVehicle.getMaxSpeed());
261 neighLaneVSafe = MIN2(neighLaneVSafe, myVehicle.getMaxSpeed());
262 if (thisLaneVSafe - neighLaneVSafe > 5. / 3.6) {
263 // ok, the current lane is faster than the right one...
264 if (myChangeProbability < 0) {
265 myChangeProbability *= pow(0.5, TS);
266 }
267 } else {
268 // ok, the right lane is faster than the current
269 myChangeProbability -= TS * ((neighLaneVSafe - thisLaneVSafe) / (myVehicle.getLane()->getVehicleMaxSpeed(&myVehicle)));
270 }
271
272 // let's recheck the "Rechtsfahrgebot"
274 vmax -= (double)(5. / 2.6);
275 if (neighLaneVSafe >= vmax) {
276 myChangeProbability -= TS * ((neighLaneVSafe - vmax) / (vmax));
277 }
278
279 if (myChangeProbability < -2 && neighDist / MAX2((double) .1, myVehicle.getSpeed()) > 20.) { //./MAX2((double) .1, myVehicle.getSpeed())) { // -.1
280 return ret | LCA_RIGHT | LCA_SPEEDGAIN;
281 }
282 // --------
283
284 return ret;
285}
286
287
288int
290 int blocked,
291 const std::pair<MSVehicle*, double>& leader,
292 const std::pair<MSVehicle*, double>& neighLead,
293 const std::pair<MSVehicle*, double>& neighFollow,
294 const MSLane& neighLane,
295 const std::vector<MSVehicle::LaneQ>& preb,
296 MSVehicle** lastBlocked,
297 MSVehicle** firstBlocked) {
298 UNUSED_PARAMETER(firstBlocked);
299 MSVehicle::LaneQ curr, best;
300 int bestLaneOffset = 0;
301 double currentDist = 0;
302 double neighDist = 0;
303 double neighExtDist = 0;
304 double currExtDist = 0;
305 int currIdx = 0;
306 const MSLane* prebLane = myVehicle.getLane();
307 if (prebLane->getEdge().isInternal()) {
308 // internal edges are not kept inside the bestLanes structure
309 prebLane = prebLane->getLinkCont()[0]->getLane();
310 }
311 for (int p = 0; p < (int) preb.size(); ++p) {
312 if (preb[p].lane == prebLane) {
313 curr = preb[p];
314 bestLaneOffset = curr.bestLaneOffset;
315 currentDist = curr.length;
316 currExtDist = curr.lane->getLength();
317 neighDist = preb[p + 1].length;
318 neighExtDist = preb[p + 1].lane->getLength();
319 best = preb[p + bestLaneOffset];
320 currIdx = p;
321 break;
322 }
323 }
324 // keep information about being a leader/follower
325 int ret = (myOwnState & 0xffff0000);
326
327 // ?!!!
328 if (leader.first != 0
329 &&
331 &&
332 (leader.first->getLaneChangeModel().getOwnState()&LCA_AMBLOCKINGFOLLOWER_DONTBRAKE) != 0) {
333
337 } else {
338 ret |= LCA_AMBACKBLOCKER;
339 myDontBrake = true;
340 }
341 }
342
343 // process information about the last blocked vehicle
344 // if this vehicle is blocking someone in front, we maybe decelerate to let him in
345 if ((*lastBlocked) != nullptr) {
346 double gap = (*lastBlocked)->getPositionOnLane() - (*lastBlocked)->getVehicleType().getLength() - myVehicle.getPositionOnLane() - myVehicle.getVehicleType().getMinGap();
347 if (gap > 0.1) {
349 if ((*lastBlocked)->getSpeed() < SUMO_const_haltingSpeed) {
351 } else {
352 ret |= LCA_AMBACKBLOCKER;
353 }
354 myVSafes.push_back(getCarFollowModel().followSpeed(&myVehicle, myVehicle.getSpeed(), (double)(gap - 0.1), (*lastBlocked)->getSpeed(), (*lastBlocked)->getCarFollowModel().getMaxDecel()));
355 (*lastBlocked) = nullptr;
356 }
357 return ret;
358 }
359 }
360
361 // we try to estimate the distance which is necessary to get on a lane
362 // we have to get on in order to keep our route
363 // we assume we need something that depends on our velocity
364 // and compare this with the free space on our wished lane
365 //
366 // if the free space is somehow less than the space we need, we should
367 // definitely try to get to the desired lane
368 //
369 // this rule forces our vehicle to change the lane if a lane changing is necessary soon
371 ? myVehicle.getSpeed() * (double) LOOK_FORWARD_FAR
372 : myVehicle.getSpeed() * (double) LOOK_FORWARD_NEAR;
373 lv += myVehicle.getVehicleType().getLengthWithGap() * (double) 2.;
374
375
376 double tdist = currentDist - myVehicle.getPositionOnLane() - best.occupation * (double) JAM_FACTOR2;
377 if (fabs(best.length - curr.length) > MIN2((double) .1, best.lane->getLength()) && bestLaneOffset > 0
378 &&
379 currentDistDisallows(tdist/*currentDist*/, bestLaneOffset, lv)) {
380 informBlocker(msgPass, blocked, LCA_MLEFT, neighLead, neighFollow);
381 if (neighLead.second > 0 && neighLead.second > leader.second) {
382 myVSafes.push_back(getCarFollowModel().followSpeed(&myVehicle, myVehicle.getSpeed(), neighLead.second, neighLead.first->getSpeed(), neighLead.first->getCarFollowModel().getMaxDecel()) - (double) 0.5);
383 }
384
385 // letting vehicles merge in at the end of the lane in case of counter-lane change, step#1, left
386 // if there is a leader and he wants to change to right (we want to change to left)
387 if (neighLead.first != 0 && (neighLead.first->getLaneChangeModel().getOwnState()&LCA_RIGHT) != 0) {
388 // save at least his length in myLeadingBlockerLength
389 myLeadingBlockerLength = MAX2(neighLead.first->getVehicleType().getLengthWithGap(), myLeadingBlockerLength);
390 // save the left space
391 myLeftSpace = currentDist - myVehicle.getPositionOnLane();
392 }
393 //
394
395 return ret | LCA_LEFT | LCA_STRATEGIC | LCA_URGENT;
396 }
397
398 // the opposite lane-changing direction should be rather done, not
399 // the one examined herein
400 // we'll check whether we assume we could change anyhow and get back in time...
401 //
402 // this rule prevents the vehicle from moving in opposite direction of the best lane
403 // unless the way till the end where the vehicle has to be on the best lane
404 // is long enough
405 double maxJam = MAX2(preb[currIdx + 1].occupation, preb[currIdx].occupation);
406 double neighLeftPlace = MAX2((double) 0, neighDist - myVehicle.getPositionOnLane() - maxJam);
407 if (bestLaneOffset <= 0 && (currentDistDisallows(neighLeftPlace, bestLaneOffset - 2, lv))) {
408 // ...we will not change the lane if not
409 return ret | LCA_STAY | LCA_STRATEGIC;
410 }
411
412
413 // if the current lane is the best and a lane-changing would cause a situation
414 // of which we assume we will not be able to return to the lane we have to be on...
415 //
416 // this rule prevents the vehicle from leaving the current, best lane when it is
417 // close to this lane's end
418 if (currExtDist > neighExtDist && (neighLeftPlace * 2. < lv/*||currE[currIdx+1].length<currentDist*/)) {
419 // ... let's not change the lane
420 return ret | LCA_STAY | LCA_STRATEGIC;
421 }
422
423 /*
424 // let's also regard the case where the vehicle is driving on a highway...
425 // in this case, we do not want to get to the dead-end of an on-ramp
426 if(bestLaneOffset==0&&myVehicle.getLane().getMaxSpeed()>80./3.6) {
427 return ret;
428 }
429 */
430
431
432 /*
433 // if the current lane is the
434 if(bestLaneOffset==0&&(neighDist==0||curr.seenVehicles2*JAM_FACTOR>=neighExtDist-curr.length)) {
435 return ret;
436 }
437 */
438 // --------
439
440 // -------- make place on current lane if blocking follower
442 &&
443 (currentDistAllows(neighDist, bestLaneOffset, lv) || neighDist >= currentDist)) {
444
445 return ret | LCA_LEFT | LCA_COOPERATIVE | LCA_URGENT;
446 }
447 // --------
448
449 // -------- security checks for krauss
450 // (vsafe fails when gap<0)
451 if ((blocked & LCA_BLOCKED) != 0) {
452 return ret;
453 }
454
455 // -------- higher speed
456 if ((congested(neighLead.first) && neighLead.second < 20) || predInteraction(leader)) {
457 return ret;
458 }
459 double neighLaneVSafe = neighLane.getVehicleMaxSpeed(&myVehicle);
460 double thisLaneVSafe = myVehicle.getLane()->getVehicleMaxSpeed(&myVehicle);
461 if (neighLead.first == 0) {
462 neighLaneVSafe = MIN2(neighLaneVSafe, getCarFollowModel().followSpeed(&myVehicle, myVehicle.getSpeed(), neighDist, 0, 0)); // !!! warum nicht die Folgesgeschw.?
463 } else {
464 // @todo: what if leader is below safe gap?!!!
465 neighLaneVSafe = MIN2(neighLaneVSafe, getCarFollowModel().followSpeed(&myVehicle, myVehicle.getSpeed(), neighLead.second, neighLead.first->getSpeed(), neighLead.first->getCarFollowModel().getMaxDecel()));
466 }
467 if (leader.first == 0) {
468 thisLaneVSafe = MIN2(thisLaneVSafe, getCarFollowModel().followSpeed(&myVehicle, myVehicle.getSpeed(), currentDist, 0, 0));
469 } else {
470 // @todo: what if leader is below safe gap?!!!
471 thisLaneVSafe = MIN2(thisLaneVSafe, getCarFollowModel().followSpeed(&myVehicle, myVehicle.getSpeed(), leader.second, leader.first->getSpeed(), leader.first->getCarFollowModel().getMaxDecel()));
472 }
473 thisLaneVSafe = MIN2(thisLaneVSafe, myVehicle.getMaxSpeed());
474 neighLaneVSafe = MIN2(neighLaneVSafe, myVehicle.getMaxSpeed());
475 if (thisLaneVSafe > neighLaneVSafe) {
476 // this lane is better
477 if (myChangeProbability > 0) {
478 myChangeProbability *= pow(0.5, TS);
479 }
480 } else {
481 // right lane is better
482 myChangeProbability += TS * ((neighLaneVSafe - thisLaneVSafe) / (myVehicle.getLane()->getVehicleMaxSpeed(&myVehicle))); // !!! Fahrzeuggeschw.!
483 }
484 if (myChangeProbability > .2 && neighDist / MAX2((double) .1, myVehicle.getSpeed()) > 20.) { // .1
485 return ret | LCA_LEFT | LCA_SPEEDGAIN | LCA_URGENT;
486 }
487 // --------
488
489 return ret;
490}
491
492
493double
494MSLCM_DK2008::patchSpeed(const double min, const double wanted, const double max, const MSCFModel& cfModel) {
495 int state = myOwnState;
496
497 // letting vehicles merge in at the end of the lane in case of counter-lane change, step#2
498 double MAGIC_offset = 1.;
499 // if we want to change and have a blocking leader and there is enough room for him in front of us
500 if (myLeadingBlockerLength != 0) {
501 double space = myLeftSpace - myLeadingBlockerLength - MAGIC_offset - myVehicle.getVehicleType().getMinGap();
502 if (space > 0) {
503 // compute speed for decelerating towards a place which allows the blocking leader to merge in in front
505 // if we are approaching this place
506 if (safe < wanted) {
507 // return this speed as the speed to use
508 return MAX2(min, safe);
509 }
510 }
511 }
512
513 // just to make sure to be notified about lane chaning end
514 if (myVehicle.getLane()->getEdge().getLanes().size() == 1 || myVehicle.getLane()->getEdge().isInternal()) {
515 // remove chaning information if on a road with a single lane
516 changed();
517 return wanted;
518 }
519
520 double nVSafe = wanted;
521 bool gotOne = false;
522 for (std::vector<double>::const_iterator i = myVSafes.begin(); i != myVSafes.end(); ++i) {
523 double v = (*i);
524 if (v >= min && v <= max) {
525 nVSafe = MIN2(v, nVSafe);
526 gotOne = true;
527 }
528 }
529
530 // check whether the vehicle is blocked
531 if ((state & LCA_WANTS_LANECHANGE) != 0) {
532 if (gotOne && !myDontBrake) {
533 return nVSafe;
534 }
535 // check whether the vehicle maybe has to be swapped with one of
536 // the blocking vehicles
537 if ((state & LCA_BLOCKED) != 0) {
538 if ((state & LCA_BLOCKED_BY_LEADER) != 0) {
539 // if interacting with leader and not too slow
540 return (min + wanted) / (double) 2.0;
541 }
542 if ((state & LCA_BLOCKED_BY_FOLLOWER) != 0) {
543 return (max + wanted) / (double) 2.0;
544 }
545 return (min + wanted) / (double) 2.0;
546 }
547 }
548
549
550 // decelerate if being a blocking follower
551 // (and does not have to change lanes)
552 if ((state & LCA_AMBLOCKINGFOLLOWER) != 0) {
553 if (fabs(max - myVehicle.getCarFollowModel().maxNextSpeed(myVehicle.getSpeed(), &myVehicle)) < 0.001 && min == 0) { // !!! was standing
554 return 0;
555 }
556 return (min + wanted) / (double) 2.0;
557 }
558 if ((state & LCA_AMBACKBLOCKER) != 0) {
559 if (max <= myVehicle.getCarFollowModel().maxNextSpeed(myVehicle.getSpeed(), &myVehicle) && min == 0) { // !!! was standing
560 return min;
561 }
562 }
563 if ((state & LCA_AMBACKBLOCKER_STANDING) != 0) {
564 return min;
565 }
566 // accelerate if being a blocking leader or blocking follower not able to brake
567 // (and does not have to change lanes)
568 if ((state & LCA_AMBLOCKINGLEADER) != 0) {
569 return (max + wanted) / (double) 2.0;
570 }
571 if ((state & LCA_AMBLOCKINGFOLLOWER_DONTBRAKE) != 0) {
572 if (max <= myVehicle.getCarFollowModel().maxNextSpeed(myVehicle.getSpeed(), &myVehicle) && min == 0) { // !!! was standing
573 return wanted;
574 }
575 return (min + wanted) / (double) 2.0;
576 }
577 return wanted;
578}
579
580
581void*
582MSLCM_DK2008::inform(void* info, MSVehicle* /*sender*/) {
583 Info* pinfo = (Info*) info;
584 //myOwnState &= 0xffffffff; // reset all bits of MyLCAEnum but only those
585 myOwnState |= pinfo->second;
586 delete pinfo;
587 return (void*) true;
588}
589
590
591void
593 myOwnState = 0;
596 myLeftSpace = 0;
597 myVSafes.clear();
598 myDontBrake = false;
599}
600
601
602void
604 int& blocked,
605 int dir,
606 const std::pair<MSVehicle*, double>& neighLead,
607 const std::pair<MSVehicle*, double>& neighFollow) {
608 if ((blocked & LCA_BLOCKED_BY_FOLLOWER) != 0) {
609 assert(neighFollow.first != 0);
610 MSVehicle* nv = neighFollow.first;
611 double decelGap =
612 neighFollow.second
613 + SPEED2DIST(myVehicle.getSpeed()) * (double) 2.0
614 - MAX2(nv->getSpeed() - (double) ACCEL2DIST(nv->getCarFollowModel().getMaxDecel()) * (double) 2.0, (double) 0);
615 if (neighFollow.second > 0 && decelGap > 0 && decelGap >= nv->getCarFollowModel().getSecureGap(nv, &myVehicle,
617 double vsafe = getCarFollowModel().followSpeed(&myVehicle, myVehicle.getSpeed(), neighFollow.second, neighFollow.first->getSpeed(), neighFollow.first->getCarFollowModel().getMaxDecel());
618 msgPass.informNeighFollower(new Info(vsafe, dir | LCA_AMBLOCKINGFOLLOWER), &myVehicle);
619 } else {
620 double vsafe = neighFollow.second <= 0 ? 0 : getCarFollowModel().followSpeed(&myVehicle, myVehicle.getSpeed(), neighFollow.second, neighFollow.first->getSpeed(), neighFollow.first->getCarFollowModel().getMaxDecel());
622 }
623 }
624 if ((blocked & LCA_BLOCKED_BY_LEADER) != 0) {
625 if (neighLead.first != 0 && neighLead.second > 0) {
626 msgPass.informNeighLeader(new Info(0, dir | LCA_AMBLOCKINGLEADER), &myVehicle);
627 }
628 }
629}
630
631
632void
635 myOwnState = 0;
637 myLeftSpace = 0;
638 myVSafes.clear();
639 myDontBrake = false;
640 // truncate myChangeProbability to work around numerical instability between different builds
641 myChangeProbability = ceil(myChangeProbability * 100000.0) * 0.00001;
643}
644
645
646/****************************************************************************/
#define JAM_FACTOR2
#define LOOK_FORWARD_NEAR
#define LOOK_FORWARD_SPEED_DIVIDER
#define LOOK_FORWARD_FAR
#define SPEED2DIST(x)
Definition SUMOTime.h:45
#define ACCEL2SPEED(x)
Definition SUMOTime.h:51
#define TS
Definition SUMOTime.h:42
#define ACCEL2DIST(x)
Definition SUMOTime.h:49
@ LCA_BLOCKED
blocked in all directions
@ LCA_URGENT
The action is urgent (to be defined by lc-model)
@ LCA_STAY
Needs to stay on the current lane.
@ LCA_BLOCKED_BY_LEADER
blocked by leader
@ LCA_AMBACKBLOCKER
@ LCA_AMBLOCKINGLEADER
@ LCA_AMBLOCKINGFOLLOWER_DONTBRAKE
@ LCA_COOPERATIVE
The action is done to help someone else.
@ LCA_LEFT
Wants go to the left.
@ LCA_STRATEGIC
The action is needed to follow the route (navigational lc)
@ LCA_AMBACKBLOCKER_STANDING
@ LCA_SPEEDGAIN
The action is due to the wish to be faster (tactical lc)
@ LCA_WANTS_LANECHANGE
lane can change
@ LCA_RIGHT
Wants go to the right.
@ LCA_BLOCKED_BY_FOLLOWER
blocker by follower
@ LCA_AMBLOCKINGFOLLOWER
#define UNUSED_PARAMETER(x)
Definition StdDefs.h:30
T MIN2(T a, T b)
Definition StdDefs.h:76
const double SUMO_const_haltingSpeed
the speed threshold at which vehicles are considered as halting
Definition StdDefs.h:58
T MAX2(T a, T b)
Definition StdDefs.h:82
A class responsible for exchanging messages between cars involved in lane-change interaction.
void * informNeighFollower(void *info, MSVehicle *sender)
Informs the follower on the desired lane.
void * informNeighLeader(void *info, MSVehicle *sender)
Informs the leader on the desired lane.
Interface for lane-change models.
int myOwnState
The current state of the vehicle.
virtual bool predInteraction(const std::pair< MSVehicle *, double > &leader)
const MSCFModel & getCarFollowModel() const
The vehicle's car following model.
MSVehicle & myVehicle
The vehicle this lane-changer belongs to.
virtual bool congested(const MSVehicle *const neighLeader)
double getMaxSpeed() const
Returns the maximum speed (the minimum of desired and technical maximum speed)
const MSVehicleType & getVehicleType() const
Returns the vehicle's type definition.
The car-following model abstraction.
Definition MSCFModel.h:55
virtual double maxNextSpeed(double speed, const MSVehicle *const veh) const
Returns the maximum speed given the current speed.
@ LANE_CHANGE
the return value is used for lane change calculations
Definition MSCFModel.h:85
virtual double getSecureGap(const MSVehicle *const veh, const MSVehicle *const, const double speed, const double leaderSpeed, const double leaderMaxDecel) const
Returns the minimum gap to reserve if the leader is braking at maximum (>=0)
double getMaxDecel() const
Get the vehicle type's maximal comfortable deceleration [m/s^2].
Definition MSCFModel.h:264
virtual double followSpeed(const MSVehicle *const veh, double speed, double gap2pred, double predSpeed, double predMaxDecel, const MSVehicle *const pred=0, const CalcReason usage=CalcReason::CURRENT) const =0
Computes the vehicle's follow speed (no dawdling)
double stopSpeed(const MSVehicle *const veh, const double speed, double gap, const CalcReason usage=CalcReason::CURRENT) const
Computes the vehicle's safe speed for approaching a non-moving obstacle (no dawdling)
Definition MSCFModel.h:168
const std::vector< MSLane * > & getLanes() const
Returns this edge's lanes.
Definition MSEdge.h:168
bool isInternal() const
return whether this edge is an internal edge
Definition MSEdge.h:268
double myLeftSpace
std::vector< double > myVSafes
std::pair< double, int > Info
MSLCM_DK2008(MSVehicle &v)
virtual ~MSLCM_DK2008()
bool amBlockingFollowerPlusNB()
virtual void changed()
virtual int wantsChangeToRight(MSAbstractLaneChangeModel::MSLCMessager &msgPass, int blocked, const std::pair< MSVehicle *, double > &leader, const std::pair< MSVehicle *, double > &neighLead, const std::pair< MSVehicle *, double > &neighFollow, const MSLane &neighLane, const std::vector< MSVehicle::LaneQ > &preb, MSVehicle **lastBlocked, MSVehicle **firstBlocked)
Called to examine whether the vehicle wants to change to right This method gets the information about...
double myChangeProbability
int wantsChange(int laneOffset, MSAbstractLaneChangeModel::MSLCMessager &msgPass, int blocked, const std::pair< MSVehicle *, double > &leader, const std::pair< MSVehicle *, double > &follower, const std::pair< MSVehicle *, double > &neighLead, const std::pair< MSVehicle *, double > &neighFollow, const MSLane &neighLane, const std::vector< MSVehicle::LaneQ > &preb, MSVehicle **lastBlocked, MSVehicle **firstBlocked)
Called to examine whether the vehicle wants to change using the given laneOffset. This method gets th...
void informBlocker(MSAbstractLaneChangeModel::MSLCMessager &msgPass, int &blocked, int dir, const std::pair< MSVehicle *, double > &neighLead, const std::pair< MSVehicle *, double > &neighFollow)
bool currentDistAllows(double dist, int laneOffset, double lookForwardDist)
double myLeadingBlockerLength
virtual void * inform(void *info, MSVehicle *sender)
virtual void prepareStep()
virtual int wantsChangeToLeft(MSAbstractLaneChangeModel::MSLCMessager &msgPass, int blocked, const std::pair< MSVehicle *, double > &leader, const std::pair< MSVehicle *, double > &neighLead, const std::pair< MSVehicle *, double > &neighFollow, const MSLane &neighLane, const std::vector< MSVehicle::LaneQ > &preb, MSVehicle **lastBlocked, MSVehicle **firstBlocked)
Called to examine whether the vehicle wants to change to left This method gets the information about ...
virtual double patchSpeed(const double min, const double wanted, const double max, const MSCFModel &cfModel)
Called to adapt the speed in order to allow a lane change.
bool currentDistDisallows(double dist, int laneOffset, double lookForwardDist)
Representation of a lane in the micro simulation.
Definition MSLane.h:84
double getSpeedLimit() const
Returns the lane's maximum allowed speed.
Definition MSLane.h:592
double getLength() const
Returns the lane's length.
Definition MSLane.h:606
double getVehicleMaxSpeed(const SUMOTrafficObject *const veh) const
Returns the lane's maximum speed, given a vehicle's speed limit adaptation.
Definition MSLane.h:574
MSEdge & getEdge() const
Returns the lane's edge.
Definition MSLane.h:764
const std::vector< MSLink * > & getLinkCont() const
returns the container with all links !!!
Definition MSLane.h:724
Representation of a vehicle in the micro simulation.
Definition MSVehicle.h:77
const MSLane * getLane() const
Returns the lane the vehicle is on.
Definition MSVehicle.h:581
double getSpeed() const
Returns the vehicle's current speed.
Definition MSVehicle.h:490
const MSCFModel & getCarFollowModel() const
Returns the vehicle's car following model definition.
Definition MSVehicle.h:965
double getPositionOnLane() const
Get the vehicle's position along the lane.
Definition MSVehicle.h:374
double getLengthWithGap() const
Get vehicle's length including the minimum gap [m].
double getMinGap() const
Get the free space in front of vehicles of this class.
A structure representing the best lanes for continuing the current route starting at 'lane'.
Definition MSVehicle.h:853
double length
The overall length which may be driven when using this lane without a lane change.
Definition MSVehicle.h:857
MSLane * lane
The described lane.
Definition MSVehicle.h:855
int bestLaneOffset
The (signed) number of lanes to be crossed to get to the lane which allows to continue the drive.
Definition MSVehicle.h:865
double occupation
The overall vehicle sum on consecutive lanes which can be passed without a lane change.
Definition MSVehicle.h:861