1 package org.opentrafficsim.road.gtu.lane.tactical.util.lmrs;
2
3 import java.util.SortedSet;
4
5 import org.djunits.unit.AccelerationUnit;
6 import org.djunits.value.vdouble.scalar.Acceleration;
7 import org.djunits.value.vdouble.scalar.Duration;
8 import org.djunits.value.vdouble.scalar.Length;
9 import org.djunits.value.vdouble.scalar.Speed;
10 import org.opentrafficsim.core.gtu.GTUException;
11 import org.opentrafficsim.core.gtu.behavioralcharacteristics.BehavioralCharacteristics;
12 import org.opentrafficsim.core.gtu.behavioralcharacteristics.ParameterException;
13 import org.opentrafficsim.core.gtu.behavioralcharacteristics.ParameterTypes;
14 import org.opentrafficsim.core.gtu.perception.EgoPerception;
15 import org.opentrafficsim.core.gtu.plan.operational.OperationalPlanException;
16 import org.opentrafficsim.core.network.LateralDirectionality;
17 import org.opentrafficsim.road.gtu.lane.perception.InfrastructureLaneChangeInfo;
18 import org.opentrafficsim.road.gtu.lane.perception.LanePerception;
19 import org.opentrafficsim.road.gtu.lane.perception.RelativeLane;
20 import org.opentrafficsim.road.gtu.lane.perception.categories.InfrastructurePerception;
21 import org.opentrafficsim.road.gtu.lane.perception.categories.IntersectionPerception;
22 import org.opentrafficsim.road.gtu.lane.perception.categories.NeighborsPerception;
23 import org.opentrafficsim.road.gtu.lane.perception.headway.HeadwayConflict;
24 import org.opentrafficsim.road.gtu.lane.perception.headway.HeadwayGTU;
25 import org.opentrafficsim.road.gtu.lane.tactical.following.CarFollowingModel;
26 import org.opentrafficsim.road.gtu.lane.tactical.util.CarFollowingUtil;
27 import org.opentrafficsim.road.network.speed.SpeedLimitInfo;
28
29
30
31
32
33
34
35
36
37
38
39
40 public enum Synchronization implements LmrsParameters
41 {
42
43
44 PASSIVE
45 {
46
47 @Override
48 Acceleration synchronize(final LanePerception perception, final BehavioralCharacteristics bc, final SpeedLimitInfo sli,
49 final CarFollowingModel cfm, final double desire, final LateralDirectionality lat, final LmrsData lmrsData)
50 throws ParameterException, OperationalPlanException
51 {
52 Acceleration a = new Acceleration(Double.POSITIVE_INFINITY, AccelerationUnit.SI);
53 double dCoop = bc.getParameter(DCOOP);
54 RelativeLane relativeLane = new RelativeLane(lat, 1);
55 SortedSet<HeadwayGTU> set = removeAllUpstreamOfConflicts(removeAllUpstreamOfConflicts(
56 perception.getPerceptionCategory(NeighborsPerception.class).getLeaders(relativeLane), perception,
57 relativeLane), perception, RelativeLane.CURRENT);
58 HeadwayGTU leader = null;
59 if (desire >= dCoop && !set.isEmpty())
60 {
61 leader = set.first();
62 }
63 else
64 {
65 for (HeadwayGTU gtu : set)
66 {
67 if (gtu.getSpeed().gt0())
68 {
69 leader = gtu;
70 break;
71 }
72 }
73 }
74 if (leader != null)
75 {
76 Speed ownSpeed = perception.getPerceptionCategory(EgoPerception.class).getSpeed();
77 Acceleration aSingle =
78 LmrsUtil.singleAcceleration(leader.getDistance(), ownSpeed, leader.getSpeed(), desire, bc, sli, cfm);
79 a = Acceleration.min(a, aSingle);
80 }
81 return gentleUrgency(a, desire, bc);
82 }
83
84 @Override
85 Acceleration cooperate(final LanePerception perception, final BehavioralCharacteristics bc, final SpeedLimitInfo sli,
86 final CarFollowingModel cfm, final LateralDirectionality lat)
87 throws ParameterException, OperationalPlanException
88 {
89 if ((lat.isLeft() && !perception.getLaneStructure().getCrossSection().contains(RelativeLane.LEFT))
90 || (lat.isRight() && !perception.getLaneStructure().getCrossSection().contains(RelativeLane.RIGHT)))
91 {
92 return new Acceleration(Double.MAX_VALUE, AccelerationUnit.SI);
93 }
94 Acceleration b = bc.getParameter(ParameterTypes.B);
95 Acceleration a = new Acceleration(Double.MAX_VALUE, AccelerationUnit.SI);
96 double dCoop = bc.getParameter(DCOOP);
97 Speed ownSpeed = perception.getPerceptionCategory(EgoPerception.class).getSpeed();
98 RelativeLane relativeLane = new RelativeLane(lat, 1);
99 for (HeadwayGTU leader : removeAllUpstreamOfConflicts(removeAllUpstreamOfConflicts(
100 perception.getPerceptionCategory(NeighborsPerception.class).getLeaders(relativeLane), perception,
101 relativeLane), perception, RelativeLane.CURRENT))
102 {
103 BehavioralCharacteristics bc2 = leader.getBehavioralCharacteristics();
104 double desire = lat.equals(LateralDirectionality.LEFT) && bc2.contains(DRIGHT) ? bc2.getParameter(DRIGHT)
105 : lat.equals(LateralDirectionality.RIGHT) && bc2.contains(DLEFT) ? bc2.getParameter(DLEFT) : 0;
106 if (desire >= dCoop && (leader.getSpeed().gt0() || leader.getDistance().gt0()))
107 {
108 Acceleration aSingle = LmrsUtil.singleAcceleration(leader.getDistance(), ownSpeed, leader.getSpeed(),
109 desire, bc, sli, cfm);
110 a = Acceleration.min(a, aSingle);
111 }
112 }
113
114 return Acceleration.max(a, b.neg());
115 }
116
117 },
118
119
120 ACTIVE
121 {
122
123 @Override
124 Acceleration synchronize(final LanePerception perception, final BehavioralCharacteristics bc, final SpeedLimitInfo sli,
125 final CarFollowingModel cfm, final double desire, final LateralDirectionality lat, final LmrsData lmrsData)
126 throws ParameterException, OperationalPlanException
127 {
128
129 Acceleration b = bc.getParameter(ParameterTypes.B);
130 Acceleration bCrit = bc.getParameter(ParameterTypes.BCRIT);
131 Duration tMin = bc.getParameter(ParameterTypes.TMIN);
132 Duration tMax = bc.getParameter(ParameterTypes.TMAX);
133 Speed vCong = bc.getParameter(ParameterTypes.VCONG);
134 Length x0 = bc.getParameter(ParameterTypes.LOOKAHEAD);
135 Duration t0 = bc.getParameter(ParameterTypes.T0);
136 Duration lc = bc.getParameter(ParameterTypes.LCDUR);
137 Speed tagSpeed = x0.divideBy(t0);
138 double dCoop = bc.getParameter(DCOOP);
139 Speed ownSpeed = perception.getPerceptionCategory(EgoPerception.class).getSpeed();
140 Length ownLength = perception.getPerceptionCategory(EgoPerception.class).getLength();
141 Length dx;
142 try
143 {
144 dx = perception.getGtu().getFront().getDx();
145 }
146 catch (GTUException exception)
147 {
148 throw new OperationalPlanException(exception);
149 }
150
151
152 InfrastructurePerception infra = perception.getPerceptionCategory(InfrastructurePerception.class);
153 SortedSet<InfrastructureLaneChangeInfo> info = infra.getInfrastructureLaneChangeInfo(RelativeLane.CURRENT);
154 Length xMerge = infra.getLegalLaneChangePossibility(RelativeLane.CURRENT, lat).minus(dx);
155 xMerge = xMerge.lt0() ? xMerge.neg() : Length.ZERO;
156 int nCur;
157 Length xCur;
158 if (info.isEmpty())
159 {
160 nCur = 0;
161 xCur = Length.createSI(Double.POSITIVE_INFINITY);
162 }
163 else
164 {
165 nCur = info.first().getRequiredNumberOfLaneChanges();
166
167 xCur = info.first().getRemainingDistance().minus(ownLength.multiplyBy(2.0 * nCur)).minus(dx);
168 }
169
170
171 Length xMergeSync = xCur.minus(Length.createSI(.5 * ownSpeed.si * ownSpeed.si / b.si));
172 xMergeSync = Length.min(xMerge, xMergeSync);
173
174
175 NeighborsPerception neighbors = perception.getPerceptionCategory(NeighborsPerception.class);
176 RelativeLane lane = new RelativeLane(lat, 1);
177 SortedSet<HeadwayGTU> leaders =
178 removeAllUpstreamOfConflicts(removeAllUpstreamOfConflicts(neighbors.getLeaders(lane), perception, lane),
179 perception, RelativeLane.CURRENT);
180 HeadwayGTU syncVehicle = lmrsData.getSyncVehicle(leaders);
181 if (syncVehicle != null && ((syncVehicle.getSpeed().lt(vCong) && syncVehicle.getDistance().lt(xMergeSync))
182 || syncVehicle.getDistance().gt(xCur)))
183 {
184 syncVehicle = null;
185 }
186
187
188 if (syncVehicle == null)
189 {
190 Length maxDistance = Length.min(x0, xCur);
191 for (HeadwayGTU leader : leaders)
192 {
193 if ((leader.getDistance().lt(maxDistance) || leader.getSpeed().gt(vCong))
194 && tagAlongAcceleration(leader, ownSpeed, ownLength, tagSpeed, desire, bc, sli, cfm).gt(b.neg()))
195 {
196 syncVehicle = leader;
197 break;
198 }
199 }
200 }
201
202
203 HeadwayGTU up;
204 SortedSet<HeadwayGTU> followers =
205 removeAllUpstreamOfConflicts(removeAllUpstreamOfConflicts(neighbors.getFollowers(lane), perception, lane),
206 perception, RelativeLane.CURRENT);
207 HeadwayGTU follower = followers.isEmpty() ? null
208 : followers.first().moved(
209 followers.first().getDistance().plus(ownLength).plus(followers.first().getLength()).neg(),
210 followers.first().getSpeed(), followers.first().getAcceleration());
211 boolean upOk;
212 if (syncVehicle == null)
213 {
214 up = null;
215 upOk = false;
216 }
217 else
218 {
219 up = getFollower(syncVehicle, leaders, follower, ownLength);
220 upOk = up == null ? false
221 : tagAlongAcceleration(up, ownSpeed, ownLength, tagSpeed, desire, bc, sli, cfm).gt(b.neg());
222 }
223 while (syncVehicle != null && up != null
224 && (upOk || (!canBeAhead(up, xCur, nCur, ownSpeed, ownLength, tagSpeed, dCoop, bCrit, tMin, tMax, x0, t0,
225 lc, desire) && desire > dCoop))
226 && (up.getDistance().plus(up.getLength()).gt(xMergeSync) || up.getSpeed().gt(vCong)))
227 {
228 if (up.equals(follower))
229 {
230
231 syncVehicle = null;
232 up = null;
233 break;
234 }
235 syncVehicle = up;
236 up = getFollower(syncVehicle, leaders, follower, ownLength);
237 upOk = up == null ? false
238 : tagAlongAcceleration(up, ownSpeed, ownLength, tagSpeed, desire, bc, sli, cfm).gt(b.neg());
239 }
240
241
242 Acceleration a = Acceleration.POSITIVE_INFINITY;
243 if (syncVehicle != null)
244 {
245 a = gentleUrgency(tagAlongAcceleration(syncVehicle, ownSpeed, ownLength, tagSpeed, desire, bc, sli, cfm),
246 desire, bc);
247 }
248 else if (follower != null)
249 {
250
251 if (!canBeAhead(follower, xCur, nCur, ownSpeed, ownLength, tagSpeed, dCoop, bCrit, tMin, tMax, x0, t0, lc,
252 desire))
253 {
254
255 double c = requiredBufferSpace(follower.getSpeed(), nCur, x0, t0, lc, dCoop).si;
256 double t = (xCur.si - follower.getDistance().si - c) / follower.getSpeed().si;
257 Acceleration acc = Acceleration.createSI(2 * (xCur.si - c - ownSpeed.si * t) / (t * t));
258 if (follower.getSpeed().eq0() || acc.si < -ownSpeed.si / t || t < 0)
259 {
260
261 a = stopForEnd(xCur, xMerge, bc, ownSpeed, cfm, sli);
262 }
263 else
264 {
265 a = gentleUrgency(acc, desire, bc);
266 }
267 }
268 else
269 {
270
271 boolean acceptFollower;
272 if (followers.first().getDistance().gt0())
273 {
274 BehavioralCharacteristics bcFollower = follower.getBehavioralCharacteristics();
275 LmrsUtil.setDesiredHeadway(bc, desire);
276 acceptFollower = LmrsUtil.singleAcceleration(followers.first().getDistance(), follower.getSpeed(),
277 ownSpeed, desire, bcFollower, follower.getSpeedLimitInfo(),
278 follower.getCarFollowingModel()).si > -b.si * desire;
279 }
280 else
281 {
282 acceptFollower = false;
283 }
284 boolean acceptSelf;
285 if (!leaders.isEmpty() && leaders.first().getDistance().gt0())
286 {
287 acceptSelf = LmrsUtil.singleAcceleration(leaders.first().getDistance(), ownSpeed,
288 leaders.first().getSpeed(), desire, bc, sli, cfm).si > -b.si * desire;
289 }
290 else
291 {
292 acceptSelf = false;
293 }
294 if (!acceptFollower || !acceptSelf)
295 {
296
297 a = stopForEnd(xCur, xMerge, bc, ownSpeed, cfm, sli);
298 }
299 }
300 }
301
302
303 if (nCur > 1)
304 {
305 if (xMerge.lt0())
306 {
307
308 Speed vMerge = xCur.minus(xMerge).divideBy(t0.multiplyBy((1 - dCoop) * (nCur - 1)).plus(lc));
309 vMerge = Speed.min(vMerge, x0.divideBy(t0));
310 a = Acceleration.min(a, CarFollowingUtil.approachTargetSpeed(cfm, bc, ownSpeed, sli, xMerge, vMerge));
311 }
312 else
313 {
314
315 Speed speed;
316 if (up != null)
317 {
318 speed = up.getSpeed();
319 }
320 else if (syncVehicle != null)
321 {
322 speed = syncVehicle.getSpeed();
323 }
324 else
325 {
326 speed = ownSpeed;
327 }
328 Length c = requiredBufferSpace(speed, nCur, x0, t0, lc, dCoop);
329 if (xCur.lt(c))
330 {
331 a = Acceleration.min(a, b.neg());
332 }
333 }
334 }
335
336 return a;
337 }
338
339 @Override
340 Acceleration cooperate(final LanePerception perception, final BehavioralCharacteristics bc, final SpeedLimitInfo sli,
341 final CarFollowingModel cfm, final LateralDirectionality lat)
342 throws ParameterException, OperationalPlanException
343 {
344 if ((lat.isLeft() && !perception.getLaneStructure().getCrossSection().contains(RelativeLane.LEFT))
345 || (lat.isRight() && !perception.getLaneStructure().getCrossSection().contains(RelativeLane.RIGHT)))
346 {
347 return new Acceleration(Double.MAX_VALUE, AccelerationUnit.SI);
348 }
349 Acceleration b = bc.getParameter(ParameterTypes.B);
350 Acceleration a = new Acceleration(Double.MAX_VALUE, AccelerationUnit.SI);
351 double dCoop = bc.getParameter(DCOOP);
352 Length x0 = bc.getParameter(ParameterTypes.LOOKAHEAD);
353 Duration t0 = bc.getParameter(ParameterTypes.T0);
354 Speed tagSpeed = x0.divideBy(t0);
355 Speed ownSpeed = perception.getPerceptionCategory(EgoPerception.class).getSpeed();
356 Length ownLength = perception.getPerceptionCategory(EgoPerception.class).getLength();
357 RelativeLane relativeLane = new RelativeLane(lat, 1);
358 SortedSet<HeadwayGTU> targetLeaders =
359 perception.getPerceptionCategory(NeighborsPerception.class).getLeaders(RelativeLane.CURRENT);
360 for (HeadwayGTU leader : removeAllUpstreamOfConflicts(removeAllUpstreamOfConflicts(
361 perception.getPerceptionCategory(NeighborsPerception.class).getLeaders(relativeLane), perception,
362 relativeLane), perception, RelativeLane.CURRENT))
363 {
364 BehavioralCharacteristics bc2 = leader.getBehavioralCharacteristics();
365 double desire = lat.equals(LateralDirectionality.LEFT) && bc2.contains(DRIGHT) ? bc2.getParameter(DRIGHT)
366 : lat.equals(LateralDirectionality.RIGHT) && bc2.contains(DLEFT) ? bc2.getParameter(DLEFT) : 0;
367 if (desire >= dCoop && (perception.getPerceptionCategory(EgoPerception.class).getSpeed().gt0()
368 || leader.getSpeed().gt0() || leader.getDistance().gt0()))
369 {
370 Acceleration aSingle;
371 if (leader.getSpeed().eq0())
372 {
373 HeadwayGTU targetLeader = getTargetLeader(leader, targetLeaders);
374 if (targetLeader == null || LmrsUtil.singleAcceleration(
375 targetLeader.getDistance().minus(leader.getDistance()).minus(leader.getLength()),
376 leader.getSpeed(), targetLeader.getSpeed(), desire, leader.getBehavioralCharacteristics(),
377 leader.getSpeedLimitInfo(), leader.getCarFollowingModel()).gt(b.neg()))
378 {
379
380 aSingle = LmrsUtil.singleAcceleration(leader.getDistance(), ownSpeed, leader.getSpeed(), desire, bc,
381 sli, cfm);
382 }
383 else
384 {
385 aSingle = tagAlongAcceleration(leader, ownSpeed, ownLength, tagSpeed, desire, bc, sli, cfm);
386 }
387 }
388 else
389 {
390 aSingle = tagAlongAcceleration(leader, ownSpeed, ownLength, tagSpeed, desire, bc, sli, cfm);
391 }
392 a = Acceleration.min(a, aSingle);
393 }
394 }
395
396 return Acceleration.max(a, b.neg());
397 }
398
399 };
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414 abstract Acceleration synchronize(LanePerception perception, BehavioralCharacteristics bc, SpeedLimitInfo sli,
415 CarFollowingModel cfm, double desire, LateralDirectionality lat, LmrsData lmrsData)
416 throws ParameterException, OperationalPlanException;
417
418
419
420
421
422
423
424
425
426
427
428
429 abstract Acceleration cooperate(LanePerception perception, BehavioralCharacteristics bc, SpeedLimitInfo sli,
430 CarFollowingModel cfm, LateralDirectionality lat) throws ParameterException, OperationalPlanException;
431
432
433
434
435
436
437
438
439
440 static SortedSet<HeadwayGTU> removeAllUpstreamOfConflicts(final SortedSet<HeadwayGTU> set, final LanePerception perception,
441 final RelativeLane relativeLane) throws OperationalPlanException
442 {
443 if (!perception.contains(IntersectionPerception.class))
444 {
445 return set;
446 }
447 for (HeadwayConflict conflict : perception.getPerceptionCategory(IntersectionPerception.class)
448 .getConflicts(relativeLane))
449 {
450 if (conflict.isCrossing() || conflict.isMerge())
451 {
452 for (HeadwayGTU conflictGtu : conflict.getUpstreamConflictingGTUs())
453 {
454 for (HeadwayGTU gtu : set)
455 {
456 if (conflictGtu.getId().equals(gtu.getId()))
457 {
458 set.remove(gtu);
459 break;
460 }
461 }
462 }
463 }
464 }
465 return set;
466 }
467
468
469
470
471
472
473
474
475
476
477 static Acceleration gentleUrgency(final Acceleration a, final double desire, final BehavioralCharacteristics bc)
478 throws ParameterException
479 {
480 Acceleration b = bc.getParameter(ParameterTypes.B);
481 if (a.si > -b.si)
482 {
483 return a;
484 }
485 double dCoop = bc.getParameter(DCOOP);
486 if (desire < dCoop)
487 {
488 return b.neg();
489 }
490 Acceleration bCrit = bc.getParameter(ParameterTypes.BCRIT);
491 double f = (desire - dCoop) / (1.0 - dCoop);
492 Acceleration lim = Acceleration.interpolate(b.neg(), bCrit.neg(), f);
493 return Acceleration.max(a, lim);
494 }
495
496
497
498
499
500
501
502
503
504 static HeadwayGTU getFollower(final HeadwayGTU gtu, final SortedSet<HeadwayGTU> leaders, final HeadwayGTU follower,
505 final Length ownLength)
506 {
507 HeadwayGTU last = null;
508 for (HeadwayGTU leader : leaders)
509 {
510 if (leader.equals(gtu))
511 {
512 return last == null ? follower : last;
513 }
514 last = leader;
515 }
516 return null;
517 }
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532 static Acceleration tagAlongAcceleration(final HeadwayGTU leader, final Speed followerSpeed, final Length followerLength,
533 final Speed tagSpeed, final double desire, final BehavioralCharacteristics bc, final SpeedLimitInfo sli,
534 final CarFollowingModel cfm) throws ParameterException
535 {
536 double dCoop = bc.getParameter(DCOOP);
537 double tagV = followerSpeed.lt(tagSpeed) ? 1.0 - followerSpeed.si / tagSpeed.si : 0.0;
538 double tagD = desire <= dCoop ? 1.0 : 1.0 - (desire - dCoop) / (1.0 - dCoop);
539 double tagExtent = tagV < tagD ? tagV : tagD;
540
541
542
543
544
545
546
547
548
549
550 Length headwayAdjustment = bc.getParameter(ParameterTypes.S0)
551 .plus(Length.min(followerLength, leader.getLength()).multiplyBy(0.5)).multiplyBy(tagExtent);
552 Acceleration a = LmrsUtil.singleAcceleration(leader.getDistance().plus(headwayAdjustment), followerSpeed,
553 leader.getSpeed(), desire, bc, sli, cfm);
554 return a;
555 }
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576 static boolean canBeAhead(final HeadwayGTU adjacentVehicle, final Length xCur, final int nCur, final Speed ownSpeed,
577 final Length ownLength, final Speed tagSpeed, final double dCoop, final Acceleration bCrit, final Duration tMin,
578 final Duration tMax, final Length x0, final Duration t0, final Duration lc, final double desire)
579 throws ParameterException
580 {
581
582 if (adjacentVehicle
583 .getDistance().gt(
584 adjacentVehicle.getLength()
585 .neg())
586 && ((desire > dCoop && LmrsUtil.singleAcceleration(
587 adjacentVehicle.getDistance().neg().minus(adjacentVehicle.getLength()).minus(ownLength),
588 adjacentVehicle.getSpeed(), ownSpeed, desire, adjacentVehicle.getBehavioralCharacteristics(),
589 adjacentVehicle.getSpeedLimitInfo(), adjacentVehicle.getCarFollowingModel()).gt(bCrit.neg()))
590 || (ownSpeed.lt(tagSpeed) && adjacentVehicle.getSpeed().lt(tagSpeed))))
591 {
592 return true;
593 }
594
595
596
597
598
599
600
601
602
603
604
605
606
607 Length c = requiredBufferSpace(adjacentVehicle.getSpeed(), nCur, x0, t0, lc, dCoop);
608 double t = (xCur.si - c.si) / ownSpeed.si;
609 double xGap = adjacentVehicle.getSpeed().si * (tMin.si + desire * (tMax.si - tMin.si));
610 return 0.0 < t && t < (xCur.si - adjacentVehicle.getDistance().si - ownLength.si - adjacentVehicle.getLength().si - c.si
611 - xGap) / adjacentVehicle.getSpeed().si;
612 }
613
614
615
616
617
618
619
620
621
622
623
624 static Length requiredBufferSpace(final Speed speed, final int nCur, final Length x0, final Duration t0, final Duration lc,
625 final double dCoop)
626 {
627 Length xCrit = speed.multiplyBy(t0);
628 xCrit = Length.max(xCrit, x0);
629 return speed.multiplyBy(lc).plus(xCrit.multiplyBy((nCur - 1.0) * (1.0 - dCoop)));
630 }
631
632
633
634
635
636
637
638
639
640
641
642
643 static Acceleration stopForEnd(final Length xCur, final Length xMerge, final BehavioralCharacteristics bc,
644 final Speed ownSpeed, final CarFollowingModel cfm, final SpeedLimitInfo sli) throws ParameterException
645 {
646 LmrsUtil.setDesiredHeadway(bc, 1.0);
647 Acceleration a = CarFollowingUtil.stop(cfm, bc, ownSpeed, sli, xCur);
648 if (a.lt0())
649 {
650
651 a = Acceleration.max(a, bc.getParameter(ParameterTypes.B).neg());
652
653 if (xMerge.gt0())
654 {
655 a = Acceleration.max(a, CarFollowingUtil.stop(cfm, bc, ownSpeed, sli, xMerge));
656 }
657 }
658 else
659 {
660 a = Acceleration.POSITIVE_INFINITY;
661 }
662 LmrsUtil.resetDesiredHeadway(bc);
663 return a;
664 }
665
666
667
668
669
670
671
672 static HeadwayGTU getTargetLeader(final HeadwayGTU gtu, final SortedSet<HeadwayGTU> leaders)
673 {
674 for (HeadwayGTU leader : leaders)
675 {
676 if (leader.getDistance().gt(gtu.getDistance()))
677 {
678 return leader;
679 }
680 }
681 return null;
682 }
683
684 }