1 package org.opentrafficsim.road.gtu.tactical.lmrs;
2
3 import java.util.SortedSet;
4
5 import org.djunits.value.vdouble.scalar.Duration;
6 import org.djunits.value.vdouble.scalar.Length;
7 import org.djunits.value.vdouble.scalar.Speed;
8 import org.djutils.immutablecollections.ImmutableLinkedHashMap;
9 import org.opentrafficsim.base.parameters.ParameterException;
10 import org.opentrafficsim.base.parameters.ParameterTypeDuration;
11 import org.opentrafficsim.base.parameters.ParameterTypeLength;
12 import org.opentrafficsim.base.parameters.ParameterTypes;
13 import org.opentrafficsim.core.gtu.Stateless;
14 import org.opentrafficsim.core.gtu.plan.operational.OperationalPlanException;
15 import org.opentrafficsim.core.network.LateralDirectionality;
16 import org.opentrafficsim.road.gtu.perception.RelativeLane;
17 import org.opentrafficsim.road.gtu.perception.categories.InfrastructurePerception;
18 import org.opentrafficsim.road.gtu.tactical.TacticalContextEgo;
19 import org.opentrafficsim.road.gtu.tactical.util.lmrs.Desire;
20 import org.opentrafficsim.road.gtu.tactical.util.lmrs.MandatoryIncentive;
21 import org.opentrafficsim.road.network.LaneChangeInfo;
22
23
24
25
26
27
28
29
30
31
32
33
34
35 public final class IncentiveRoute implements MandatoryIncentive, Stateless<IncentiveRoute>
36 {
37
38
39 protected static final ParameterTypeLength LOOKAHEAD = ParameterTypes.LOOKAHEAD;
40
41
42 public static final ParameterTypeDuration T0 = ParameterTypes.T0;
43
44
45 public static final IncentiveRoute SINGLETON = new IncentiveRoute();
46
47 @Override
48 public IncentiveRoute get()
49 {
50 return SINGLETON;
51 }
52
53
54
55
56 private IncentiveRoute()
57 {
58
59 }
60
61 @Override
62 public Desire determineDesire(final TacticalContextEgo context,
63 final ImmutableLinkedHashMap<Class<? extends MandatoryIncentive>, Desire> mandatoryDesire)
64 throws ParameterException, OperationalPlanException
65 {
66
67 InfrastructurePerception infra = context.getPerception().getPerceptionCategory(InfrastructurePerception.class);
68 SortedSet<LaneChangeInfo> currentInfo = infra.getLegalLaneChangeInfo(RelativeLane.CURRENT);
69 Length currentFirst = currentInfo.isEmpty() || currentInfo.first().numberOfLaneChanges() == 0 ? Length.POSITIVE_INFINITY
70 : currentInfo.first().remainingDistance();
71 double dCurr = getDesireToLeave(context, RelativeLane.CURRENT);
72
73
74 double dLeft = 0.0;
75 if (context.getPerception().getLaneStructure().exists(RelativeLane.LEFT)
76 && infra.getLegalLaneChangePossibility(RelativeLane.CURRENT, LateralDirectionality.LEFT).neg().lt(currentFirst))
77 {
78
79 dLeft = getDesireToLeave(context, RelativeLane.LEFT);
80
81 dLeft = dLeft < dCurr ? dCurr : dLeft > dCurr ? -dLeft : 0.0;
82 }
83
84
85 double dRigh = 0.0;
86 if (context.getPerception().getLaneStructure().exists(RelativeLane.RIGHT) && infra
87 .getLegalLaneChangePossibility(RelativeLane.CURRENT, LateralDirectionality.RIGHT).neg().lt(currentFirst))
88 {
89
90 dRigh = getDesireToLeave(context, RelativeLane.RIGHT);
91
92 dRigh = dRigh < dCurr ? dCurr : dRigh > dCurr ? -dRigh : 0.0;
93 }
94
95 return new Desire(dLeft, dRigh);
96 }
97
98
99
100
101
102
103
104
105
106 public static double getDesireToLeave(final TacticalContextEgo context, final RelativeLane lane)
107 throws ParameterException, OperationalPlanException
108 {
109 InfrastructurePerception infra = context.getPerception().getPerceptionCategory(InfrastructurePerception.class);
110 Length x0 = context.getParameters().getParameter(LOOKAHEAD);
111 Duration t0 = context.getParameters().getParameter(T0);
112 double dOut = 0.0;
113 if (infra.getCrossSection().contains(lane))
114 {
115 for (LaneChangeInfo info : infra.getLegalLaneChangeInfo(lane))
116 {
117 double d = info.remainingDistance().lt0() ? info.numberOfLaneChanges()
118 : getDesireToLeave(x0, t0, info.remainingDistance(), info.numberOfLaneChanges(), context.getSpeed());
119 dOut = d > dOut ? d : dOut;
120 }
121 }
122 return dOut;
123 }
124
125
126
127
128
129
130
131
132
133
134
135 public static double getDesireToLeave(final Length x0, final Duration t0, final Length x, final int n, final Speed v)
136 throws ParameterException
137 {
138 double d1 = 1 - x.si / (n * x0.si);
139 double d2 = 1 - (x.si / v.si) / (n * t0.si);
140 d1 = d2 > d1 ? d2 : d1;
141 return d1 < 0 ? 0 : d1;
142 }
143
144 @Override
145 public String toString()
146 {
147 return "IncentiveRoute";
148 }
149
150 }