1 package org.opentrafficsim.road.gtu.generator;
2
3 import java.util.HashSet;
4 import java.util.Map;
5 import java.util.Set;
6 import java.util.SortedSet;
7
8 import org.djunits.value.vdouble.scalar.Duration;
9 import org.djunits.value.vdouble.scalar.Length;
10 import org.djunits.value.vdouble.scalar.Speed;
11 import org.djutils.exceptions.Throw;
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.multiplyBy(Duration.createSI(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.multiplyBy(Duration.createSI(1.0));
81 double f = this.headwayFactor(desiredSpeed, desiredHeadway, speed, headway, leader.getLength());
82 headway = headway.multiplyBy(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.multiplyBy(generationSpeed));
96
97 Set<DirectedLanePosition> generationPosition;
98 if (move.eq0() || initialPosition.size() != 1)
99 {
100 generationPosition = initialPosition;
101 }
102 else
103 {
104 generationPosition = new HashSet<>();
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 Map<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 }