I am attempting to test some discrete time functions against their continuous counterparts and I am surprised by how inaccurate the discrete versions are coming out.

I am modeling the displacement, velocity, and acceleration of an ideal string struck by a mass as per: https://www.dsprelated.com/freebooks/pasp/Ideal_String_Struck_Mass.html

This gives displacement as:

$y(t) = \frac{v*m}{2R}*(1-e^{\frac{-2Rt}{m}})$

Velocity as a function of time is:

$v(t) = v*e^{\frac{-2Rt}{m}}$

Acceleration can be derived from velocity:

$a(t) = \frac{-2Rve^{\frac{-2Rt}{m}}}{m}$

A discrete time formula for velocity using the displacement output from the first continuous function is:

$v(s) = sy(s)$

$v[n] = \frac{y[n] - y[n-1]}{T}$

A discrete formula for acceleration from displacement is:

$a(s) = s^{2}y(s)$

$a[n] = \frac{y[n-2] - 2y[n-1] + y[n]}{T^{2}}$

Mostly the discrete formulas seem to give normal output that matches the continuous equations. It seems close at the start and finish. However, at some points it's shocking how far off it is.

Here's some basic code to test this:

displacement_2 = displacement_1;
displacement_1 = displacement;
displacement = ((velocity * mass)/ (2 * impedance)) * (1 - exp(-2 * impedance * timer / mass));

velocityContinuous = velocity * exp((-2 * impedance * timer) / mass);
velocityDiscrete = (displacement - displacement_1) / deltaTime;

accelContinuous =  (-2 * impedance * velocity * exp((-2 * impedance * timer) / mass)) / mass;
accelDiscrete = (displacement_2 - (2 * displacement_1) + displacement)/(deltaTime*deltaTime);

timer = timer + deltaTime;

deltaTime = 1/sampleRate;
velocity = 8.f;
impedance = 0.5f;
mass = 0.004f;

At some points I'll get output like:

 velocityContinuous: 2.81216 velocityDiscrete: 3.47256
 velocityContinuous: 2.78302 velocityDiscrete: 3.45452

 accelContinuous: -840.176 accelDiscrete: -1089.63
 accelContinuous: -831.469 accelDiscrete: -1083.97

That's a pretty massive error. Is this normal? Or have I done something wrong? Sample rate is 96 kHz.

On another note, accelDiscrete puts out 0 first sample, then an insanely large number of the wrong sign second sample, then "correct" output after that. velocityDiscrete puts out 0 first sample then normal output. I assume this is because displacement_2 and displacement_1 are 0 at initialization and it can't calculate properly from them. Is there any typical fix for this type of behavior, particularly accelDiscrete which is putting out a crazy number on the second sample?

  • $\begingroup$ A general debugging technique is to halve your sampling time step (double the sample rate), and see if that reduces the error. Rinse and repeat as needed. $\endgroup$ – hotpaw2 Dec 23 '19 at 0:12
  • $\begingroup$ The sampling rate plays a great deal on the results. Particularly you need to remember that derivatives of a sampled signal are way more noisy than the original signal. $\endgroup$ – Moti Dec 23 '19 at 1:22
  • $\begingroup$ Yeah I think it's just a sample rate noise issue. I've been testing more equations and they come out roughly right but continuous is just more accurate. No biggie. $\endgroup$ – mike Dec 23 '19 at 2:56

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.