1 package org.opentrafficsim.road.gtu.strategical.route;
2
3 import java.util.Iterator;
4 import java.util.Set;
5
6 import org.opentrafficsim.core.gtu.GTU;
7 import org.opentrafficsim.core.gtu.GTUDirectionality;
8 import org.opentrafficsim.core.gtu.GTUType;
9 import org.opentrafficsim.core.gtu.plan.tactical.TacticalPlanner;
10 import org.opentrafficsim.core.network.Link;
11 import org.opentrafficsim.core.network.LinkDirection;
12 import org.opentrafficsim.core.network.NetworkException;
13 import org.opentrafficsim.core.network.Node;
14 import org.opentrafficsim.core.network.route.Route;
15 import org.opentrafficsim.road.gtu.lane.driver.LaneBasedBehavioralCharacteristics;
16 import org.opentrafficsim.road.gtu.strategical.AbstractLaneBasedStrategicalPlanner;
17 import org.opentrafficsim.road.gtu.strategical.LaneBasedStrategicalPlanner;
18 import org.opentrafficsim.road.network.lane.CrossSectionElement;
19 import org.opentrafficsim.road.network.lane.CrossSectionLink;
20 import org.opentrafficsim.road.network.lane.Lane;
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36 public class LaneBasedStrategicalRoutePlanner extends AbstractLaneBasedStrategicalPlanner implements
37 LaneBasedStrategicalPlanner
38 {
39
40 private final Route route;
41
42
43 private final TacticalPlanner fixedTacticalPlanner;
44
45
46
47
48
49 public LaneBasedStrategicalRoutePlanner(LaneBasedBehavioralCharacteristics drivingCharacteristics,
50 final TacticalPlanner fixedTacticalPlanner)
51 {
52 this(drivingCharacteristics, fixedTacticalPlanner, null);
53 }
54
55
56
57
58
59
60 public LaneBasedStrategicalRoutePlanner(LaneBasedBehavioralCharacteristics drivingCharacteristics,
61 final TacticalPlanner fixedTacticalPlanner, final Route route)
62 {
63 super(drivingCharacteristics);
64 this.route = route;
65 this.fixedTacticalPlanner = fixedTacticalPlanner;
66 }
67
68
69 @Override
70 public TacticalPlanner generateTacticalPlanner(final GTU gtu)
71 {
72 return this.fixedTacticalPlanner;
73 }
74
75
76 @Override
77 public Node nextNode(final Link link, final GTUDirectionality direction, final GTUType gtuType) throws NetworkException
78 {
79 LinkDirection linkDirection = nextLinkDirection(link, direction, gtuType);
80 return linkDirection.getNodeTo();
81 }
82
83
84 @Override
85 public LinkDirection nextLinkDirection(final Link link, final GTUDirectionality direction, final GTUType gtuType)
86 throws NetworkException
87 {
88 Node lastNode = direction.equals(GTUDirectionality.DIR_PLUS) ? link.getEndNode() : link.getStartNode();
89 return nextLinkDirection(lastNode, link, gtuType);
90 }
91
92
93 @Override
94 public Node nextNode(final Node node, final Link previousLink, final GTUType gtuType) throws NetworkException
95 {
96 LinkDirection linkDirection = nextLinkDirection(node, previousLink, gtuType);
97 return linkDirection.getNodeTo();
98 }
99
100
101 @Override
102 public LinkDirection nextLinkDirection(final Node node, final Link previousLink, final GTUType gtuType)
103 throws NetworkException
104 {
105
106
107
108
109
110
111 if (node.getLinks().size() == 1 && previousLink != null)
112 {
113
114 throw new NetworkException("LaneBasedStrategicalRoutePlanner is asked for a next link, but node " + node
115 + " has no successors");
116 }
117 if (node.getLinks().size() == 1 && previousLink == null)
118 {
119
120 Link link = node.getLinks().iterator().next();
121 return link.getStartNode().equals(node) ? new LinkDirection(link, GTUDirectionality.DIR_PLUS) : new LinkDirection(
122 link, GTUDirectionality.DIR_MINUS);
123 }
124 if (node.getLinks().size() == 2)
125 {
126
127
128
129
130 for (Link link : node.getLinks())
131 {
132 if (!link.equals(previousLink))
133 {
134 return link.getStartNode().equals(node) ? new LinkDirection(link, GTUDirectionality.DIR_PLUS)
135 : new LinkDirection(link, GTUDirectionality.DIR_MINUS);
136 }
137 }
138 }
139
140
141 Set<Link> links = node.getLinks();
142 for (Iterator<Link> linkIterator = links.iterator(); linkIterator.hasNext();)
143 {
144 Link link = linkIterator.next();
145 if (link.equals(previousLink))
146 {
147
148 linkIterator.remove();
149 }
150 else
151 {
152
153 if ((link.getStartNode().equals(node) && link.getDirectionality(gtuType).isBackward())
154 || (link.getEndNode().equals(node) && link.getDirectionality(gtuType).isForward()))
155 {
156 linkIterator.remove();
157 }
158 else
159 {
160
161 boolean out = false;
162 CrossSectionLink csLink = (CrossSectionLink) link;
163 for (CrossSectionElement cse : csLink.getCrossSectionElementList())
164 {
165 if (cse instanceof Lane)
166 {
167 Lane lane = (Lane) cse;
168 if ((link.getStartNode().equals(node) && lane.getDirectionality(gtuType).isForwardOrBoth())
169 || (link.getEndNode().equals(node) && lane.getDirectionality(gtuType).isBackwardOrBoth()))
170 {
171 out = true;
172 }
173 }
174 }
175 if (!out)
176 {
177 linkIterator.remove();
178 }
179 }
180 }
181 }
182
183
184
185
186
187
188 if (links.size() == 1)
189 {
190 Link link = links.iterator().next();
191 return link.getStartNode().equals(node) ? new LinkDirection(link, GTUDirectionality.DIR_PLUS) : new LinkDirection(
192 link, GTUDirectionality.DIR_MINUS);
193 }
194
195
196 if (this.route == null)
197 {
198 throw new NetworkException("LaneBasedStrategicalRoutePlanner does not have a route");
199 }
200 int i = this.route.getNodes().indexOf(node);
201 if (i == -1)
202 {
203 throw new NetworkException("LaneBasedStrategicalRoutePlanner is asked for a next link coming from " + previousLink
204 + ", but node " + node + " not in route " + this.route);
205 }
206 if (i == this.route.getNodes().size() - 1)
207 {
208 throw new NetworkException("LaneBasedStrategicalRoutePlanner is asked for a next link coming from " + previousLink
209 + ", but the GTU reached the last node for route " + this.route);
210 }
211 Node nextNode = this.route.getNode(i + 1);
212
213
214
215
216
217
218 for (Link link : links)
219 {
220 if (link.getStartNode().equals(nextNode) && link.getEndNode().equals(node))
221 {
222
223
224
225
226 return new LinkDirection(link, GTUDirectionality.DIR_MINUS);
227 }
228 if (link.getEndNode().equals(nextNode) && link.getStartNode().equals(node))
229 {
230
231
232
233
234 return new LinkDirection(link, GTUDirectionality.DIR_PLUS);
235 }
236 }
237 throw new NetworkException("LaneBasedStrategicalRoutePlanner is asked for a next linkcoming from " + previousLink
238 + ", but no link could be found connecting node " + node + " and node " + nextNode + " for route " + this.route);
239 }
240
241
242
243
244 public final Route getRoute()
245 {
246 return this.route;
247 }
248
249 }