Link to home
Start Free TrialLog in
Avatar of xenium
xenium

asked on

Dampening formula for animated graph

Here's a fun little graph:

https://enex.net/topshef/dev/20200223/sds_graph.php?config_file=./data/working/NQJ.SDS.graph_config.live.txt

Nodes animate according to some physical attraction/repulsion rules, and a linear dampening on speed which is not strictly realistic and also results in a perpetual oscillation in some cases such as above.

Can anyone suggest a simple modification to the dampening that will remove this oscillation? Also why is the oscillation perpetual if there is dampening?

JS code is visible by viewing source.

Many thanks
Avatar of xenium
xenium

ASKER

The dampening is in graph.js:

node.velX = node.velX * 0.9;
node.velY = node.velY * 0.9;

I think a more complex function is needed to simulate friction.

I'll see if i can post an offline version. It may be just saving the page will work.
Avatar of xenium

ASKER

The dampening is applied to all nodes.

The js is nested with relative links from main.js, here is graph.js

https://enex.net/topshef/dev/20200223/asset/dist/graph.js
Avatar of xenium

ASKER

An observation: the oscillation only occurs after a certain animation speed:

Compare:
https://enex.net/topshef/dev/20200310/sds_graph.php?config_file=./data/working/4BS.SDS.graph_config.live.txt 
with a slower speed that does not oscillate:
https://enex.net/topshef/dev/20200310/sds_graph.php?speed=5&config_file=./data/working/4BS.SDS.graph_config.live.txt 

I haven't investigated yet, but wondering first if the issue is a trait of the coding, or of the model itself (can the 2 be different since all nodes are not updates simultaneously?)
Avatar of phoffric
Hi xenium,
I do not know JS, so only able to make a wild guess by looking at your above comment about
node.velX = node.velX * 0.9;

Open in new window

. I looked for other references in this js file for node.velX. Here is what I came up with:  

