1 package org.opentrafficsim.road.gtu.lane.tactical.lanechangemobil;
2
3 import java.util.Collection;
4 import java.util.Map;
5
6 import org.djunits.unit.AccelerationUnit;
7 import org.djunits.value.vdouble.scalar.Acceleration;
8 import org.djunits.value.vdouble.scalar.Length;
9 import org.djunits.value.vdouble.scalar.Speed;
10 import org.djunits.value.vdouble.scalar.base.DoubleScalar;
11 import org.opentrafficsim.base.parameters.ParameterException;
12 import org.opentrafficsim.base.parameters.ParameterTypeAcceleration;
13 import org.opentrafficsim.base.parameters.ParameterTypeLength;
14 import org.opentrafficsim.base.parameters.ParameterTypes;
15 import org.opentrafficsim.core.gtu.GtuException;
16 import org.opentrafficsim.core.gtu.RelativePosition;
17 import org.opentrafficsim.core.gtu.plan.operational.OperationalPlanException;
18 import org.opentrafficsim.core.network.LateralDirectionality;
19 import org.opentrafficsim.road.gtu.lane.LaneBasedGtu;
20 import org.opentrafficsim.road.gtu.lane.perception.LanePerception;
21 import org.opentrafficsim.road.gtu.lane.perception.categories.DefaultSimplePerception;
22 import org.opentrafficsim.road.gtu.lane.perception.headway.Headway;
23 import org.opentrafficsim.road.gtu.lane.tactical.AbstractLaneBasedTacticalPlanner;
24 import org.opentrafficsim.road.gtu.lane.tactical.following.AbstractGtuFollowingModelMobil;
25 import org.opentrafficsim.road.gtu.lane.tactical.following.DualAccelerationStep;
26 import org.opentrafficsim.road.gtu.lane.tactical.following.GtuFollowingModelOld;
27 import org.opentrafficsim.road.network.lane.Lane;
28
29
30
31
32
33
34
35
36
37
38 public abstract class AbstractLaneChangeModel implements LaneChangeModel
39 {
40
41
42 protected static final ParameterTypeLength LOOKAHEAD = ParameterTypes.LOOKAHEAD;
43
44
45 protected static final ParameterTypeAcceleration B = ParameterTypes.B;
46
47
48 private static Acceleration extraThreshold = new Acceleration(0.000001, AccelerationUnit.SI);
49
50
51 @SuppressWarnings("checkstyle:parameternumber")
52 @Override
53 public final LaneMovementStep computeLaneChangeAndAcceleration(final LaneBasedGtu gtu,
54 final Collection<Headway> sameLaneGTUs, final Collection<Headway> preferredLaneGTUs,
55 final Collection<Headway> nonPreferredLaneGTUs, final Speed speedLimit,
56 final Acceleration preferredLaneRouteIncentive, final Acceleration laneChangeThreshold,
57 final Acceleration nonPreferredLaneRouteIncentive) throws ParameterException, OperationalPlanException
58 {
59 try
60 {
61 LanePerception perception = gtu.getTacticalPlanner().getPerception();
62 Length headway = gtu.getParameters().getParameter(LOOKAHEAD);
63 Map<Lane, Length> positions = gtu.positions(RelativePosition.REFERENCE_POSITION);
64 Lane lane = positions.keySet().iterator().next();
65 Length longitudinalPosition = positions.get(lane);
66
67
68 final LateralDirectionality preferred = LateralDirectionality.RIGHT;
69 final LateralDirectionality nonPreferred = LateralDirectionality.LEFT;
70 DefaultSimplePerception simplePerception = perception.getPerceptionCategory(DefaultSimplePerception.class);
71 simplePerception.updateAccessibleAdjacentLanes();
72 Lane nonPreferredLane = simplePerception.bestAccessibleAdjacentLane(lane, nonPreferred, longitudinalPosition);
73 Lane preferredLane = simplePerception.bestAccessibleAdjacentLane(lane, preferred, longitudinalPosition);
74 AbstractLaneBasedTacticalPlanner albtp = (AbstractLaneBasedTacticalPlanner) gtu.getTacticalPlanner();
75 if (null == albtp)
76 {
77 throw new NullPointerException(gtu + " returns null for its tactical planner");
78 }
79 GtuFollowingModelOld gtuFollowingModel = (GtuFollowingModelOld) albtp.getCarFollowingModel();
80 if (null == gtuFollowingModel)
81 {
82 throw new NullPointerException(gtu + " has null GtuFollowingModel");
83 }
84 DualAccelerationStep straightAccelerationSteps =
85 gtuFollowingModel.computeDualAccelerationStep(gtu, sameLaneGTUs, headway, speedLimit);
86 if (straightAccelerationSteps.getLeaderAcceleration().getSI() < -9999)
87 {
88 System.out.println("Problem");
89 gtuFollowingModel.computeDualAccelerationStep(gtu, sameLaneGTUs, headway, speedLimit);
90 }
91 Acceleration straightA = applyDriverPersonality(straightAccelerationSteps).plus(laneChangeThreshold);
92 DualAccelerationStep nonPreferredAccelerationSteps = null == nonPreferredLane ? null
93 : gtuFollowingModel.computeDualAccelerationStep(gtu, nonPreferredLaneGTUs, headway, speedLimit);
94 if (null != nonPreferredAccelerationSteps && nonPreferredAccelerationSteps.getFollowerAcceleration()
95 .getSI() < -gtu.getParameters().getParameter(B).getSI())
96 {
97 nonPreferredAccelerationSteps = AbstractGtuFollowingModelMobil.TOODANGEROUS;
98 }
99 Acceleration nonPreferredA =
100 null == nonPreferredLane ? null : applyDriverPersonality(nonPreferredAccelerationSteps);
101 DualAccelerationStep preferredAccelerationSteps = null == preferredLane ? null
102 : gtuFollowingModel.computeDualAccelerationStep(gtu, preferredLaneGTUs, headway, speedLimit);
103 if (null != preferredAccelerationSteps && preferredAccelerationSteps.getFollowerAcceleration()
104 .getSI() < -gtu.getParameters().getParameter(B).getSI())
105 {
106 preferredAccelerationSteps = AbstractGtuFollowingModelMobil.TOODANGEROUS;
107 }
108 Acceleration preferredA = null == preferredLane ? null : applyDriverPersonality(preferredAccelerationSteps);
109 if (null == preferredA)
110 {
111
112 if (null == nonPreferredA)
113 {
114
115 return new LaneMovementStep(straightAccelerationSteps.getLeaderAccelerationStep(), null);
116 }
117 else
118 {
119
120 if (DoubleScalar.plus(nonPreferredA, nonPreferredLaneRouteIncentive).gt(straightA.plus(extraThreshold)))
121 {
122
123 return new LaneMovementStep(nonPreferredAccelerationSteps.getLeaderAccelerationStep(), nonPreferred);
124 }
125 else
126 {
127
128 return new LaneMovementStep(straightAccelerationSteps.getLeaderAccelerationStep(), null);
129 }
130 }
131 }
132
133 if (null == nonPreferredA)
134 {
135
136 if (DoubleScalar.plus(preferredA, preferredLaneRouteIncentive).plus(extraThreshold).ge(straightA))
137 {
138
139 return new LaneMovementStep(preferredAccelerationSteps.getLeaderAccelerationStep(), preferred);
140 }
141 else
142 {
143
144 return new LaneMovementStep(straightAccelerationSteps.getLeaderAccelerationStep(), null);
145 }
146 }
147
148 Acceleration preferredAttractiveness =
149 preferredA.plus(preferredLaneRouteIncentive).minus(straightA).plus(extraThreshold);
150 Acceleration nonPreferredAttractiveness =
151 nonPreferredA.plus(nonPreferredLaneRouteIncentive).minus(straightA).minus(extraThreshold);
152 if (preferredAttractiveness.getSI() < 0 && nonPreferredAttractiveness.getSI() <= 0)
153 {
154
155 return new LaneMovementStep(straightAccelerationSteps.getLeaderAccelerationStep(), null);
156
157 }
158 if (preferredAttractiveness.getSI() >= 0 && preferredAttractiveness.gt(nonPreferredAttractiveness))
159 {
160
161 return new LaneMovementStep(preferredAccelerationSteps.getLeaderAccelerationStep(), preferred);
162 }
163
164 return new LaneMovementStep(nonPreferredAccelerationSteps.getLeaderAccelerationStep(), nonPreferred);
165 }
166 catch (GtuException exception)
167 {
168 throw new RuntimeException(exception);
169 }
170 }
171
172
173
174
175
176
177
178
179
180 public abstract Acceleration applyDriverPersonality(DualAccelerationStep accelerationSteps);
181
182 }