1   package org.opentrafficsim.road.gtu.generator;
2   
3   import java.util.LinkedHashSet;
4   import java.util.Set;
5   import java.util.SortedSet;
6   
7   import org.djunits.value.vdouble.scalar.Duration;
8   import org.djunits.value.vdouble.scalar.Length;
9   import org.djunits.value.vdouble.scalar.Speed;
10  import org.djutils.exceptions.Throw;
11  import org.djutils.immutablecollections.ImmutableMap;
12  import org.opentrafficsim.core.gtu.GTUDirectionality;
13  import org.opentrafficsim.core.gtu.GTUException;
14  import org.opentrafficsim.core.network.NetworkException;
15  import org.opentrafficsim.road.gtu.generator.LaneBasedGTUGenerator.Placement;
16  import org.opentrafficsim.road.gtu.generator.LaneBasedGTUGenerator.RoomChecker;
17  import org.opentrafficsim.road.gtu.generator.characteristics.LaneBasedGTUCharacteristics;
18  import org.opentrafficsim.road.gtu.lane.perception.headway.HeadwayGTU;
19  import org.opentrafficsim.road.network.lane.DirectedLanePosition;
20  import org.opentrafficsim.road.network.lane.Lane;
21  
22  
23  
24  
25  
26  
27  
28  
29  
30  
31  
32  
33  
34  
35  public class CFRoomChecker implements RoomChecker
36  {
37  
38      
39      @Override
40      public Placement canPlace(final SortedSet<HeadwayGTU> leaders, final LaneBasedGTUCharacteristics characteristics,
41              final Duration since, final Set<DirectedLanePosition> initialPosition) throws NetworkException, GTUException
42      {
43          Speed speedLimit = null;
44          for (DirectedLanePosition lane : initialPosition)
45          {
46              try
47              {
48                  Speed limit = lane.getLane().getSpeedLimit(characteristics.getGTUType());
49                  if (speedLimit == null || limit.gt(speedLimit))
50                  {
51                      speedLimit = limit;
52                  }
53              }
54              catch (NetworkException exception)
55              {
56                  
57              }
58          }
59          Throw.when(speedLimit == null, IllegalStateException.class, "No speed limit could be determined for GTUType %s.",
60                  characteristics.getGTUType());
61          Speed desiredSpeed = characteristics.getStrategicalPlannerFactory().peekDesiredSpeed(characteristics.getGTUType(),
62                  speedLimit, characteristics.getMaximumSpeed());
63          desiredSpeed = desiredSpeed != null ? desiredSpeed : speedLimit; 
64          if (leaders.isEmpty())
65          {
66              
67              return new Placement(desiredSpeed, initialPosition);
68          }
69          Length desiredHeadway =
70                  characteristics.getStrategicalPlannerFactory().peekDesiredHeadway(characteristics.getGTUType(), desiredSpeed);
71          desiredHeadway = desiredHeadway != null ? desiredHeadway : desiredSpeed.times(Duration.instantiateSI(1.0)); 
72          
73          Length move = Length.POSITIVE_INFINITY;
74          Speed generationSpeed = desiredSpeed;
75          for (HeadwayGTU leader : leaders)
76          {
77              Speed speed = Speed.min(desiredSpeed, leader.getSpeed());
78              Length headway =
79                      characteristics.getStrategicalPlannerFactory().peekDesiredHeadway(characteristics.getGTUType(), speed);
80              headway = headway != null ? headway : speed.times(Duration.instantiateSI(1.0)); 
81              double f = this.headwayFactor(desiredSpeed, desiredHeadway, speed, headway, leader.getLength());
82              headway = headway.times(f);
83              if (leader.getDistance().lt(headway))
84              {
85                  
86                  return Placement.NO;
87              }
88              Length moveToLeader = leader.getDistance().minus(headway);
89              if (moveToLeader.lt(move))
90              {
91                  move = moveToLeader;
92                  generationSpeed = speed;
93              }
94          }
95          move = Length.min(move, since.times(generationSpeed)); 
96          
97          Set<DirectedLanePosition> generationPosition;
98          if (move.eq0() || initialPosition.size() != 1)
99          {
100             generationPosition = initialPosition;
101         }
102         else
103         {
104             generationPosition = new LinkedHashSet<>();
105             for (DirectedLanePosition dirPos : initialPosition)
106             {
107                 Lane lane = dirPos.getLane();
108                 GTUDirectionality dir = dirPos.getGtuDirection();
109                 Length position = dirPos.getPosition();
110                 Length canMove = dir.isPlus() ? lane.getLength().minus(position) : position;
111                 while (canMove.lt(move))
112                 {
113                     ImmutableMap<Lane, GTUDirectionality> down = lane.downstreamLanes(dir, characteristics.getGTUType());
114                     if (down.size() != 1)
115                     {
116                         
117                         return new Placement(generationSpeed, initialPosition);
118                     }
119                     else
120                     {
121                         move = move.minus(canMove);
122                         lane = down.keySet().iterator().next();
123                         dir = down.get(lane);
124                         position = dir.isPlus() ? Length.ZERO : lane.getLength();
125                         canMove = lane.getLength();
126                     }
127                 }
128                 position = dir.isPlus() ? position.plus(move) : position.minus(move);
129                 generationPosition.add(new DirectedLanePosition(lane, position, dir));
130             }
131         }
132         return new Placement(generationSpeed, generationPosition);
133     }
134 
135     
136 
137 
138 
139 
140 
141 
142 
143 
144     protected double headwayFactor(final Speed desiredSpeed, final Length desiredHeadway, final Speed generationSpeed,
145             final Length generationHeadway, final Length leaderLength)
146     {
147         return 1.0;
148     }
149 
150 }