1 package org.opentrafficsim.road.gtu.lane;
2
3 import java.util.Iterator;
4
5 import org.djunits.value.vdouble.scalar.Angle;
6 import org.djunits.value.vdouble.scalar.Length;
7 import org.djunits.value.vdouble.scalar.Speed;
8 import org.djutils.event.EventListenerMap;
9 import org.djutils.event.EventProducer;
10 import org.djutils.event.EventType;
11 import org.djutils.exceptions.Try;
12 import org.djutils.math.AngleUtil;
13 import org.djutils.metadata.MetaData;
14 import org.djutils.metadata.ObjectDescriptor;
15 import org.opentrafficsim.base.logger.Logger;
16 import org.opentrafficsim.core.gtu.Gtu;
17 import org.opentrafficsim.core.gtu.GtuException;
18 import org.opentrafficsim.core.gtu.plan.operational.OperationalPlanException;
19 import org.opentrafficsim.core.network.Network;
20 import org.opentrafficsim.road.gtu.lane.perception.PerceptionCollectable;
21 import org.opentrafficsim.road.gtu.lane.perception.PerceptionCollectable.UnderlyingDistance;
22 import org.opentrafficsim.road.gtu.lane.perception.RelativeLane;
23 import org.opentrafficsim.road.gtu.lane.perception.categories.neighbors.NeighborsPerception;
24 import org.opentrafficsim.road.gtu.lane.perception.object.PerceivedGtu;
25 import org.opentrafficsim.road.network.lane.object.LaneBasedObject;
26
27
28
29
30
31
32
33
34
35
36
37 public class CollisionDetector extends AbstractLaneBasedMoveChecker implements EventProducer
38 {
39
40
41 public static final EventType COLLISION = new EventType(new MetaData("COLLISION",
42 "Event when a GTU collides into an object", new ObjectDescriptor("GTU", "Colliding GTU", LaneBasedGtu.class),
43 new ObjectDescriptor("Object", "Object that is collided into", LaneBasedObject.class)));
44
45
46 private final EventListenerMap listenerMap = new EventListenerMap();
47
48
49
50
51
52 public CollisionDetector(final Network network)
53 {
54 super(network);
55 }
56
57 @Override
58 public void checkMove(final LaneBasedGtu gtu) throws Exception
59 {
60 try
61 {
62 NeighborsPerception neighbors =
63 gtu.getTacticalPlanner().getPerception().getPerceptionCategory(NeighborsPerception.class);
64 PerceptionCollectable<PerceivedGtu, LaneBasedGtu> leaders = neighbors.getLeaders(RelativeLane.CURRENT);
65 Iterator<UnderlyingDistance<LaneBasedGtu>> gtus = leaders.underlyingWithDistance();
66 if (!gtus.hasNext())
67 {
68 return;
69 }
70 UnderlyingDistance<LaneBasedGtu> leader = gtus.next();
71 if (leader.distance().lt0())
72 {
73 fireEvent(COLLISION, new Object[] {gtu, leader.object()});
74
75
76 }
77 }
78 catch (OperationalPlanException exception)
79 {
80 throw new GtuException(exception);
81 }
82 }
83
84 @Override
85 public EventListenerMap getEventListenerMap()
86 {
87 return this.listenerMap;
88 }
89
90
91
92
93
94 public CollisionDetector logCollisions()
95 {
96 Try.execute(() -> addListener((e) ->
97 {
98 Object[] payload = (Object[]) e.getContent();
99 LaneBasedGtu gtu = (LaneBasedGtu) payload[0];
100 LaneBasedObject object = (LaneBasedObject) payload[1];
101 Speed objectSpeed = object instanceof Gtu otherGtu ? otherGtu.getSpeed() : Speed.ZERO;
102 Speed dv = gtu.getSpeed().minus(objectSpeed);
103 Length distance = Length.ofSI(gtu.getLocation().distance(object.getLocation()));
104 Angle angle = Angle.ofSI(AngleUtil.normalizeAroundZero(object.getDirZ() - gtu.getDirZ()));
105 Logger.ots().info("GTU " + gtu.getId() + " collided with " + object.getId() + " at a point distance of " + distance
106 + " with a speed difference of " + dv + " and and angle of " + angle + ".");
107 }, COLLISION), "Unable to listen to collisions.");
108 return this;
109 }
110
111
112
113
114
115 public CollisionDetector stopCollided()
116 {
117 Try.execute(() -> addListener((e) ->
118 {
119 Object[] payload = (Object[]) e.getContent();
120 LaneBasedGtu gtu = (LaneBasedGtu) payload[0];
121 LaneBasedObject object = (LaneBasedObject) payload[1];
122 gtu.stop();
123 if (object instanceof LaneBasedGtu otherGtu)
124 {
125 otherGtu.stop();
126 }
127 }, COLLISION), "Unable to listen to collisions.");
128 return this;
129 }
130
131
132
133
134
135 public CollisionDetector throwException()
136 {
137 Try.execute(() -> addListener((e) ->
138 {
139 Object[] payload = (Object[]) e.getContent();
140 LaneBasedGtu gtu = (LaneBasedGtu) payload[0];
141 LaneBasedObject object = (LaneBasedObject) payload[1];
142 throw new CollisionException("GTU " + gtu.getId() + " collided with " + object.getId());
143 }, COLLISION), "Unable to listen to collisions.");
144 return this;
145 }
146
147
148
149
150
151 public CollisionDetector destroyGtu()
152 {
153 Try.execute(() -> addListener((e) -> ((LaneBasedGtu) ((Object[]) e.getContent())[0]).destroy(), COLLISION),
154 "Unable to listen to collisions.");
155 return this;
156 }
157
158 }