1 package org.opentrafficsim.road.gtu.lane.tactical.cacc;
2
3 import java.util.ArrayList;
4 import java.util.List;
5
6 import org.opentrafficsim.core.gtu.GTU;
7 import org.opentrafficsim.core.network.LateralDirectionality;
8
9 import nl.tudelft.simulation.dsol.SimRuntimeException;
10
11 /**
12 * Platoon meta data.
13 * <p>
14 * Copyright (c) 2013-2017 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/node/13">OpenTrafficSim License</a>.
16 * <p>
17 * @version $Revision$, $LastChangedDate$, by $Author$, initial version 22 okt. 2018 <br>
18 * @author <a href="http://www.tbm.tudelft.nl/averbraeck">Alexander Verbraeck</a>
19 * @author <a href="http://www.tudelft.nl/pknoppers">Peter Knoppers</a>
20 * @author <a href="http://www.transport.citg.tudelft.nl">Wouter Schakel</a>
21 */
22 public class Platoon
23 {
24
25 /** List of GTUs. */
26 private final List<String> gtuList = new ArrayList<>();
27
28 /** Lane change direction. */
29 private LateralDirectionality laneChangeDir = LateralDirectionality.NONE;
30
31 /** List of changed GTUs. */
32 private List<String> changedGtus = new ArrayList<>();
33
34 /**
35 * Adds a GTU to the platoon. This is done by a generator listener.
36 * @param id String; GTU id
37 */
38 public void addGtu(final String id)
39 {
40 this.gtuList.add(id);
41 }
42
43 /**
44 * Returns the size of the platoon.
45 * @return int; size of the platoon
46 */
47 public int size()
48 {
49 return this.gtuList.size();
50 }
51
52 /**
53 * Returns the GTU id of the index
54 * @param index int; index position of gtuList
55 * @return String; id of gtu on index position; NULL is none?
56 */
57 public String getId(int index)
58 {
59 return this.gtuList.get(index);
60 }
61
62 /**
63 * Add a lane change as it's finished. This will reset the lane change when all GTUs in the platoon changed lane.
64 * @param gtu GTU; gtu
65 */
66 public void addLaneChange(final GTU gtu)
67 {
68 this.changedGtus.add(gtu.getId());
69 if (this.changedGtus.size() == size())
70 {
71 // all GTUs in platoon changed
72 try
73 {
74 gtu.getSimulator().scheduleEventNow(this, this, "endLaneChangeProcess", null);
75 }
76 catch (SimRuntimeException exception)
77 {
78 throw new RuntimeException(exception);
79 }
80 }
81 }
82
83 /**
84 * End lane change process.
85 */
86 @SuppressWarnings("unused")
87 private void endLaneChangeProcess()
88 {
89 this.laneChangeDir = LateralDirectionality.NONE;
90 this.changedGtus.clear();
91 }
92
93 /**
94 * Returns whether the platoon is ready for a lane change (i.e. not in the process of a lane change).
95 * @return boolean; whether the platoon is ready for a lane change (i.e. not in the process of a lane change)
96 */
97 public boolean canInitiateLaneChangeProcess()
98 {
99 return this.laneChangeDir.isNone();
100 }
101
102 /**
103 * Initiates a lane change.
104 * @param laneChangeDirection LateralDirectionality; direction of the lane change
105 */
106 public void initiateLaneChange(final LateralDirectionality laneChangeDirection)
107 {
108 this.laneChangeDir = laneChangeDirection;
109 }
110
111 /**
112 * Returns the index of the GTU in the platoon, with the leader {@code 0}.
113 * @param gtuId String; GTU id
114 * @return int; index of the GTU in the platoon, with the leader {@code 0}
115 */
116 public int getIndex(final String gtuId)
117 {
118 return this.gtuList.indexOf(gtuId);
119 }
120
121 /**
122 * Returns whether the GTU is the platoon.
123 * @param gtuId String; GTU id
124 * @return boolean; whether the GTU is the platoon
125 */
126 public boolean isInPlatoon(final String gtuId)
127 {
128 return this.gtuList.contains(gtuId);
129 }
130
131 /**
132 * Returns the direction in which the GTU should change lane.
133 * @param gtuId String; GTU id
134 * @return LateralDirectionality; direction to change to, or {@code NONE}
135 */
136 public LateralDirectionality shouldChangeLane(final String gtuId)
137 {
138 if (this.changedGtus.isEmpty()) // No trucks have changed yet
139 {
140 return size() == (getIndex(gtuId) + 1) ? this.laneChangeDir : LateralDirectionality.NONE;
141 }
142 else if (this.changedGtus.contains(gtuId))
143 {
144 return LateralDirectionality.NONE;
145 }
146 else
147 {
148 return this.laneChangeDir;
149 }
150
151 }
152
153 /**
154 * Returns true when a lane change is in progress.
155 * @return boolean; whether a lane change is currently in progress
156 */
157 public boolean laneChangeInProgress()
158 {
159 return !this.changedGtus.isEmpty();
160 }
161
162 /**
163 * Number of gtus that have changed lanes.
164 * @return int; number of gtus changed lanes currently
165 */
166 public int numberOfChanged()
167 {
168 return this.changedGtus.size();
169 }
170
171 }