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