View Javadoc
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   * Strategical planner, route-based, with personal driving characteristics, which contain settings for the tactical planner. The
24   * tactical planner will only consult the route when the GTU has multiple possibilities on a node, so the route does not have to
25   * be complete. As long as all 'splitting' nodes are part of the route and have a valid successor node (connected by a Link),
26   * the strategical planner is able to make a plan.
27   * <p>
28   * Copyright (c) 2013-2015 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved. <br>
29   * BSD-style license. See <a href="http://opentrafficsim.org/docs/license.html">OpenTrafficSim License</a>.
30   * </p>
31   * $LastChangedDate: 2015-07-24 02:58:59 +0200 (Fri, 24 Jul 2015) $, @version $Revision: 1147 $, by $Author: averbraeck $,
32   * initial version Nov 26, 2015 <br>
33   * @author <a href="http://www.tbm.tudelft.nl/averbraeck">Alexander Verbraeck</a>
34   * @author <a href="http://www.tudelft.nl/pknoppers">Peter Knoppers</a>
35   */
36  public class LaneBasedStrategicalRoutePlanner extends AbstractLaneBasedStrategicalPlanner implements
37          LaneBasedStrategicalPlanner
38  {
39      /** The route to drive. */
40      private final Route route;
41  
42      /** The fixed tactical planner to use for the GTU. */
43      private final TacticalPlanner fixedTacticalPlanner;
44  
45      /**
46       * @param drivingCharacteristics the personal driving characteristics, which contain settings for the tactical planner
47       * @param fixedTacticalPlanner the tactical planner to use for the GTU
48       */
49      public LaneBasedStrategicalRoutePlanner(LaneBasedBehavioralCharacteristics drivingCharacteristics,
50              final TacticalPlanner fixedTacticalPlanner)
51      {
52          this(drivingCharacteristics, fixedTacticalPlanner, null);
53      }
54  
55      /**
56       * @param drivingCharacteristics the personal driving characteristics, which contain settings for the tactical planner
57       * @param fixedTacticalPlanner the tactical planner to use for the GTU
58       * @param route the route to drive
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      /** {@inheritDoc} */
69      @Override
70      public TacticalPlanner generateTacticalPlanner(final GTU gtu)
71      {
72          return this.fixedTacticalPlanner;
73      }
74  
75      /** {@inheritDoc} */
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      /** {@inheritDoc} */
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      /** {@inheritDoc} */
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     /** {@inheritDoc} */
101     @Override
102     public LinkDirection nextLinkDirection(final Node node, final Link previousLink, final GTUType gtuType)
103             throws NetworkException
104     {
105         // if (node.getId().contains("68.158"))
106         // {
107         // System.err.println(node + ", links=" + node.getLinks());
108         // }
109 
110         // if there is no split, don't ask the route
111         if (node.getLinks().size() == 1 && previousLink != null)
112         {
113             // end node
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             // start node
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             // if (node.getId().contains("68.158"))
127             // {
128             // System.err.println(node + ", size=2");
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         // if we only have one way to go, don't bother about the route yet
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                 // No u-turn...
148                 linkIterator.remove();
149             }
150             else
151             {
152                 // does the directionality of the link forbid us to go in?
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                     // are there no lanes from the node into this link in the outgoing direction?
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         // if (node.getId().contains("68.158"))
184         // {
185         // System.err.println(node + ", cleaning... links = " + links);
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         // more than 2 links... We have to check the route!
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         // if (node.getId().contains("68.158"))
214         // {
215         // System.err.println(node + ", route, nextNode = " + nextNode);
216         // }
217 
218         for (Link link : links)
219         {
220             if (link.getStartNode().equals(nextNode) && link.getEndNode().equals(node))
221             {
222                 // if (node.getId().contains("68.158"))
223                 // {
224                 // System.err.println(node + ", returned " + link);
225                 // }
226                 return new LinkDirection(link, GTUDirectionality.DIR_MINUS);
227             }
228             if (link.getEndNode().equals(nextNode) && link.getStartNode().equals(node))
229             {
230                 // if (node.getId().contains("68.158"))
231                 // {
232                 // System.err.println(node + ", route, returned " + link);
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      * @return the route
243      */
244     public final Route getRoute()
245     {
246         return this.route;
247     }
248 
249 }