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