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