1 package org.opentrafficsim.road.gtu.lane.changing;
2
3 import java.util.Collection;
4 import java.util.Map;
5
6 import org.djunits.value.vdouble.scalar.DoubleScalar;
7 import org.opentrafficsim.core.gtu.RelativePosition;
8 import org.opentrafficsim.core.network.LateralDirectionality;
9 import org.opentrafficsim.core.network.NetworkException;
10 import org.opentrafficsim.road.gtu.following.AbstractGTUFollowingModel;
11 import org.opentrafficsim.road.gtu.following.DualAccelerationStep;
12 import org.opentrafficsim.road.gtu.following.GTUFollowingModel;
13 import org.opentrafficsim.road.gtu.following.HeadwayGTU;
14 import org.opentrafficsim.road.gtu.lane.LaneBasedGTU;
15 import org.opentrafficsim.road.network.lane.Lane;
16
17
18
19
20
21
22
23
24
25
26
27
28 public abstract class AbstractLaneChangeModel implements LaneChangeModel
29 {
30
31 @SuppressWarnings("checkstyle:parameternumber")
32 @Override
33 public final LaneMovementStep computeLaneChangeAndAcceleration(final LaneBasedGTU gtu,
34 final Collection<HeadwayGTU> sameLaneGTUs, final Collection<HeadwayGTU> preferredLaneGTUs,
35 final Collection<HeadwayGTU> nonPreferredLaneGTUs, final Speed.Abs speedLimit,
36 final Acceleration.Rel preferredLaneRouteIncentive, final Acceleration.Rel laneChangeThreshold,
37 final Acceleration.Rel nonPreferredLaneRouteIncentive)
38 {
39 try
40 {
41 Map<Lane, Length.Rel> positions = gtu.positions(RelativePosition.REFERENCE_POSITION);
42 Lane lane = positions.keySet().iterator().next();
43 Length.Rel longitudinalPosition = positions.get(lane);
44
45
46 final LateralDirectionality preferred = LateralDirectionality.RIGHT;
47 final LateralDirectionality nonPreferred = LateralDirectionality.LEFT;
48 Lane nonPreferredLane = gtu.bestAccessibleAdjacentLane(lane, nonPreferred, longitudinalPosition);
49 Lane preferredLane = gtu.bestAccessibleAdjacentLane(lane, preferred, longitudinalPosition);
50 GTUFollowingModel gtuFollowingModel = gtu.getGTUFollowingModel();
51 if (null == gtuFollowingModel)
52 {
53 throw new Error("GTU " + gtu + " has null GTUFollowingModel");
54 }
55 DualAccelerationStep straightAccelerationSteps =
56 gtuFollowingModel.computeAcceleration(gtu, sameLaneGTUs, speedLimit);
57 if (straightAccelerationSteps.getLeaderAcceleration().getSI() < -9999)
58 {
59 System.out.println("Problem");
60 gtu.getGTUFollowingModel().computeAcceleration(gtu, sameLaneGTUs, speedLimit);
61 }
62 Acceleration.Abs straightA = applyDriverPersonality(straightAccelerationSteps).plus(laneChangeThreshold);
63 DualAccelerationStep nonPreferrredAccelerationSteps =
64 null == nonPreferredLane ? null : gtu.getGTUFollowingModel().computeAcceleration(gtu, nonPreferredLaneGTUs,
65 speedLimit);
66 if (null != nonPreferrredAccelerationSteps
67 && nonPreferrredAccelerationSteps.getFollowerAcceleration().getSI() < -gtu.getGTUFollowingModel()
68 .maximumSafeDeceleration().getSI())
69 {
70 nonPreferrredAccelerationSteps = AbstractGTUFollowingModel.TOODANGEROUS;
71 }
72 Acceleration.Abs nonPreferredA =
73 null == nonPreferredLane ? null : applyDriverPersonality(nonPreferrredAccelerationSteps);
74 DualAccelerationStep preferredAccelerationSteps =
75 null == preferredLane ? null : gtu.getGTUFollowingModel().computeAcceleration(gtu, preferredLaneGTUs,
76 speedLimit);
77 if (null != preferredAccelerationSteps
78 && preferredAccelerationSteps.getFollowerAcceleration().getSI() < -gtu.getGTUFollowingModel()
79 .maximumSafeDeceleration().getSI())
80 {
81 preferredAccelerationSteps = AbstractGTUFollowingModel.TOODANGEROUS;
82 }
83 Acceleration.Abs preferredA = null == preferredLane ? null : applyDriverPersonality(preferredAccelerationSteps);
84 if (null == preferredA)
85 {
86
87 if (null == nonPreferredA)
88 {
89
90 return new LaneMovementStep(straightAccelerationSteps.getLeaderAccelerationStep(), null);
91 }
92 else
93 {
94
95 if (DoubleScalar.plus(nonPreferredA, nonPreferredLaneRouteIncentive).gt(straightA))
96 {
97
98 return new LaneMovementStep(nonPreferrredAccelerationSteps.getLeaderAccelerationStep(), nonPreferred);
99 }
100 else
101 {
102
103 return new LaneMovementStep(straightAccelerationSteps.getLeaderAccelerationStep(), null);
104 }
105 }
106 }
107
108 if (null == nonPreferredA)
109 {
110
111 if (DoubleScalar.plus(preferredA, preferredLaneRouteIncentive).gt(straightA))
112 {
113
114 return new LaneMovementStep(preferredAccelerationSteps.getLeaderAccelerationStep(), preferred);
115 }
116 else
117 {
118
119 return new LaneMovementStep(straightAccelerationSteps.getLeaderAccelerationStep(), null);
120 }
121 }
122
123 Acceleration.Rel preferredAttractiveness = preferredA.plus(preferredLaneRouteIncentive).minus(straightA);
124 Acceleration.Rel nonPreferredAttractiveness =
125 nonPreferredA.plus(nonPreferredLaneRouteIncentive).minus(straightA);
126 if (preferredAttractiveness.getSI() <= 0 && nonPreferredAttractiveness.getSI() < 0)
127 {
128
129 return new LaneMovementStep(straightAccelerationSteps.getLeaderAccelerationStep(), null);
130
131 }
132 if (preferredAttractiveness.getSI() > 0 && preferredAttractiveness.gt(nonPreferredAttractiveness))
133 {
134
135 return new LaneMovementStep(preferredAccelerationSteps.getLeaderAccelerationStep(), preferred);
136 }
137
138 return new LaneMovementStep(nonPreferrredAccelerationSteps.getLeaderAccelerationStep(), nonPreferred);
139 }
140 catch (NetworkException exception)
141 {
142 exception.printStackTrace();
143 }
144 throw new Error("Cannot happen: computeLaneChangeAndAcceleration failed to decide whether or not to change lane");
145 }
146
147
148
149
150
151
152
153
154
155
156 public abstract Acceleration.Abs applyDriverPersonality(DualAccelerationStep accelerationSteps);
157 }