simulating biorhythms

Started by
9 comments, last by Crispy 20 years, 7 months ago
Maybe "biorhythms" isn''t the most suitable word for what I have in mind, but it''s not strictly a cardiogram either. What I''d like to simulate (based on the intensity of user input) is a kind of heartbeat monitor (expressed by a single line) that would have the following characteristics: when the system is idle, the line is a prefect sinusoid. As input is recorded, a generic variable (let''s call it the Biorhythm) increases, adding interference to the line. Sudden increases in Biorhythm should introduce unexpected jerks in the line. I''d like the line to maintain certain regularities, though, so using randomized change isn''t really an option (I tried it and the outcome was to erratic - no regularity whatsoever, just as expected). The results were occasionally pretty good when I interlaced two sinusoids with different frequencies - that, however, caused the sinusoid that was added to the first one oscillate along the first one (which is also pretty logical, but unwanted). I did quite a bit of experimenting and didn''t manage to work out a good formula that would 1) stay centered on a flat center line, 2) become systematically more and more erratic as user input increases, 3) would nicely recede to its normal form (a nice sinusoid) when linearly normalized (if there is no user input, the Biorhythm "recuperates" linearly). Think of it this way: Biorhythm = [0.1; 0.9], the larger it gets, the more turbulent the line is. Increase, based on user input, can be as slow as 0.0001 or as sudden as 0.3. I''ve spen hours trying to come up with something decent, but to no avail - if there''s anyone who could suggest something I''d really appreciate it. Cheers
"Literally, it means that Bob is everything you can think of, but not dead; i.e., Bob is a purple-spotted, yellow-striped bumblebee/dragon/pterodactyl hybrid with a voracious addiction to Twix candy bars, but not dead."- kSquared
Advertisement
The kind of jerk that you want is slightly unclear. Do you really want a heart-beat-like diagram?

If not, you might want to try to simulate a damped forced harmonic oscillator.

The basic equation is simply

F = -kx - fv + J

where x is the current position of the oscillator (i.e.: the current value of the heartbeat), k is a constant, f is another constant (for friction), v is the current speed of the oscillator (you''ll have to keep it internally, and apply the acceleration from the force F at each time step), and J is the driving force.

For constant k, f, and J, you''ll get a sinusoidal x (after an initial transition phase). You can then introduce random variations to all three constants to vary the behavior.

Cédric
Alright - I finally got to play around with that formula you gave and I must admit I don''t really see how it should work. No matter what I set the constants to and no matter how I change any of the variables, I can''t get anything but a straigh line out of it. I added a sin function to the formula and got my sinusoid, but didn''t get any irregularities.

I''ll link a picture this time - hopefully it gets it across a little better as to what I''m after (since I couldn''t find a good picture, I''ll post something that resembles it and describe it further below):



This is a simple cardiogram that shows the kinds of jerks I''m after when there''s a lot of user input. However, I don''t want these to occur based on heartbeat, but according to input intensity, more specifically when there''s a sudden surge in the Biorhythm variable. Moreover, I want the line to be messier and not subside to a straight line when input dies, but to a low frequency sinusoid.

Sorry I couldn''t get your formula working, Cédric - it''s probably due to my complete lack of knowledge as far as oscillators are involved...
"Literally, it means that Bob is everything you can think of, but not dead; i.e., Bob is a purple-spotted, yellow-striped bumblebee/dragon/pterodactyl hybrid with a voracious addiction to Twix candy bars, but not dead."- kSquared
you have to integrate the acceleration (you get it from the force given by Cédric) to get the velocity and integrate again to get the position of your oscillator

[edited by - bucheron on September 1, 2003 6:35:06 PM]
Ok, um... Sorry about that. If you haven''t played with this kind of formula, it''s entirely normal that you fail to do anything with them. I should have told you to ask for more details if you didn''t understand how it works. So let me correct this:

Ask for more details if you don''t understand how it works.

Now that this is behind us, onto the details. As bucheron said, you have to integrate numerically the acceleration to get the speed, and then integrate the speed to get the position (x). What we are doing is simulating a mass attached to a spring.

First, let dt be the time step between two successive updates of the formula. This should be relatively small. What you are going to plot, is x against t. We start t at 0, and at each time step, we increment t by dt, and update x according to the equations given.

Initial conditions: x = 0, v = 0. k, f and J are parameters (try different values for them, to play with the shape of the resulting curve. If they remain constant, you should get a nice sinusoid as a result.)

t = t + dtF = -kx - fv + Ja = F / m     (m is another parameter; you can set it to 1 for the purposes of this exercise, so that a = F)x = x + vt + at² / 2         (Update position)v = v + at                   (Update speed) 

Now, you have your first value to plot for the heartbeat, which is (t, x). Reapply these formulas again to t and x to get your second value, and so forth.

If the behavior doesn''t look sinusoidal with constant k, f, and J, your dt is probably too large.

That''s it for now. Once you get this working, we can play around with the results to achieve what you want.

Cédric
Thanks for the explanation! I''m getting a sinusoid now. However the amplitude increases linearly no matter how I adjust the parameters as t and a skyrocket pretty quickly. I have J, f and k (no pun intended hehe ) all set to something as small as 0.01 (I''m currently keeping them at the same value) so the line starts out as flat. How can I counteract this increase in amplitude or, more precisely, what am I doing wrong?

It''s probably best for me to confess that my mathematical abilities are relatively impaired - I can see what''s going on, but I don''t have the kind of mathematical "spark" to think and improvise my way out of a predicament so, yeah - I''m sorry if my questions seem naïve or stupid .

