7

I am trying to add measurement noise to a simulation. This is possible to do in for example Simulink but seems to be more difficult in Modelica and SystemModeler.

Any ideas on how to do this?

Daniel Hedberg
  • 5,677
  • 4
  • 36
  • 61
sebnil
  • 113
  • 8

2 Answers2

8

You can add white noise in Wolfram SystemModeler via external C-code.

Modelica code (I've removed the diagram annotations from the code, so that it might be easier to read):

package WhiteNoise "Package for generating white noise"
  extends Modelica.Icons.Library;

  block NoiseNormal "Normally distributed random noise"
    parameter Real mean=0 "Mean value of random noise";
    parameter Real stdev=1 "Standard deviation of random noise";
    parameter Real tSample=0.01 "Noise sample time";
    Modelica.Blocks.Interfaces.RealOutput y;
  equation 
    when initial() then
      WhiteNoise.initRandomNormal();
    end when;
    when sample(0, tSample) then
      y=mean + stdev*WhiteNoise.RandomNormal(time);
    end when;
  end NoiseNormal;

  function initRandomNormal
    external "C" ext_initRandomNormal()   annotation(Include="#include \"ext_initRandNormal.c\"");
  end initRandomNormal;

  function RandomNormal
    output Real y;
    input Real u;
    external "C" y=ext_RandomNormal(u)   annotation(Include="#include \"ext_RandNormal.c\"");
  end RandomNormal;

end WhiteNoise;

External code:

ext_intRandNormal.c

#include <math.h>
#include <limits.h>

void ext_initRandomNormal()
{
    srand(time(NULL));
}

ext_RandNormal.c

#include <math.h>
#include <limits.h>
double ext_RandomNormal(double timein)

{
    unsigned int seed = 0;
    double v1, v2, r;

    timein /= 100;
    seed = (timein - floor(timein)) * UINT_MAX;

    do
    {
        v1 = 2 * ((double) rand()) /((double) RAND_MAX) - 1;
        v2 = 2 * ((double) rand()) /((double) RAND_MAX) - 1;
        r = v1 * v1 + v2 * v2;
    } while((r >= 1.0) || (r == 0.0));

    return v1 * sqrt( - 2.0 * log(r) / r );
}
jrhodin
  • 659
  • 5
  • 14
  • 2
    I would add an alternative `ext_initRandomNormaWithSeed` function to allow the user to pass a seed value in. This way, you can reproduce the noise signal. What is the point of the `seed` variable in `ext_RandomNormal`? Am I missing something? It seems to be computed but never used. – Michael Tiller Feb 19 '13 at 13:40
  • 4
    To be even more rigourous, you might wish to use an `ExternalObject` that preserves state. If you have to different `WhiteNoise` sources using the above code, they will "interact" with each other (one will affect the other). – Michael Tiller Feb 19 '13 at 13:43
3

An alternative is to use Modelica.Blocks.Noise to avoid writing external code yourself (added in Modelica Standard Library 3.2.2 released April 3, 2016; i.e. it would not have helped when the original question was asked).

One benefit of Modelica.Blocks.Noise is that the tricky questions with sampling, multiple seeds, etc are solved.

Hans Olsson
  • 11,123
  • 15
  • 38