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