1 package org.opentrafficsim.road.gtu.lane.perception;
2
3 import java.io.Serializable;
4
5 import org.djunits.value.vdouble.scalar.Length;
6 import org.djutils.exceptions.Throw;
7 import org.opentrafficsim.core.gtu.RelativePosition;
8 import org.opentrafficsim.core.network.LateralDirectionality;
9
10 /**
11 * Contains information by which drivers know when they need to leave a lane in order to be able to stay on the infrastructure
12 * and follow their route.
13 * <p>
14 * Copyright (c) 2013-2023 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved. <br>
15 * BSD-style license. See <a href="https://opentrafficsim.org/docs/license.html">OpenTrafficSim License</a>.
16 * </p>
17 * @author <a href="https://dittlab.tudelft.nl">Wouter Schakel</a>
18 */
19 public class InfrastructureLaneChangeInfo implements Comparable<InfrastructureLaneChangeInfo>, Serializable
20 {
21
22 /** */
23 private static final long serialVersionUID = 20160811L;
24
25 /** Required number of lane changes. */
26 private final int requiredNumberOfLaneChanges;
27
28 /** Record who's end defines the remaining distances. */
29 private final LaneStructureRecord record;
30
31 /** Available length after the start (reference on start). */
32 private final Length afterStartLength;
33
34 /** Whether the need to change lane comes from a dead-end. */
35 private boolean deadEnd;
36
37 /** Lateral directionality of required lane changes. */
38 private final LateralDirectionality lat;
39
40 /**
41 * Constructor for subclasses.
42 * @param requiredNumberOfLaneChanges int; required number of lane changes
43 * @param deadEnd boolean; whether the need to change lane comes from a dead-end
44 */
45 protected InfrastructureLaneChangeInfo(final int requiredNumberOfLaneChanges, final boolean deadEnd)
46 {
47 this.requiredNumberOfLaneChanges = requiredNumberOfLaneChanges;
48 this.record = null;
49 this.deadEnd = deadEnd;
50 this.afterStartLength = null;
51 this.lat = LateralDirectionality.NONE;
52 }
53
54 /**
55 * Constructor.
56 * @param requiredNumberOfLaneChanges int; required number of lane changes
57 * @param record LaneStructureRecord; record who's end defines the remaining distance
58 * @param relativePosition RelativePosition; critical relative position (i.e. nose when driving forward)
59 * @param deadEnd boolean; whether the need to change lane comes from a dead-end
60 * @param lat LateralDirectionality; lateral directionality of required lane changes
61 * @throws IllegalArgumentException if required number of lane changes or remaining distance is negative
62 * @throws NullPointerException if remaining distance is null
63 */
64 public InfrastructureLaneChangeInfo(final int requiredNumberOfLaneChanges, final LaneStructureRecord record,
65 final RelativePosition relativePosition, final boolean deadEnd, final LateralDirectionality lat)
66 {
67 Throw.when(requiredNumberOfLaneChanges < 0, IllegalArgumentException.class,
68 "Required number of lane changes may not be negative.");
69 Throw.whenNull(lat, "Lateral directionality may not be null.");
70 Throw.when(requiredNumberOfLaneChanges != 0 && lat.equals(LateralDirectionality.NONE), IllegalArgumentException.class,
71 "Lateral directionality may not be NONE for non-zero lane changes.");
72 Throw.whenNull(record, "Record may not be null.");
73 this.requiredNumberOfLaneChanges = requiredNumberOfLaneChanges;
74 this.record = record;
75 this.afterStartLength = this.record.getLane().getLength().minus(relativePosition.getDx());
76 this.deadEnd = deadEnd;
77 this.lat = lat;
78 }
79
80 /**
81 * @return requiredNumberOfLaneChanges required number of lane changes.
82 */
83 public final int getRequiredNumberOfLaneChanges()
84 {
85 return this.requiredNumberOfLaneChanges;
86 }
87
88 /**
89 * @return remainingDistance remaining distance to perform required lane changes.
90 */
91 public Length getRemainingDistance()
92 {
93 return this.record.getStartDistance().plus(this.afterStartLength);
94 }
95
96 /**
97 * @return whether this reason to change lane is due to a dead-end.
98 */
99 public final boolean isDeadEnd()
100 {
101 return this.deadEnd;
102 }
103
104 /**
105 * Sets whether this reason to change lane is due to a dead-end.
106 * @param deadEnd boolean; whether the need to change lane comes from a dead-end
107 */
108 public final void setDeadEnd(final boolean deadEnd)
109 {
110 this.deadEnd = deadEnd;
111 }
112
113 /**
114 * Returns the lateral directionality of the required lane changes.
115 * @return LateralDirectionality; lateral directionality of the required lane changes
116 */
117 public final LateralDirectionality getLateralDirectionality()
118 {
119 return this.lat;
120 }
121
122 /** {@inheritDoc} */
123 @SuppressWarnings("checkstyle:designforextension")
124 @Override
125 public String toString()
126 {
127 return "InfrastructureLaneChangeInfo [requiredNumberOfLaneChanges=" + this.requiredNumberOfLaneChanges
128 + ", remainingDistance=" + getRemainingDistance() + "]";
129 }
130
131 /** {@inheritDoc} */
132 @Override
133 public final int compareTo(final InfrastructureLaneChangeInfo infrastructureLaneChangeInfo)
134 {
135 return this.getRemainingDistance().compareTo(infrastructureLaneChangeInfo.getRemainingDistance());
136 }
137
138 /**
139 * Returns lane change info for one lane towards the left.
140 * @param rec LaneStructureRecord; record who's end defines the remaining distance
141 * @param rel RelativePosition; critical relative position (i.e. nose when driving forward)
142 * @param dead boolean; whether the need to change lane comes from a dead-end
143 * @return InfrastructureLaneChangeInfo; lane change info for one lane towards the left
144 */
145 public final InfrastructureLaneChangeInfo left(final LaneStructureRecord rec, final RelativePosition rel,
146 final boolean dead)
147 {
148 return new InfrastructureLaneChangeInfo(this.requiredNumberOfLaneChanges + 1, rec, rel, dead,
149 LateralDirectionality.LEFT);
150 }
151
152 /**
153 * Returns lane change info for one lane towards the right.
154 * @param rec LaneStructureRecord; record who's end defines the remaining distance
155 * @param rel RelativePosition; critical relative position (i.e. nose when driving forward)
156 * @param dead boolean; whether the need to change lane comes from a dead-end
157 * @return InfrastructureLaneChangeInfo; lane change info for one lane towards the right
158 */
159 public final InfrastructureLaneChangeInfo right(final LaneStructureRecord rec, final RelativePosition rel,
160 final boolean dead)
161 {
162 return new InfrastructureLaneChangeInfo(this.requiredNumberOfLaneChanges + 1, rec, rel, dead,
163 LateralDirectionality.RIGHT);
164 }
165
166 /**
167 * Returns an instance for the case the entire lane is inaccessible.
168 * @param deadEnd boolean; dead end
169 * @return instance for the case the entire lane is inaccessible
170 */
171 public static InfrastructureLaneChangeInfo fromInaccessibleLane(final boolean deadEnd)
172 {
173 return new InfrastructureLaneChangeInfoInaccessibleLane(deadEnd);
174 }
175
176 /**
177 * Extension which sets the distance to 0 always, used for fully inaccessible lanes regarding the route.
178 * <p>
179 * Copyright (c) 2013-2023 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved.
180 * <br>
181 * BSD-style license. See <a href="https://opentrafficsim.org/docs/license.html">OpenTrafficSim License</a>.
182 * </p>
183 * @author <a href="https://github.com/averbraeck">Alexander Verbraeck</a>
184 * @author <a href="https://tudelft.nl/staff/p.knoppers-1">Peter Knoppers</a>
185 * @author <a href="https://dittlab.tudelft.nl">Wouter Schakel</a>
186 */
187 private static class InfrastructureLaneChangeInfoInaccessibleLane extends InfrastructureLaneChangeInfo
188 {
189
190 /** */
191 private static final long serialVersionUID = 20180214L;
192
193 /**
194 * @param deadEnd boolean; whether the need to change lane comes from a dead-end
195 */
196 InfrastructureLaneChangeInfoInaccessibleLane(final boolean deadEnd)
197 {
198 super(1, deadEnd);
199 }
200
201 /** {@inheritDoc} */
202 @Override
203 public Length getRemainingDistance()
204 {
205 return Length.ZERO;
206 }
207
208 }
209
210 }