for (let node of this.nodes) {
                  
// linear dampening - stable only in some circumstances eg 3 pointed star
node.velX = node.velX * 0.9;
node.velY = node.velY * 0.9;
                  
// force bias accelerations - NB implicit unit size time step !!!
const timestep = 1.0;
const vx =   Math.cos(node.force_bias.angle) * node.force_bias.length * timestep;
const vy = - Math.sin(node.force_bias.angle) * node.force_bias.length * timestep; //NB origin of SVG coordinates and direction of Y axis

node.velX += vx;
node.velY += vy;

Since I don't know how to debug JS, I can only take a wild guess that the vx, when added to the node.velX may possibly neutralize the dampening effect. The highlighter cos function looks like an oscilatory forcing function. In that case, since 0.9 is close to 1.0, the dampening effect is likely being overwhelmed by the forcing function that keeps the nodes oscillating. But, are the other parameters that make up vx the same for all nodes? If so, I am surprised, because most of the nodes stabilize.

If you were to write the equations down with all the parameters associated with each node that go into these equations, in plain math, I might come up with a better explanation.

I saw your interesting note about "with a slower speed that does not oscillate". All I can say, is that timesteps and sinusoids play a close relationship to each other. Think about old western movie wagon wheels rolling backwards. This is a strobing effect. Here is a video of an airplane propeller that you can see spinning very slowly.
https://en.wikipedia.org/wiki/Wagon-wheel_effect

It is possible by changing the timestep to make the wagon wheel or the propeller appear stationary.
Avatar of xenium

ASKER

hi phoffric,

Thanks for your input.

I think the "force bias accelerations" is a generic "gravity" feature and I think it's a red-herring here. The oscillation issue occurred even before this feature was put in.

Good suggestion to write down the formulae in maths. I will see if I can do that sometime, along with the algorithm as a sequence.

Your last point about strobing is interesting, though I'm not sure I see the parallel exactly. What is clear is that there are at least 2 sources of inaccuracy in implementing the "model" with code:

1. the code uses a discrete timestep, whereas reality is continuous
2. the code cycles through nodes updating each in sequence, whereas in reality they all update simultaneously

I suspect that consciously addressing these 2 points in the coding might be the key.

Thanks again

PS sorry for the slow reply. This issue isn't on a critical path of my project so isn't getting priority attention, but I find it an interesting problem and I'm hoping to solve it in slow-time.

Avatar of xenium

ASKER

Perhaps if the deviation between the model and the simulation is greater than the dampening effect then the latter no longer has the intended effect. Maybe there's even a name for this.

If this is the case I'm guessing there must be standard studies and techniques on this.

I googled "thrashing" which lead to this, no idea if relevant just a hunch at present: https://en.wikipedia.org/wiki/Hysteresis 
Are you able to convert your js simulation program to C, C++, or MATLAB (or Python, which I had to use for a couple of months, so I might be able to help there)? My preference for this is MATLAB to be able to quickly show plots. (Python is also good, but I haven't done plots yet.)

I don't know what the forces are on each node. Are you able to create a tiny model and still get some unexpected oscillations?

Most of the nodes become apparently still or just some extremely low amplitude oscillations. From the observation it appears that there is a large forcing function applied to one of the nodes that causes it to oscillate. I don't know what is in the model (and especially the code) that creates the forcing functions.

The box - spring - wall review:
If you have a heavy box not moving (i.e., the rest point) on a flat frictionless surface, and pull the box to stretch the spring, and let go, then you know that the box will oscillate forever even in the absence of external forces other than the force of the spring.
If you add a little friction, then the oscillation will continue forever (i.e., underdamped) but the amplitude will decrease asymptotically to the box's rest point.
If you add a huge amount of friction so that it is very hard to move the box, and let go, the box may not even move if the spring force cannot overcome the static friction force (but this case is probably not in your model). If you give the box a nudge to break static friction, and if the spring force is slightly greater than the kinetic friction force, then the net force on the box is small, and the box will begin to slowly move to its rest place and not oscillate (overdamped).

Some of your nodes appear to be overdamped, and some one appears to be underdamped (or actually, as your question suggests - no damping) from observation. And when you change your animation rate, you get  respective rest points (very complicated in a multi-body model, but still, you are correct to believe that the nodes should come to a rest point).

This makes me believe that there is a coding bug in your program. I always try to use a debugger and break points to examine variables to solve my coding errors. But sometimes, I am forced to print out the variables' values that I think are causing a problem.

Maybe you can do this. Pick the worst node that is oscillating forever with no amplitude dampening. If it has a mass, print it out. I assume the mass is constant. Then for each incremental timestep of the animation, print out the node's position (x, y), its velocity vector (v_x, v_y), its acceleration (a_x, a_y); and all the force vectors (f1_x, f1_y; f2_x, f2_y, etc.) affecting that node, and the time (t_i, i for ith step). With this information, we should be able to compute offline whether our predicted position, velocity, and acceleration matches your printed results.

The results should fit nicely into an excel spreadsheet if you use a csv printout like this:
t_i,    x, y,    v_x, v_y,   a_x, a_y,    f1_x, f1_y,   f2_x, f2_y,     fxy_etc.
Avatar of xenium

ASKER

hi phoffic, thanks for your comment. Sorry I won't be able to go into that much detail just yet as a number of other priorities have come up. I do however think the clue is in the timestep, ie the fact that the bug only appears at faster speeds suggests it could be a rounding issue as mentioned above.

Let's let this one slow-cook for a while (weeks, months) and I'll repost if a solution emerges from the stew!

Thanks again
slow-cook is fine. No problem.
This question needs an answer!
Become an EE member today
7 DAY FREE TRIAL
Members can start a 7-Day Free trial then enjoy unlimited access to the platform.
View membership options
or
Learn why we charge membership fees
We get it - no one likes a content blocker. Take one extra minute and find out why we block content.