View Javadoc
1   package org.opentrafficsim.road.gtu.strategical.route;
2   
3   import java.io.Serializable;
4   import java.util.Iterator;
5   import java.util.Set;
6   
7   import org.opentrafficsim.core.Throw;
8   import org.opentrafficsim.core.gtu.GTU;
9   import org.opentrafficsim.core.gtu.GTUDirectionality;
10  import org.opentrafficsim.core.gtu.GTUException;
11  import org.opentrafficsim.core.gtu.GTUType;
12  import org.opentrafficsim.core.gtu.behavioralcharacteristics.BehavioralCharacteristics;
13  import org.opentrafficsim.core.gtu.plan.tactical.TacticalPlanner;
14  import org.opentrafficsim.core.network.Link;
15  import org.opentrafficsim.core.network.LinkDirection;
16  import org.opentrafficsim.core.network.NetworkException;
17  import org.opentrafficsim.core.network.Node;
18  import org.opentrafficsim.core.network.route.Route;
19  import org.opentrafficsim.road.gtu.lane.LaneBasedGTU;
20  import org.opentrafficsim.road.gtu.strategical.AbstractLaneBasedStrategicalPlanner;
21  import org.opentrafficsim.road.gtu.strategical.LaneBasedStrategicalPlanner;
22  import org.opentrafficsim.road.network.lane.CrossSectionElement;
23  import org.opentrafficsim.road.network.lane.CrossSectionLink;
24  import org.opentrafficsim.road.network.lane.Lane;
25  
26  /**
27   * Strategical planner, route-based, with personal driving characteristics, which contain settings for the tactical planner. The
28   * tactical planner will only consult the route when the GTU has multiple possibilities on a node, so the route does not have to
29   * be complete. As long as all 'splitting' nodes are part of the route and have a valid successor node (connected by a Link),
30   * the strategical planner is able to make a plan.
31   * <p>
32   * Copyright (c) 2013-2016 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved. <br>
33   * BSD-style license. See <a href="http://opentrafficsim.org/docs/license.html">OpenTrafficSim License</a>.
34   * </p>
35   * $LastChangedDate: 2015-07-24 02:58:59 +0200 (Fri, 24 Jul 2015) $, @version $Revision: 1147 $, by $Author: averbraeck $,
36   * initial version Nov 26, 2015 <br>
37   * @author <a href="http://www.tbm.tudelft.nl/averbraeck">Alexander Verbraeck</a>
38   * @author <a href="http://www.tudelft.nl/pknoppers">Peter Knoppers</a>
39   */
40  public class LaneBasedStrategicalRoutePlanner extends AbstractLaneBasedStrategicalPlanner implements
41      LaneBasedStrategicalPlanner, Serializable
42  {
43      /** */
44      private static final long serialVersionUID = 20150724L;
45  
46      /** The route to drive. */
47      private final Route route;
48  
49      /** The fixed tactical planner to use for the GTU. */
50      private final TacticalPlanner fixedTacticalPlanner;
51  
52      /**
53       * @param behavioralCharacteristics the personal driving characteristics, which contain settings for the tactical planner
54       * @param fixedTacticalPlanner the tactical planner to use for the GTU
55       * @param gtu GTU
56       * @throws GTUException if fixed tactical planner == null
57       */
58      public LaneBasedStrategicalRoutePlanner(final BehavioralCharacteristics behavioralCharacteristics,
59          final TacticalPlanner fixedTacticalPlanner, final LaneBasedGTU gtu) throws GTUException
60      {
61          this(behavioralCharacteristics, fixedTacticalPlanner, null, gtu);
62      }
63  
64      /**
65       * @param behavioralCharacteristics the personal driving characteristics, which contain settings for the tactical planner
66       * @param fixedTacticalPlanner the tactical planner to use for the GTU
67       * @param route the route to drive
68       * @param gtu GTU
69       * @throws GTUException if fixed tactical planner == null
70       */
71      public LaneBasedStrategicalRoutePlanner(final BehavioralCharacteristics behavioralCharacteristics,
72          final TacticalPlanner fixedTacticalPlanner, final Route route, final LaneBasedGTU gtu) throws GTUException
73      {
74          super(behavioralCharacteristics, gtu);
75          this.route = route;
76          this.fixedTacticalPlanner = fixedTacticalPlanner;
77          Throw.when(fixedTacticalPlanner == null, GTUException.class,
78              "Fixed Tactical Planner for a Strategical planner is null");
79      }
80  
81      /** {@inheritDoc} */
82      @Override
83      public TacticalPlanner generateTacticalPlanner()
84      {
85          return this.fixedTacticalPlanner;
86      }
87  
88      /** {@inheritDoc} */
89      @Override
90      public Node nextNode(final Link link, final GTUDirectionality direction, final GTUType gtuType) throws NetworkException
91      {
92          LinkDirection linkDirection = nextLinkDirection(link, direction, gtuType);
93          return linkDirection.getNodeTo();
94      }
95  
96      /** {@inheritDoc} */
97      @Override
98      public LinkDirection nextLinkDirection(final Link link, final GTUDirectionality direction, final GTUType gtuType)
99          throws NetworkException
100     {
101         Node nextNode = direction.equals(GTUDirectionality.DIR_PLUS) ? link.getEndNode() : link.getStartNode();
102         return nextLinkDirection(nextNode, link, gtuType);
103     }
104 
105     /** {@inheritDoc} */
106     @Override
107     public Node nextNode(final Node node, final Link previousLink, final GTUType gtuType) throws NetworkException
108     {
109         LinkDirection linkDirection = nextLinkDirection(node, previousLink, gtuType);
110         return linkDirection.getNodeTo();
111     }
112 
113     /** {@inheritDoc} */
114     @Override
115     public LinkDirection nextLinkDirection(final Node node, final Link previousLink, final GTUType gtuType)
116         throws NetworkException
117     {
118         // if (node.getId().contains("68.158"))
119         // {
120         // System.err.println(node + ", links=" + node.getLinks());
121         // }
122 
123         // if there is no split, don't ask the route
124         if (node.getLinks().size() == 1 && previousLink != null)
125         {
126             // end node
127             throw new NetworkException("LaneBasedStrategicalRoutePlanner is asked for a next link, but node " + node
128                 + " has no successors");
129         }
130         if (node.getLinks().size() == 1 && previousLink == null)
131         {
132             // start node
133             Link link = node.getLinks().iterator().next();
134             return link.getStartNode().equals(node) ? new LinkDirection(link, GTUDirectionality.DIR_PLUS)
135                 : new LinkDirection(link, GTUDirectionality.DIR_MINUS);
136         }
137         if (node.getLinks().size() == 2)
138         {
139             // if (node.getId().contains("68.158"))
140             // {
141             // System.err.println(node + ", size=2");
142             // }
143             for (Link link : node.getLinks())
144             {
145                 if (!link.equals(previousLink))
146                 {
147                     return link.getStartNode().equals(node) ? new LinkDirection(link, GTUDirectionality.DIR_PLUS)
148                         : new LinkDirection(link, GTUDirectionality.DIR_MINUS);
149                 }
150             }
151         }
152 
153         // if we only have one way to go, don't bother about the route yet
154         Set<Link> links = node.getLinks();
155         for (Iterator<Link> linkIterator = links.iterator(); linkIterator.hasNext();)
156         {
157             Link link = linkIterator.next();
158             if (link.equals(previousLink))
159             {
160                 // No u-turn...
161                 linkIterator.remove();
162             }
163             else
164             {
165                 // does the directionality of the link forbid us to go in?
166                 if ((link.getStartNode().equals(node) && link.getDirectionality(gtuType).isBackward())
167                     || (link.getEndNode().equals(node) && link.getDirectionality(gtuType).isForward()))
168                 {
169                     linkIterator.remove();
170                 }
171                 else
172                 {
173                     // are there no lanes from the node into this link in the outgoing direction?
174                     boolean out = false;
175                     CrossSectionLink csLink = (CrossSectionLink) link;
176                     for (CrossSectionElement cse : csLink.getCrossSectionElementList())
177                     {
178                         if (cse instanceof Lane)
179                         {
180                             Lane lane = (Lane) cse;
181                             if ((link.getStartNode().equals(node) && lane.getDirectionality(gtuType).isForwardOrBoth())
182                                 || (link.getEndNode().equals(node) && lane.getDirectionality(gtuType).isBackwardOrBoth()))
183                             {
184                                 out = true;
185                             }
186                         }
187                     }
188                     if (!out)
189                     {
190                         linkIterator.remove();
191                     }
192                 }
193             }
194         }
195 
196         // if (node.getId().contains("68.158"))
197         // {
198         // System.err.println(node + ", cleaning... links = " + links);
199         // }
200 
201         if (links.size() == 1)
202         {
203             Link link = links.iterator().next();
204             return link.getStartNode().equals(node) ? new LinkDirection(link, GTUDirectionality.DIR_PLUS)
205                 : new LinkDirection(link, GTUDirectionality.DIR_MINUS);
206         }
207 
208         // more than 2 links... We have to check the route!
209         if (this.route == null)
210         {
211             throw new NetworkException("LaneBasedStrategicalRoutePlanner does not have a route");
212         }
213         int i = this.route.getNodes().indexOf(node);
214         if (i == -1)
215         {
216             throw new NetworkException("LaneBasedStrategicalRoutePlanner is asked for a next link coming from "
217                 + previousLink + ", but node " + node + " not in route " + this.route);
218         }
219         if (i == this.route.getNodes().size() - 1)
220         {
221             throw new NetworkException("LaneBasedStrategicalRoutePlanner is asked for a next link coming from "
222                 + previousLink + ", but the GTU reached the last node for route " + this.route);
223         }
224         Node nextNode = this.route.getNode(i + 1);
225 
226         // if (node.getId().contains("68.158"))
227         // {
228         // System.err.println(node + ", route, nextNode = " + nextNode);
229         // }
230 
231         for (Link link : links)
232         {
233             if (link.getStartNode().equals(nextNode) && link.getEndNode().equals(node))
234             {
235                 // if (node.getId().contains("68.158"))
236                 // {
237                 // System.err.println(node + ", returned " + link);
238                 // }
239                 return new LinkDirection(link, GTUDirectionality.DIR_MINUS);
240             }
241             if (link.getEndNode().equals(nextNode) && link.getStartNode().equals(node))
242             {
243                 // if (node.getId().contains("68.158"))
244                 // {
245                 // System.err.println(node + ", route, returned " + link);
246                 // }
247                 return new LinkDirection(link, GTUDirectionality.DIR_PLUS);
248             }
249         }
250         throw new NetworkException("LaneBasedStrategicalRoutePlanner is asked for a next linkcoming from " + previousLink
251             + ", but no link could be found connecting node " + node + " and node " + nextNode + " for route " + this.route);
252     }
253 
254     /** {@inheritDoc} */
255     @Override
256     public final Route getRoute()
257     {
258         return this.route;
259     }
260 
261     /** {@inheritDoc} */
262     @Override
263     public final String toString()
264     {
265         return "LaneBasedStrategicalRoutePlanner [route=" + this.route + ", fixedTacticalPlanner="
266             + this.fixedTacticalPlanner + "]";
267     }
268 
269 }