View Javadoc
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-2024 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://github.com/wjschakel">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.dx());
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-2024 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://github.com/wjschakel">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 }