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