1 package org.opentrafficsim.road.gtu.tactical.lmrs;
2
3 import org.djunits.value.vdouble.scalar.Duration;
4 import org.djunits.value.vdouble.scalar.Length;
5 import org.djunits.value.vdouble.scalar.Speed;
6 import org.djutils.draw.point.DirectedPoint2d;
7 import org.opentrafficsim.base.DistancedObject;
8 import org.opentrafficsim.base.parameters.ParameterException;
9 import org.opentrafficsim.base.parameters.ParameterTypes;
10 import org.opentrafficsim.core.gtu.GtuException;
11 import org.opentrafficsim.core.gtu.TurnIndicatorStatus;
12 import org.opentrafficsim.core.gtu.plan.operational.OperationalPlan;
13 import org.opentrafficsim.core.network.NetworkException;
14 import org.opentrafficsim.road.gtu.LaneBasedGtu;
15 import org.opentrafficsim.road.gtu.operational.LaneOperationalPlanBuilder;
16 import org.opentrafficsim.road.gtu.operational.SimpleOperationalPlan;
17 import org.opentrafficsim.road.gtu.perception.LanePerception;
18 import org.opentrafficsim.road.gtu.perception.RelativeLane;
19 import org.opentrafficsim.road.gtu.tactical.Blockable;
20 import org.opentrafficsim.road.gtu.tactical.Synchronizable;
21 import org.opentrafficsim.road.gtu.tactical.TacticalContextEgo;
22 import org.opentrafficsim.road.gtu.tactical.WithDesiredSpeed;
23 import org.opentrafficsim.road.gtu.tactical.following.CarFollowingModel;
24 import org.opentrafficsim.road.gtu.tactical.util.DeadEndUtil;
25 import org.opentrafficsim.road.gtu.tactical.util.LaneChangeNotAllowedUtil;
26 import org.opentrafficsim.road.gtu.tactical.util.lmrs.Cooperation;
27 import org.opentrafficsim.road.gtu.tactical.util.lmrs.GapAcceptance;
28 import org.opentrafficsim.road.gtu.tactical.util.lmrs.LmrsData;
29 import org.opentrafficsim.road.gtu.tactical.util.lmrs.LmrsParameters;
30 import org.opentrafficsim.road.gtu.tactical.util.lmrs.LmrsUtil;
31 import org.opentrafficsim.road.gtu.tactical.util.lmrs.Synchronization;
32 import org.opentrafficsim.road.gtu.tactical.util.lmrs.Tailgating;
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47 public class Lmrs extends AbstractIncentivesTacticalPlanner implements Synchronizable, Blockable, WithDesiredSpeed
48 {
49
50
51 private static final DistancedObject<Length> NO_DEVIATION = new DistancedObject<>(Length.ZERO, Length.ZERO);
52
53
54 private final LmrsData lmrsData;
55
56
57
58
59
60
61
62
63
64
65
66 public Lmrs(final CarFollowingModel carFollowingModel, final LaneBasedGtu gtu, final LanePerception lanePerception,
67 final Synchronization synchronization, final Cooperation cooperation, final GapAcceptance gapAcceptance,
68 final Tailgating tailgating)
69 {
70 super(carFollowingModel, gtu, lanePerception);
71 this.lmrsData = new LmrsData(synchronization, cooperation, gapAcceptance, tailgating);
72 }
73
74 @Override
75 public OperationalPlan generateOperationalPlan(final Duration startTime, final DirectedPoint2d locationAtStartTime)
76 throws GtuException, NetworkException, ParameterException
77 {
78
79 TacticalContextEgo context = new TacticalContextEgo(getGtu());
80
81
82 SimpleOperationalPlan simplePlan = LmrsUtil.determinePlan(context, this.lmrsData, this);
83
84
85 RelativeLane[] lanes;
86 double dLeft = context.getParameters().getParameter(LmrsParameters.DLEFT);
87 double dRight = context.getParameters().getParameter(LmrsParameters.DRIGHT);
88 double dSync = context.getParameters().getParameter(LmrsParameters.DSYNC);
89 if (dLeft >= dSync && dLeft >= dRight)
90 {
91 lanes = new RelativeLane[] {RelativeLane.CURRENT, RelativeLane.LEFT};
92 }
93 else if (dRight >= dSync)
94 {
95 lanes = new RelativeLane[] {RelativeLane.CURRENT, RelativeLane.RIGHT};
96 }
97 else
98 {
99 lanes = new RelativeLane[] {RelativeLane.CURRENT};
100 }
101 for (RelativeLane lane : lanes)
102 {
103 if (getPerception().getLaneStructure().getRootCrossSection().contains(lane))
104 {
105
106
107
108 Length mergeDistance = lane.isCurrent() ? Length.ZERO
109 : Synchronization.getMergeDistance(getPerception(), lane.getLateralDirectionality());
110 simplePlan.minimizeAcceleration(getAcceleration(context, lane, mergeDistance));
111 }
112 }
113
114
115 simplePlan = LaneChangeNotAllowedUtil.preventLaneChange(context, DeadEndUtil.dealWithDeadEnd(context, simplePlan));
116
117
118 context.getIntent(TurnIndicatorStatus.class).ifPresentOrElse((d) -> getGtu().setTurnIndicatorStatus(d.object()),
119 () -> getGtu().setTurnIndicatorStatus(TurnIndicatorStatus.NONE));
120
121
122 return LaneOperationalPlanBuilder.buildPlanFromSimplePlan(getGtu(), simplePlan,
123 getGtu().getParameters().getParameter(ParameterTypes.LCDUR),
124 context.getIntent(Length.class).orElse(NO_DEVIATION));
125
126 }
127
128 @Override
129 public Synchronizable.State getSynchronizationState()
130 {
131 return this.lmrsData.getSynchronizationState();
132 }
133
134 @Override
135 public boolean isBlocking()
136 {
137 for (AccelerationIncentive acc : getAccelerationIncentives())
138 {
139 if (acc instanceof AccelerationConflicts)
140 {
141 return ((AccelerationConflicts) acc).isBlocking();
142 }
143 }
144 return false;
145 }
146
147 @Override
148 public Speed getDesiredSpeed()
149 {
150 return this.lmrsData.getDesiredSpeed();
151 }
152
153 @Override
154 public String toString()
155 {
156 return "LMRS [mandatoryIncentives=" + getMandatoryIncentives() + ", voluntaryIncentives=" + getVoluntaryIncentives()
157 + ", accelerationIncentives = " + getAccelerationIncentives() + "]";
158 }
159
160 }