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