Non-related: purely out of interest - couldn''t this method be used to calculate faster sines? For instance, if t is known, it would be much faster to do the 6 multiplications, 2 divisions and 3 additions/subtractions as opposed to iterating through the Taylor series? Then again - I can''t even get this working so who am I to talk ...
"Literally, it means that Bob is everything you can think of, but not dead; i.e., Bob is a purple-spotted, yellow-striped bumblebee/dragon/pterodactyl hybrid with a voracious addiction to Twix candy bars, but not dead."- kSquared
quote:Original post by Crispy
Thanks for the explanation! I''m getting a sinusoid now.

Cool!
quote: However the amplitude increases linearly no matter how I adjust the parameters as t and a skyrocket pretty quickly.

t skyrockets??? Its only variation comes from t = t + dt, so it should increase linearly. t is the time.

As for the amplitude, I have just realized that I have made a mistake. A constant J should lead to a sinusoid that dies. To counteract that, you want to have J = Bsin(t/w) where w and B are constants too.

I have also made another mistake in the formulas (yay me!):
quote:x = x + vt + at² / 2
v = v + at

Replace all the "t" by "dt". This should fix your problem.

quote: I have J, f and k (no pun intended hehe ) all set to something as small as 0.01

The importance isn''t so much their value, but rather their relative importance. High f tends to bring the amplitude down. High k will try to maintain the current oscillation. High J (if it varies as described earlier) will try to increase the amplitude, until it reaches a peak.

quote:I''m sorry if my questions seem naïve or stupid .
Not at all. I only hope that the end result is what you want to achieve
quote:Non-related: purely out of interest - couldn''t this method be used to calculate faster sines? For instance, if t is known, it would be much faster to do the 6 multiplications, 2 divisions and 3 additions/subtractions as opposed to iterating through the Taylor series? Then again - I can''t even get this working so who am I to talk ...

Nice idea, but no. The precision required to have a good sin function would require very small dts. So there would be a lot of multiplications and additions involved, more than in the Taylor series.

However, for drawing a sine curve, this method might be faster, since each point of the sine curve is an increment over the previous one, whereas a method that uses a Taylor expansion at each point starts from scratch every time.

Cédric
>> t skyrockets??? Its only variation comes from t = t + dt, so it should increase linearly. t is the time.

sorry: "skyrocket" wasn''t really the most suitable word here. I do realise what the symbols mean, though - generally you won''t get to finish highschool if you don''t even know those .

Now back to the topic - it still gains in amplitude and by adding one constant after another this is getting way too confusing for me 8). I''ll post the code - perhaps there''s something I fail to notice - hopefully you''ll find the patience to skim through it (added the dots for readability reasons):

static float k = 0.01f;static float f = 0.0001f;static float J = 0.01f;.static float v = 0;static float x = 0;static float t = 0;.static float F;static float m = 0.1;static float a;.static float w = 2.0;static float B = 0.001;static float dt;.dt = FrameTime / 20.f;.t += dt;J = B * sin(t / w);F = -k * x - f * v + J;a = F / m;x += v * dt + (a * dt * dt) / 2.f;v += a * dt;.Use(x);


Off-topic again: regarding the calcualtion of sinus using the previous formula (before you posted the modifications in your previous post) - is the increase in amplitude linear or does it have some characteristics? Namely, in my mind, if the change in amplitude can be compensated for with one or two multiplications (if the increase is linear), then, knowing that for a normal sine dt, J, f and k are constant, why can''t it be approximated to the following base formula?

x = vt + a(t2) / 2

By calculating t linearly (through what relation, I don''t know) and matching a from an approximated look-up table, wouldn''t it be possible to calculate mysin(X) where t = F(X)? Of course, I have no idea what to do with v . Sorry for rambling - I occasionally get carried away with things I know little or nothing about

"Literally, it means that Bob is everything you can think of, but not dead; i.e., Bob is a purple-spotted, yellow-striped bumblebee/dragon/pterodactyl hybrid with a voracious addiction to Twix candy bars, but not dead."- kSquared
quote:Original post by Crispy
Now back to the topic - it still gains in amplitude and by adding one constant after another this is getting way too confusing for me 8).

Your code looks right. It''s normal that it gains some aplitude, but it should get stable at some point, after many iterations.

Try w = sqrt(k/m)
quote:Off-topic again: regarding the calcualtion of sinus using the previous formula (before you posted the modifications in your previous post) - is the increase in amplitude linear or does it have some characteristics?

Before I made the modifications, there shouldn''t have been an increase. But it was overkill. All you need for a sinus is
F = -kx
But you have to give x a non-zero initial value.
quote:Namely, in my mind, if the change in amplitude can be compensated for with one or two multiplications (if the increase is linear), then, knowing that for a normal sine dt, J, f and k are constant, why can''t it be approximated to the following base formula?

Um, yeah, well, you can''t do that. This is an iterative method. You can''t know the ith step without having calculated the (i-1)th step. v, a, and x are the core of the iteration, so you can''t just forget about them.

The F = -kx part reminds me: you could start with just that, and see if it works. Then, add friction (-fv). And then, try adding a force.

It''s a nice exercise for you to do, to get an idea of how harmonic motion works. Without friction and force, what you have is a friction-less spring.

Cédric
Right - I''ve tried a million variations now with the variables, iterated it a lot, scaled it down > 1 million times and it still increases until it crashes (as it eventually goes out of bounds)...
"Literally, it means that Bob is everything you can think of, but not dead; i.e., Bob is a purple-spotted, yellow-striped bumblebee/dragon/pterodactyl hybrid with a voracious addiction to Twix candy bars, but not dead."- kSquared

This topic is closed to new replies.

Advertisement