1   package org.opentrafficsim.road.gtu.lane.perception.mental;
2   
3   import org.djunits.value.vdouble.scalar.Duration;
4   import org.djutils.exceptions.Try;
5   import org.opentrafficsim.base.parameters.ParameterException;
6   import org.opentrafficsim.base.parameters.Parameters;
7   import org.opentrafficsim.core.gtu.GTUException;
8   import org.opentrafficsim.road.gtu.lane.LaneBasedGTU;
9   import org.opentrafficsim.road.gtu.lane.perception.LanePerception;
10  import org.opentrafficsim.road.gtu.lane.perception.RelativeLane;
11  import org.opentrafficsim.road.gtu.lane.perception.categories.neighbors.NeighborsPerception;
12  import org.opentrafficsim.road.gtu.lane.tactical.util.lmrs.LmrsParameters;
13  
14  
15  
16  
17  
18  
19  
20  
21  
22  
23  
24  
25  
26  public class TaskLaneChanging extends TaskHeadwayBased
27  {
28  
29      
30      private final LateralConsideration lateralConsideration;
31  
32      
33  
34  
35  
36      public TaskLaneChanging(final LateralConsideration lateralConsideration)
37      {
38          this.lateralConsideration = lateralConsideration;
39      }
40  
41      
42      @Override
43      protected Duration getHeadway(final LanePerception perception, final LaneBasedGTU gtu, final Parameters parameters)
44              throws ParameterException
45      {
46          NeighborsPerception neighbors = Try.assign(() -> perception.getPerceptionCategory(NeighborsPerception.class),
47                  "NeighborsPerception not available.");
48          double lat = Try.assign(() -> this.lateralConsideration.getConsideration(perception, gtu, parameters),
49                  "Exception during lateral consideration.");
50          RelativeLane lane;
51          if (Math.abs(lat) < 1e-9)
52          {
53              return null;
54          }
55          if (lat < 0.0)
56          {
57              lane = RelativeLane.LEFT;
58              lat = -lat;
59          }
60          else
61          {
62              lane = RelativeLane.RIGHT;
63          }
64          Try.execute(() -> neighbors.updateGtuAlongside(lane.getLateralDirectionality()), "Exception while updating alongside.");
65          if (neighbors.isGtuAlongside(lane.getLateralDirectionality()))
66          {
67              return Duration.ZERO;
68          }
69          Try.execute(() -> neighbors.updateLeaders(lane), "Exception while updating adjacent leaders.");
70          Try.execute(() -> neighbors.updateFollowers(lane), "Exception while updating adjacent followers.");
71          Duration h1 = neighbors.getLeaders(lane).collect(new TaskHeadwayCollector(getSpeed()));
72          Duration h2 = neighbors.getFollowers(lane).collect(new TaskHeadwayCollector(getSpeed()));
73          if (h1 == null)
74          {
75              return h2 == null ? null : h2.divideBy(lat);
76          }
77          if (h2 == null)
78          {
79              return h1 == null ? null : h1.divideBy(lat);
80          }
81          if (h1.eq0() && h2.eq0())
82          {
83              return Duration.ZERO;
84          }
85          return Duration.createSI(h1.si * h2.si / (lat * (h1.si + h2.si)));
86      }
87  
88      
89  
90  
91  
92  
93  
94  
95  
96  
97  
98  
99  
100     public interface LateralConsideration
101     {
102 
103         
104         LateralConsideration DESIRE = new LateralConsideration()
105         {
106             @Override
107             public double getConsideration(final LanePerception perception, final LaneBasedGTU gtu, final Parameters parameters)
108                     throws ParameterException, GTUException
109             {
110                 double dLeft = gtu.getParameters().getParameter(LmrsParameters.DLEFT);
111                 double dRight = gtu.getParameters().getParameter(LmrsParameters.DRIGHT);
112                 if (dLeft > dRight && dLeft > 0.0)
113                 {
114                     return dLeft > 1.0 ? -1.0 : -dLeft;
115                 }
116                 else if (dRight > dLeft && dRight > 0.0)
117                 {
118                     return dRight > 1.0 ? 1.0 : dRight;
119                 }
120                 return 0.0;
121             }
122         };
123 
124         
125 
126 
127 
128 
129 
130 
131 
132 
133 
134         double getConsideration(LanePerception perception, LaneBasedGTU gtu, Parameters parameters)
135                 throws ParameterException, GTUException;
136     }
137 
138 }