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.headway.HeadwayGtu;
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 @Override
35 public Placement canPlace(final SortedSet<HeadwayGtu> leaders, final LaneBasedGtuCharacteristics characteristics,
36 final Duration since, final LanePosition initialPosition) throws NetworkException, GtuException
37 {
38 Speed speedLimit = initialPosition.lane().getSpeedLimit(characteristics.getGtuType());
39 Throw.when(speedLimit == null, IllegalStateException.class, "No speed limit could be determined for GtuType %s.",
40 characteristics.getGtuType());
41 Speed desiredSpeed = characteristics.getStrategicalPlannerFactory().peekDesiredSpeed(characteristics.getGtuType(),
42 speedLimit, characteristics.getMaximumSpeed());
43 desiredSpeed = desiredSpeed != null ? desiredSpeed : speedLimit;
44 if (leaders.isEmpty())
45 {
46
47 return new Placement(desiredSpeed, initialPosition);
48 }
49 Length desiredHeadway =
50 characteristics.getStrategicalPlannerFactory().peekDesiredHeadway(characteristics.getGtuType(), desiredSpeed);
51 desiredHeadway = desiredHeadway != null ? desiredHeadway : desiredSpeed.times(Duration.instantiateSI(1.0));
52
53 Length move = Length.POSITIVE_INFINITY;
54 Speed generationSpeed = desiredSpeed;
55 for (HeadwayGtu leader : leaders)
56 {
57 Speed speed = Speed.min(desiredSpeed, leader.getSpeed());
58 Length headway =
59 characteristics.getStrategicalPlannerFactory().peekDesiredHeadway(characteristics.getGtuType(), speed);
60 headway = headway != null ? headway : speed.times(Duration.instantiateSI(1.0));
61 double f = this.headwayFactor(desiredSpeed, desiredHeadway, speed, headway, leader.getLength());
62 headway = headway.times(f);
63 if (leader.getDistance().lt(headway))
64 {
65
66 return Placement.NO;
67 }
68 Length moveToLeader = leader.getDistance().minus(headway);
69 if (moveToLeader.lt(move))
70 {
71 move = moveToLeader;
72 generationSpeed = speed;
73 }
74 }
75 move = Length.min(move, since.times(generationSpeed));
76
77 LanePosition generationPosition;
78 if (move.eq0())
79 {
80 generationPosition = initialPosition;
81 }
82 else
83 {
84 Lane lane = initialPosition.lane();
85 Length position = initialPosition.position();
86 Length canMove = lane.getLength().minus(position);
87 while (canMove.lt(move))
88 {
89 Set<Lane> down = lane.nextLanes(characteristics.getGtuType());
90 if (down.size() != 1)
91 {
92
93 return new Placement(generationSpeed, initialPosition);
94 }
95 else
96 {
97 move = move.minus(canMove);
98 lane = down.iterator().next();
99 position = Length.ZERO;
100 canMove = lane.getLength();
101 }
102 }
103 position = position.plus(move);
104 generationPosition = new LanePosition(lane, position);
105 }
106 return new Placement(generationSpeed, generationPosition);
107 }
108
109
110
111
112
113
114
115
116
117
118 protected double headwayFactor(final Speed desiredSpeed, final Length desiredHeadway, final Speed generationSpeed,
119 final Length generationHeadway, final Length leaderLength)
120 {
121 return 1.0;
122 }
123
124 }