AbstractSensor.java

  1. package org.opentrafficsim.road.network.lane.object.sensor;

  2. import java.util.HashSet;
  3. import java.util.Set;

  4. import nl.tudelft.simulation.immutablecollections.ImmutableHashSet;
  5. import nl.tudelft.simulation.immutablecollections.ImmutableSet;
  6. import nl.tudelft.simulation.language.Throw;
  7. import nl.tudelft.simulation.language.d3.DirectedPoint;

  8. import org.djunits.value.vdouble.scalar.Length;
  9. import org.opentrafficsim.core.dsol.OTSDEVSSimulatorInterface;
  10. import org.opentrafficsim.core.dsol.OTSSimulatorInterface;
  11. import org.opentrafficsim.core.geometry.OTSGeometryException;
  12. import org.opentrafficsim.core.geometry.OTSLine3D;
  13. import org.opentrafficsim.core.geometry.OTSPoint3D;
  14. import org.opentrafficsim.core.gtu.GTUType;
  15. import org.opentrafficsim.core.gtu.RelativePosition;
  16. import org.opentrafficsim.core.network.NetworkException;
  17. import org.opentrafficsim.road.gtu.lane.LaneBasedGTU;
  18. import org.opentrafficsim.road.network.lane.CrossSectionElement;
  19. import org.opentrafficsim.road.network.lane.Lane;
  20. import org.opentrafficsim.road.network.lane.object.AbstractLaneBasedObject;

  21. /**
  22.  * <p>
  23.  * Copyright (c) 2013-2016 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved. <br>
  24.  * BSD-style license. See <a href="http://opentrafficsim.org/docs/license.html">OpenTrafficSim License</a>.
  25.  * <p>
  26.  * $LastChangedDate: 2015-09-14 01:33:02 +0200 (Mon, 14 Sep 2015) $, @version $Revision: 1401 $, by $Author: averbraeck $,
  27.  * initial version Dec 31, 2014 <br>
  28.  * @author <a href="http://www.tbm.tudelft.nl/averbraeck">Alexander Verbraeck</a>
  29.  * @author <a href="http://www.tudelft.nl/pknoppers">Peter Knoppers</a>
  30.  */
  31. public abstract class AbstractSensor extends AbstractLaneBasedObject implements SingleSensor
  32. {
  33.     /** */
  34.     private static final long serialVersionUID = 20141231L;

  35.     /** The relative position of the vehicle that triggers the sensor. */
  36.     private final RelativePosition.TYPE positionType;

  37.     /** The simulator for being able to generate an animation. */
  38.     private final OTSDEVSSimulatorInterface simulator;

  39.     /** The GTU types will trigger this particular sensor. */
  40.     private final ImmutableSet<GTUType> triggeringGTUTypes;

  41.     /** The immutable set for all gtu type. Implements OTS-219. */
  42.     protected static final ImmutableSet<GTUType> GTUTYPE_SET_ALL;

  43.     static
  44.     {
  45.         Set<GTUType> gtuTypeSet = new HashSet<>();
  46.         gtuTypeSet.add(GTUType.ALL);
  47.         GTUTYPE_SET_ALL = new ImmutableHashSet<GTUType>(gtuTypeSet);

  48.     }

  49.     /**
  50.      * Create a sensor on a lane at a position on that lane.
  51.      * @param id String; the id of the sensor.
  52.      * @param lane Lane; the lane for which this is a sensor.
  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 positionType RelativePosition.TYPE; the relative position type (e.g., FRONT, BACK) of the vehicle that triggers
  56.      *            the sensor.
  57.      * @param simulator OTSDEVSSimulatorInterface; the simulator (needed to generate the animation).
  58.      * @param geometry OTSLine3D; the geometry of the object, which provides its location and bounds as well
  59.      * @param elevation Length; elevation of the sensor
  60.      * @param triggeringGTUTypes ImmutableSet&lt;GTUType&gt;; The GTU types will trigger this particular sensor
  61.      * @throws NetworkException when the position on the lane is out of bounds
  62.      */
  63.     public AbstractSensor(final String id, final Lane lane, final Length longitudinalPosition,
  64.             final RelativePosition.TYPE positionType, final OTSDEVSSimulatorInterface simulator, final OTSLine3D geometry,
  65.             final Length elevation, final ImmutableSet<GTUType> triggeringGTUTypes) throws NetworkException
  66.     {
  67.         super(id, lane, longitudinalPosition, geometry, elevation);
  68.         Throw.when(simulator == null, NullPointerException.class, "simulator is null");
  69.         Throw.when(positionType == null, NullPointerException.class, "positionType is null");
  70.         Throw.when(id == null, NullPointerException.class, "id is null");
  71.         this.positionType = positionType;
  72.         this.simulator = simulator;
  73.         this.triggeringGTUTypes = triggeringGTUTypes;
  74.         getLane().addSensor(this); // Implements OTS-218
  75.     }

  76.     /**
  77.      * Create a sensor on a lane at a position on that lane at elevation <code>Sensor.DEFAULT_SENSOR_ELEVATION</code>.
  78.      * @param id String; the id of the sensor.
  79.      * @param lane Lane; the lane for which this is a sensor.
  80.      * @param longitudinalPosition Length; the position (between 0.0 and the length of the Lane) of the sensor on the design
  81.      *            line of the lane.
  82.      * @param positionType RelativePosition.TYPE; the relative position type (e.g., FRONT, BACK) of the vehicle that triggers
  83.      *            the sensor.
  84.      * @param simulator OTSDEVSSimulatorInterface; the simulator (needed to generate the animation).
  85.      * @param geometry OTSLine3D; the geometry of the object, which provides its location and bounds as well
  86.      * @param triggeringGTUTypes ImmutableSet&lt;GTUType&gt;; The GTU types will trigger this particular sensor
  87.      * @throws NetworkException when the position on the lane is out of bounds
  88.      */
  89.     public AbstractSensor(final String id, final Lane lane, final Length longitudinalPosition,
  90.             final RelativePosition.TYPE positionType, final OTSDEVSSimulatorInterface simulator, final OTSLine3D geometry,
  91.             final ImmutableSet<GTUType> triggeringGTUTypes) throws NetworkException
  92.     {
  93.         super(id, lane, longitudinalPosition, geometry, DEFAULT_SENSOR_ELEVATION);
  94.         Throw.when(simulator == null, NullPointerException.class, "simulator is null");
  95.         Throw.when(positionType == null, NullPointerException.class, "positionType is null");
  96.         Throw.when(id == null, NullPointerException.class, "id is null");
  97.         this.positionType = positionType;
  98.         this.simulator = simulator;
  99.         this.triggeringGTUTypes = triggeringGTUTypes;
  100.         getLane().addSensor(this); // Implements OTS-218
  101.     }

  102.     /**
  103.      * Create a sensor on a lane at a position on that lane at specified elevation and triggering an all GTU types.
  104.      * @param id String; the id of the sensor.
  105.      * @param lane Lane; the lane for which this is a sensor.
  106.      * @param longitudinalPosition Length; the position (between 0.0 and the length of the Lane) of the sensor on the design
  107.      *            line of the lane.
  108.      * @param positionType RelativePosition.TYPE; the relative position type (e.g., FRONT, BACK) of the vehicle that triggers
  109.      *            the sensor.
  110.      * @param simulator OTSDEVSSimulatorInterface; the simulator (needed to generate the animation).
  111.      * @param geometry OTSLine3D; the geometry of the object, which provides its location and bounds as well
  112.      * @param elevation Length; elevation of the sensor
  113.      * @throws NetworkException when the position on the lane is out of bounds
  114.      */
  115.     public AbstractSensor(final String id, final Lane lane, final Length longitudinalPosition,
  116.             final RelativePosition.TYPE positionType, final OTSDEVSSimulatorInterface simulator, final OTSLine3D geometry,
  117.             final Length elevation) throws NetworkException
  118.     {
  119.         this(id, lane, longitudinalPosition, positionType, simulator, geometry, elevation, GTUTYPE_SET_ALL);
  120.     }

  121.     /**
  122.      * Create a sensor on a lane at a position on that lane at specified elevation and triggering an all GTU types.
  123.      * @param id String; the id of the sensor.
  124.      * @param lane Lane; the lane for which this is a sensor.
  125.      * @param longitudinalPosition Length; the position (between 0.0 and the length of the Lane) of the sensor on the design
  126.      *            line of the lane.
  127.      * @param positionType RelativePosition.TYPE; the relative position type (e.g., FRONT, BACK) of the vehicle that triggers
  128.      *            the sensor.
  129.      * @param simulator OTSDEVSSimulatorInterface; the simulator (needed to generate the animation).
  130.      * @param geometry OTSLine3D; the geometry of the object, which provides its location and bounds as well
  131.      * @throws NetworkException when the position on the lane is out of bounds
  132.      */
  133.     public AbstractSensor(final String id, final Lane lane, final Length longitudinalPosition,
  134.             final RelativePosition.TYPE positionType, final OTSDEVSSimulatorInterface simulator, final OTSLine3D geometry)
  135.             throws NetworkException
  136.     {
  137.         this(id, lane, longitudinalPosition, positionType, simulator, geometry, GTUTYPE_SET_ALL);
  138.     }

  139.     /**
  140.      * @param id String; the id of the sensor.
  141.      * @param lane Lane; the lane for which this is a sensor.
  142.      * @param longitudinalPosition Length; the position (between 0.0 and the length of the Lane) of the sensor on the design
  143.      *            line of the lane.
  144.      * @param positionType RelativePosition.TYPE; the relative position type (e.g., FRONT, BACK) of the vehicle that triggers
  145.      *            the sensor.
  146.      * @param simulator OTSDEVSSimulatorInterface; the simulator (needed to generate the animation).
  147.      * @throws NetworkException when the position on the lane is out of bounds
  148.      */
  149.     public AbstractSensor(final String id, final Lane lane, final Length longitudinalPosition,
  150.             final RelativePosition.TYPE positionType, final OTSDEVSSimulatorInterface simulator) throws NetworkException
  151.     {
  152.         this(id, lane, longitudinalPosition, positionType, simulator, makeGeometry(lane, longitudinalPosition));
  153.     }

  154.     /**
  155.      * Make a geometry perpendicular to the center line of the lane with a length of 90% of the width of the lane.
  156.      * @param lane the lane for which to make a perpendicular geometry
  157.      * @param longitudinalPosition the position on the lane
  158.      * @return an OTSLine3D that describes the line
  159.      * @throws NetworkException in case the sensor point on the center line of the lane cannot be found
  160.      */
  161.     private static OTSLine3D makeGeometry(final Lane lane, final Length longitudinalPosition) throws NetworkException
  162.     {
  163.         try
  164.         {
  165.             double w45 = lane.getWidth(longitudinalPosition).si * 0.45;
  166.             DirectedPoint c = lane.getCenterLine().getLocation(longitudinalPosition);
  167.             double a = c.getRotZ();
  168.             OTSPoint3D p1 = new OTSPoint3D(c.x + w45 * Math.cos(a + Math.PI / 2), c.y - w45 * Math.sin(a + Math.PI / 2), c.z);
  169.             OTSPoint3D p2 = new OTSPoint3D(c.x - w45 * Math.cos(a + Math.PI / 2), c.y + w45 * Math.sin(a + Math.PI / 2), c.z);
  170.             return new OTSLine3D(p1, p2);
  171.         }
  172.         catch (OTSGeometryException exception)
  173.         {
  174.             throw new NetworkException(exception);
  175.         }
  176.     }

  177.     /** {@inheritDoc} */
  178.     @Override
  179.     public final void trigger(final LaneBasedGTU gtu)
  180.     {
  181.         fireTimedEvent(SingleSensor.SENSOR_TRIGGER_EVENT, new Object[] { getId(), this, gtu, this.positionType }, getSimulator()
  182.                 .getSimulatorTime());
  183.         triggerResponse(gtu);
  184.     }

  185.     /**
  186.      * Implementation of the response to a trigger of this sensor by a GTU.
  187.      * @param gtu LaneBasedGTU; the lane based GTU that triggered this sensor.
  188.      */
  189.     protected abstract void triggerResponse(final LaneBasedGTU gtu);

  190.     /** {@inheritDoc} */
  191.     @Override
  192.     public final RelativePosition.TYPE getPositionType()
  193.     {
  194.         return this.positionType;
  195.     }

  196.     /** {@inheritDoc} */
  197.     @Override
  198.     public final OTSDEVSSimulatorInterface getSimulator()
  199.     {
  200.         return this.simulator;
  201.     }

  202.     /** {@inheritDoc} */
  203.     @Override
  204.     public final ImmutableSet<GTUType> getTriggeringGTUTypes()
  205.     {
  206.         return this.triggeringGTUTypes;
  207.     }

  208.     /** {@inheritDoc} */
  209.     @SuppressWarnings("checkstyle:designforextension")
  210.     @Override
  211.     public int hashCode()
  212.     {
  213.         final int prime = 31;
  214.         int result = 1;
  215.         result = prime * result + ((getLane() == null) ? 0 : getLane().hashCode());
  216.         long temp;
  217.         temp = Double.doubleToLongBits(getLongitudinalPosition().si);
  218.         result = prime * result + (int) (temp ^ (temp >>> 32));
  219.         result = prime * result + ((this.positionType == null) ? 0 : this.positionType.hashCode());
  220.         return result;
  221.     }

  222.     /** {@inheritDoc} */
  223.     @SuppressWarnings({ "checkstyle:needbraces", "checkstyle:designforextension" })
  224.     @Override
  225.     public boolean equals(final Object obj)
  226.     {
  227.         if (this == obj)
  228.             return true;
  229.         if (obj == null)
  230.             return false;
  231.         if (getClass() != obj.getClass())
  232.             return false;
  233.         AbstractSensor other = (AbstractSensor) obj;
  234.         if (this.getLane() == null)
  235.         {
  236.             if (other.getLane() != null)
  237.                 return false;
  238.         }
  239.         else if (!this.getLane().equals(other.getLane()))
  240.             return false;
  241.         if (Double.doubleToLongBits(this.getLongitudinalPosition().si) != Double.doubleToLongBits(other
  242.                 .getLongitudinalPosition().si))
  243.             return false;
  244.         if (this.positionType == null)
  245.         {
  246.             if (other.positionType != null)
  247.                 return false;
  248.         }
  249.         else if (!this.positionType.equals(other.positionType))
  250.             return false;
  251.         return true;
  252.     }

  253.     /** {@inheritDoc} */
  254.     @SuppressWarnings("checkstyle:designforextension")
  255.     @Override
  256.     public int compareTo(final SingleSensor o)
  257.     {
  258.         if (this.getLane() != o.getLane())
  259.         {
  260.             return this.getLane().hashCode() < o.getLane().hashCode() ? -1 : 1;
  261.         }
  262.         if (this.getLongitudinalPosition().si != o.getLongitudinalPosition().si)
  263.         {
  264.             return this.getLongitudinalPosition().si < o.getLongitudinalPosition().si ? -1 : 1;
  265.         }
  266.         if (!this.positionType.equals(o.getPositionType()))
  267.         {
  268.             return this.positionType.hashCode() < o.getPositionType().hashCode() ? -1 : 1;
  269.         }
  270.         if (!this.equals(o))
  271.         {
  272.             return this.hashCode() < o.hashCode() ? -1 : 1;
  273.         }
  274.         return 0;
  275.     }

  276.     /** {@inheritDoc} */
  277.     @Override
  278.     public abstract AbstractSensor clone(CrossSectionElement newCSE, OTSSimulatorInterface newSimulator, boolean animation)
  279.             throws NetworkException;

  280. }