1 package org.opentrafficsim.road.network.lane.object;
2
3 import org.djunits.value.vdouble.scalar.Length;
4 import org.djutils.exceptions.Throw;
5 import org.opentrafficsim.core.geometry.OTSLine3D;
6 import org.opentrafficsim.core.network.LongitudinalDirectionality;
7 import org.opentrafficsim.core.network.Network;
8 import org.opentrafficsim.core.network.NetworkException;
9 import org.opentrafficsim.core.object.StaticObject;
10 import org.opentrafficsim.road.network.lane.CrossSectionElement;
11 import org.opentrafficsim.road.network.lane.Lane;
12 import org.opentrafficsim.road.network.lane.object.sensor.SingleSensor;
13
14 import nl.tudelft.simulation.dsol.simulators.SimulatorInterface;
15 import nl.tudelft.simulation.language.d3.DirectedPoint;
16
17 /**
18 * An abstract implementation of the LaneBasedObject interface with the required fields being initialized and getters for those
19 * fields. All StaticObjects are EventProducers, allowing them to provide state changes to subscribers.
20 * <p>
21 * Copyright (c) 2013-2019 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved. <br>
22 * BSD-style license. See <a href="http://opentrafficsim.org/docs/license.html">OpenTrafficSim License</a>.
23 * </p>
24 * $LastChangedDate: 2015-07-24 02:58:59 +0200 (Fri, 24 Jul 2015) $, @version $Revision: 1147 $, by $Author: averbraeck $,
25 * initial version Sep 10, 2016 <br>
26 * @author <a href="http://www.tbm.tudelft.nl/averbraeck">Alexander Verbraeck</a>
27 * @author <a href="http://www.tudelft.nl/pknoppers">Peter Knoppers</a>
28 * @author <a href="http://www.transport.citg.tudelft.nl">Wouter Schakel</a>
29 */
30 public abstract class AbstractLaneBasedObject extends StaticObject implements LaneBasedObject
31 {
32 /** */
33 private static final long serialVersionUID = 20160909L;
34
35 /** The lane for which this is a sensor. */
36 private final Lane lane;
37
38 /** The direction in which this is valid. */
39 private final LongitudinalDirectionality direction;
40
41 /** The position (between 0.0 and the length of the Lane) of the sensor on the design line of the lane. */
42 private final Length longitudinalPosition;
43
44 /** The DirectedPoint that indicates the location on the lane. */
45 private final DirectedPoint location;
46
47 /**
48 * Construct a new AbstractLanebasedObject with the required fields.
49 * @param id String; the id of the new object
50 * @param lane Lane; The lane on which the new object resides. If the new object is a Sensor; it is automatically registered
51 * on the lane
52 * @param direction LongitudinalDirectionality; the directionality in which this is valid.
53 * @param longitudinalPosition Length; The position (between 0.0 and the length of the Lane) of the sensor on the design
54 * line of the lane
55 * @param geometry OTSLine3D; the geometry of the object, which provides its location and bounds as well
56 * @param height Length; the height of the object, in case it is a 3D object
57 * @throws NetworkException when the position on the lane is out of bounds
58 */
59 public AbstractLaneBasedObject(final String id, final Lane lane, final LongitudinalDirectionality direction,
60 final Length longitudinalPosition, final OTSLine3D geometry, final Length height) throws NetworkException
61 {
62 super(id, geometry, height);
63
64 Throw.whenNull(lane, "lane is null");
65 Throw.whenNull(direction, "Longitudinal direction is null");
66 Throw.whenNull(longitudinalPosition, "longitudinal position is null");
67 Throw.when(longitudinalPosition.si < 0.0 || longitudinalPosition.si > lane.getCenterLine().getLengthSI(),
68 NetworkException.class, "Position of the object on the lane is out of bounds");
69
70 this.lane = lane;
71 this.direction = direction;
72 this.longitudinalPosition = longitudinalPosition;
73 DirectedPoint p = lane.getCenterLine().getLocationExtended(this.longitudinalPosition);
74 this.location = new DirectedPoint(p.x, p.y, p.z + 0.01, p.getRotX(), p.getRotY(), p.getRotZ());
75
76 // OTS-218: sensors register themselves.
77 if (!(this instanceof SingleSensor))
78 {
79 this.lane.addLaneBasedObject(this); // implements OTS-218
80 }
81 }
82
83 /**
84 * Construct a new AbstractLanebasedObject with the required fields.
85 * @param id String; the id of the new object
86 * @param lane Lane; The lane on which the new object resides. If the new object is a Sensor; it is automatically registered
87 * on the lane
88 * @param longitudinalPosition Length; The position (between 0.0 and the length of the Lane) of the sensor on the design
89 * line of the lane
90 * @param geometry OTSLine3D; the geometry of the object, which provides its location and bounds as well
91 * @param height Length; the height of the object, in case it is a 3D object
92 * @throws NetworkException when the position on the lane is out of bounds
93 */
94 public AbstractLaneBasedObject(final String id, final Lane lane, final Length longitudinalPosition,
95 final OTSLine3D geometry, final Length height) throws NetworkException
96 {
97 this(id, lane, LongitudinalDirectionality.DIR_BOTH, longitudinalPosition, geometry, height);
98 }
99
100 /**
101 * Construct a new LaneBasedObject with the required fields.
102 * @param id String; the id of the new AbstractLaneBasedObject
103 * @param lane Lane; The lane for which this is a sensor
104 * @param direction LongitudinalDirectionality; the directionality in which this is valid.
105 * @param longitudinalPosition Length; The position (between 0.0 and the length of the Lane) of the sensor on the design
106 * line of the lane
107 * @param geometry OTSLine3D; the geometry of the object, which provides its location and bounds as well
108 * @throws NetworkException when the position on the lane is out of bounds
109 */
110 public AbstractLaneBasedObject(final String id, final Lane lane, final LongitudinalDirectionality direction,
111 final Length longitudinalPosition, final OTSLine3D geometry) throws NetworkException
112 {
113 this(id, lane, direction, longitudinalPosition, geometry, Length.ZERO);
114 }
115
116 /**
117 * Construct a new LaneBasedObject with the required fields.
118 * @param id String; the id of the new AbstractLaneBasedObject
119 * @param lane Lane; The lane for which this is a sensor
120 * @param longitudinalPosition Length; The position (between 0.0 and the length of the Lane) of the sensor on the design
121 * line of the lane
122 * @param geometry OTSLine3D; the geometry of the object, which provides its location and bounds as well
123 * @throws NetworkException when the position on the lane is out of bounds
124 */
125 public AbstractLaneBasedObject(final String id, final Lane lane, final Length longitudinalPosition,
126 final OTSLine3D geometry) throws NetworkException
127 {
128 this(id, lane, longitudinalPosition, geometry, Length.ZERO);
129 }
130
131 /** {@inheritDoc} */
132 @Override
133 public final String getFullId()
134 {
135 return getLane().getFullId() + "." + super.getId();
136 }
137
138 /** {@inheritDoc} */
139 @Override
140 public final Lane getLane()
141 {
142 return this.lane;
143 }
144
145 /** {@inheritDoc} */
146 @Override
147 public final LongitudinalDirectionality getDirection()
148 {
149 return this.direction;
150 }
151
152 /** {@inheritDoc} */
153 @Override
154 public final Length getLongitudinalPosition()
155 {
156 return this.longitudinalPosition;
157 }
158
159 /** {@inheritDoc} */
160 @Override
161 @SuppressWarnings("checkstyle:designforextension")
162 public DirectedPoint getLocation()
163 {
164 return this.location;
165 }
166
167 /** {@inheritDoc} */
168 @Override
169 public final StaticObject clone(final Network newNetwork, final SimulatorInterface.TimeDoubleUnit newSimulator,
170 final boolean animation) throws NetworkException
171 {
172 throw new NetworkException("LaneBasedObjects should be cloned with the clone(lane, simulator, animation) method");
173 }
174
175 /** {@inheritDoc} */
176 @Override
177 @SuppressWarnings("checkstyle:designforextension")
178 public String toString()
179 {
180 return "LaneBasedObject[" + getId() + "]";
181 }
182
183 /**
184 * Clone the LaneBasedObject for e.g., copying a network.
185 * @param newCSE CrossSectionElement; the new cross section element to which the clone belongs
186 * @param newSimulator SimulatorInterface.TimeDoubleUnit; the new simulator for this network
187 * @return AbstractLaneBasedObject; a clone of this object
188 * @throws NetworkException in case the cloning fails
189 */
190 @SuppressWarnings("checkstyle:designforextension")
191 public abstract AbstractLaneBasedObject clone(CrossSectionElement newCSE, SimulatorInterface.TimeDoubleUnit newSimulator)
192 throws NetworkException;
193
194 }