1 package org.opentrafficsim.road.gtu.generator;
2
3 import java.util.Set;
4 import java.util.SortedSet;
5
6 import org.djunits.value.vdouble.scalar.Duration;
7 import org.djunits.value.vdouble.scalar.Length;
8 import org.djunits.value.vdouble.scalar.Speed;
9 import org.djutils.exceptions.Throw;
10 import org.opentrafficsim.core.gtu.GtuException;
11 import org.opentrafficsim.core.network.NetworkException;
12 import org.opentrafficsim.road.gtu.generator.LaneBasedGtuGenerator.Placement;
13 import org.opentrafficsim.road.gtu.generator.LaneBasedGtuGenerator.RoomChecker;
14 import org.opentrafficsim.road.gtu.generator.characteristics.LaneBasedGtuCharacteristics;
15 import org.opentrafficsim.road.gtu.lane.perception.object.PerceivedGtu;
16 import org.opentrafficsim.road.network.lane.Lane;
17 import org.opentrafficsim.road.network.lane.LanePosition;
18
19
20
21
22
23
24
25
26
27
28
29
30
31 public class CfRoomChecker implements RoomChecker
32 {
33
34
35
36
37 public CfRoomChecker()
38 {
39
40 }
41
42 @Override
43 public Placement canPlace(final SortedSet<PerceivedGtu> leaders, final LaneBasedGtuCharacteristics characteristics,
44 final Duration since, final LanePosition initialPosition) throws NetworkException, GtuException
45 {
46 Speed speedLimit = initialPosition.lane().getSpeedLimit(characteristics.getGtuType());
47 Throw.when(speedLimit == null, IllegalStateException.class, "No speed limit could be determined for GtuType %s.",
48 characteristics.getGtuType());
49 Speed desiredSpeed = characteristics.getStrategicalPlannerFactory()
50 .peekDesiredSpeed(characteristics.getGtuType(), speedLimit, characteristics.getMaximumSpeed())
51 .orElse(speedLimit);
52 if (leaders.isEmpty())
53 {
54
55 return new Placement(desiredSpeed, initialPosition);
56 }
57 Length desiredHeadway =
58 characteristics.getStrategicalPlannerFactory().peekDesiredHeadway(characteristics.getGtuType(), desiredSpeed)
59 .orElseGet(() -> desiredSpeed.times(Duration.ofSI(1.0)));
60
61 Length move = Length.POSITIVE_INFINITY;
62 Speed generationSpeed = desiredSpeed;
63 for (PerceivedGtu leader : leaders)
64 {
65 Speed speed = Speed.min(desiredSpeed, leader.getSpeed());
66 Length headway =
67 characteristics.getStrategicalPlannerFactory().peekDesiredHeadway(characteristics.getGtuType(), speed)
68 .orElseGet(() -> desiredSpeed.times(Duration.ofSI(1.0)));
69 double f = headwayFactor(desiredSpeed, desiredHeadway, speed, headway, leader.getLength());
70 headway = headway.times(f);
71 if (leader.getDistance().lt(headway))
72 {
73
74 return Placement.NO;
75 }
76 Length moveToLeader = leader.getDistance().minus(headway);
77 if (moveToLeader.lt(move))
78 {
79 move = moveToLeader;
80 generationSpeed = speed;
81 }
82 }
83 move = Length.min(move, since.times(generationSpeed));
84
85 LanePosition generationPosition;
86 if (move.eq0())
87 {
88 generationPosition = initialPosition;
89 }
90 else
91 {
92 Lane lane = initialPosition.lane();
93 Length position = initialPosition.position();
94 Length canMove = lane.getLength().minus(position);
95 while (canMove.lt(move))
96 {
97 Set<Lane> down = lane.nextLanes(characteristics.getGtuType());
98 if (down.size() != 1)
99 {
100
101 return new Placement(generationSpeed, initialPosition);
102 }
103 else
104 {
105 move = move.minus(canMove);
106 lane = down.iterator().next();
107 position = Length.ZERO;
108 canMove = lane.getLength();
109 }
110 }
111 position = position.plus(move);
112 generationPosition = new LanePosition(lane, position);
113 }
114 return new Placement(generationSpeed, generationPosition);
115 }
116
117
118
119
120
121
122
123
124
125
126 protected double headwayFactor(final Speed desiredSpeed, final Length desiredHeadway, final Speed generationSpeed,
127 final Length generationHeadway, final Length leaderLength)
128 {
129 return 1.0;
130 }
131
132 }