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.gtu.GTUDirectionality;
8   import org.opentrafficsim.core.gtu.GTUException;
9   import org.opentrafficsim.core.gtu.GTUType;
10  import org.opentrafficsim.core.gtu.behavioralcharacteristics.BehavioralCharacteristics;
11  import org.opentrafficsim.core.gtu.plan.tactical.TacticalPlanner;
12  import org.opentrafficsim.core.network.Link;
13  import org.opentrafficsim.core.network.LinkDirection;
14  import org.opentrafficsim.core.network.NetworkException;
15  import org.opentrafficsim.core.network.Node;
16  import org.opentrafficsim.core.network.route.Route;
17  import org.opentrafficsim.road.gtu.lane.LaneBasedGTU;
18  import org.opentrafficsim.road.gtu.strategical.AbstractLaneBasedStrategicalPlanner;
19  import org.opentrafficsim.road.gtu.strategical.LaneBasedStrategicalPlanner;
20  import org.opentrafficsim.road.network.lane.CrossSectionElement;
21  import org.opentrafficsim.road.network.lane.CrossSectionLink;
22  import org.opentrafficsim.road.network.lane.Lane;
23  
24  import nl.tudelft.simulation.language.Throw;
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().toSet();
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 (links.size() == 1)
197         {
198             Link link = links.iterator().next();
199             return link.getStartNode().equals(node) ? new LinkDirection(link, GTUDirectionality.DIR_PLUS)
200                 : new LinkDirection(link, GTUDirectionality.DIR_MINUS);
201         }
202 
203         // more than 2 links... We have to check the route!
204         if (this.route == null)
205         {
206             throw new NetworkException("LaneBasedStrategicalRoutePlanner does not have a route");
207         }
208         int i = this.route.getNodes().indexOf(node);
209         if (i == -1)
210         {
211             throw new NetworkException("LaneBasedStrategicalRoutePlanner is asked for a next link coming from "
212                 + previousLink + ", but node " + node + " not in route " + this.route);
213         }
214         if (i == this.route.getNodes().size() - 1)
215         {
216             throw new NetworkException("LaneBasedStrategicalRoutePlanner is asked for a next link coming from "
217                 + previousLink + ", but the GTU reached the last node for route " + this.route);
218         }
219         Node nextNode = this.route.getNode(i + 1);
220 
221         // if (node.getId().contains("68.158"))
222         // {
223         // System.err.println(node + ", route, nextNode = " + nextNode);
224         // }
225 
226         for (Link link : links)
227         {
228             if (link.getStartNode().equals(nextNode) && link.getEndNode().equals(node))
229             {
230                 // if (node.getId().contains("68.158"))
231                 // {
232                 // System.err.println(node + ", returned " + link);
233                 // }
234                 return new LinkDirection(link, GTUDirectionality.DIR_MINUS);
235             }
236             if (link.getEndNode().equals(nextNode) && link.getStartNode().equals(node))
237             {
238                 // if (node.getId().contains("68.158"))
239                 // {
240                 // System.err.println(node + ", route, returned " + link);
241                 // }
242                 return new LinkDirection(link, GTUDirectionality.DIR_PLUS);
243             }
244         }
245         throw new NetworkException("LaneBasedStrategicalRoutePlanner is asked for a next linkcoming from " + previousLink
246             + ", but no link could be found connecting node " + node + " and node " + nextNode + " for route " + this.route);
247     }
248 
249     /** {@inheritDoc} */
250     @Override
251     public final Route getRoute()
252     {
253         return this.route;
254     }
255 
256     /** {@inheritDoc} */
257     @Override
258     public final String toString()
259     {
260         return "LaneBasedStrategicalRoutePlanner [route=" + this.route + ", fixedTacticalPlanner="
261             + this.fixedTacticalPlanner + "]";
262     }
263 
264 }