View Javadoc
1   package org.opentrafficsim.road.gtu.lane.perception.categories;
2   
3   import org.djunits.value.vdouble.scalar.Duration;
4   import org.djunits.value.vdouble.scalar.Time;
5   import org.opentrafficsim.core.dsol.OTSSimulatorInterface;
6   
7   import nl.tudelft.simulation.jstats.distributions.DistNormal;
8   import nl.tudelft.simulation.jstats.streams.StreamInterface;
9   
10  /**
11   * A numerical update scheme that represents a Wiener process if {@code dt << tau}. A Wiener process is a process that results
12   * in random values that follow a Normal distribution with parameters mu and sigma. However, there is a time progression with
13   * correlation {@code tau}, such that the process has a tendency to stay close to the previous value. The correlation time
14   * {@code tau} is a measure for this tendency. Given sufficient time (and {@code dt << tau}) the overall probability remains
15   * equal to the Normal distribution.
16   * <p>
17   * The Wiener process is typically used for measurement or perception errors in cases where the error of two consecutive time
18   * steps is unlikely to deviate much.
19   * <p>
20   * Treiber, M., A. Kesting, D. Helbing (2006) "Delays, Inaccuracies and Anticipation in Microscopic Traffic Models", Physica A –
21   * Statistical Mechanics and its Applications, Vol. 360, Issue 1, pp. 71-88.
22   * <p>
23   * Copyright (c) 2013-2019 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/node/13">OpenTrafficSim License</a>.
25   * <p>
26   * @version $Revision$, $LastChangedDate$, by $Author$, initial version 18 okt. 2018 <br>
27   * @author <a href="http://www.tbm.tudelft.nl/averbraeck">Alexander Verbraeck</a>
28   * @author <a href="http://www.tudelft.nl/pknoppers">Peter Knoppers</a>
29   * @author <a href="http://www.transport.citg.tudelft.nl">Wouter Schakel</a>
30   */
31  public class WienerProcess extends DistNormal
32  {
33  
34      /** */
35      private static final long serialVersionUID = 20181018L;
36  
37      /** Simulator. */
38      private final OTSSimulatorInterface simulator;
39  
40      /** Mean. */
41      private final double muW;
42  
43      /** Standard deviation. */
44      private final double sigmaW;
45  
46      /** Correlation time. */
47      private final Duration tau;
48  
49      /** Value of the standard Wiener process (mu = 0, sigma = 1). */
50      private Double value;
51  
52      /** Time the value was determined. */
53      private Time prevTime;
54  
55      /**
56       * @param stream StreamInterface; random number stream
57       * @param mu double; mean
58       * @param sigma double; standard deviation
59       * @param tau Duration; correlation time
60       * @param simulator OTSSimulatorInterface; simulator
61       */
62      public WienerProcess(final StreamInterface stream, final double mu, final double sigma, final Duration tau,
63              final OTSSimulatorInterface simulator)
64      {
65          super(stream);
66          this.muW = mu;
67          this.sigmaW = sigma;
68          this.tau = tau;
69          this.simulator = simulator;
70      }
71  
72      /** {@inheritDoc} */
73      @Override
74      public double draw()
75      {
76          if (this.value == null)
77          {
78              this.value = super.draw();
79              this.prevTime = this.simulator.getSimulatorTime();
80          }
81          else if (this.simulator.getSimulatorTime().gt(this.prevTime))
82          {
83              // calculate next value
84              Time now = this.simulator.getSimulatorTime();
85              double dt = now.si - this.prevTime.si;
86              if (dt <= this.tau.si)
87              {
88                  this.value = Math.exp(-dt / this.tau.si) * this.value + Math.sqrt((2 * dt) / this.tau.si) * super.draw();
89              }
90              else
91              {
92                  // too long ago, exp may result in extreme values, draw new independent value
93                  this.value = super.draw();
94              }
95              this.prevTime = now;
96          }
97          return this.muW + this.value * this.sigmaW;
98      }
99  
100 }