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