NSV, Euler Integration Confusion - math

I'm trying to get my head around these integration methods and I'm thouroughly confused.
Here is the code:
public void update_euler(float timeDelta){
vPos.y += vVelocity.y * timeDelta;
vVelocity.y += gravity.y * timeDelta;
}
public void update_nsv(float timeDelta){
vVelocity.y += gravity.y*timeDelta;
vPos.y += vVelocity.y * timeDelta;
}
public void onDrawFrame(GL10 gl) {
currentTime = System.currentTimeMillis();
float timeDelta = currentTime - startTime;
startTime = currentTime;
timeDelta *= 1.0f/1000;;
// update_RK4(timeDelta);
// update_nsv(timeDelta);
// update_euler(timeDelta);
// update_velocity_verlet(timeDelta);
}
Firstly, I just want to make sure I've got these right.
I am simulating a perfectly elastic ball bouncing, so on the bounce I just reverse the velocity.
The Euler method, the ball bounces higher on each bounce. Is this due to an error in my code or is this due to the innacuracy of the method. I've read that with the Euler integration you lose energy over time. Well I'm gaining it and I don't know why.
The nsv method: I don't quite understand how this is different to the Eular method, but in any case the ball bounces lower on each bounce. It is losing energy which I've read isnt meant to happen with the nsv method. Why am I losing energy?
(The velocity verlet and RK4 methods are working as I'd expect them to).
I get the impression I'm lacking a fundamental bit of information on this subject, but I don't know what.
I do realise my timestep is lacking, and updating it to run the physics using a static timestep would stop me losing/gaining energy, but I am trying to understand what is going on.
Any help would be appreciated.

To add another option to #Beta's answer, if you average the two methods, your error should disappear (except for issues around handling the actual bounce).
public void update_avg(float timeDelta){
vVelocity.y += gravity.y*timeDelta/2;
vPos.y += vVelocity.y * timeDelta;
vVelocity.y += gravity.y*timeDelta/2;
}
What I'm doing here is updating the velocity to the average velocity over the interval, then updating the position based on that velocity, then updating the velocity to the velocity at the end of the interval.
If you have a more complicated scenario that you want to model, consider using the Runge-Kutta Method to solve differential equations of the form y' = f(x, y). (Note that here y can be a set of different variables. So in your case you'd have d(position, velocity)/dt = (velocity, -gravity). And the code I gave you works out to be the same as the second-order version of that method.

In real life, the ball moves upward and decelerates, reaches the apex (apogee) where its velocity is zero for a split-second, then moves downward and accelerates. Over any time interval it is exchanging kinetic energy (being fast) with potential energy (being high).
In the Euler method, it moves with constant velocity for the duration of the interval, then at the end of the interval it suddenly changes its velocity. So on the upward journey it goes up at high speed, then slows down, having gained more altitude than it should have. On the downward leg it creeps down slowly, losing little altitude, then speeds up.
In the nsv method, the opposite happens: on the way up it loses speed "too soon" and doesn't get very high, on the way down it hurries and reaches the ground without building up much speed.
The two methods are the same in the limit as timeDelta goes to zero. (If that statement made no sense, don't sweat it, it's just calculus.) If you make timeDelta small, the effect should fade. Or you could use energy as your primary variable, not {position, velocity}, but the math would be a little more complicated.

The integration introduces artificial damping into the system. I believe you can determine ho much by doing a Fourier analysis on the integration scheme, but I'd have to refresh my memory on the details.

Related

Trying to understand how a series of arrays is being mapped in an AVR routine

I'm trying to port an Arduino AVR routine either to ESP32/8266 or a Python script and would appreciate understanding how to crack the operation of this program. I'm self-teaching and am only looking to get something that works - pretty isn't required. This is a hobby and I am the only audience. The basic operations are understood (99% certain ;)) - there are 4 arrays total: Equilarg and Nodefactor contain 10 rows of 37 values; startSecs contains the epochtime values for the start of each year (2022-2032); and speed contains 37 values.
I believe each row of the Equilarg and Nodefactor arrays corresponds to the year, but I can't work out how the the specific element is pulled from each of the 3, 37 element arrays.
Here is the operating code:
// currentTide calculation function, takes a DateTime object from real time clock.
float TideCalc::currentTide (DateTime now)
{
// Calculate difference between current year and starting year.
YearIndx = now.year() - startYear;
// Calculate hours since start of current year. Hours = seconds / 3600
currHours = (now.unixtime() - pgm_read_dword_near (&startSecs[YearIndx])) / float(3600);
// Shift currHours to Greenwich Mean Time
currHours = currHours + adjustGMT;
// **************Calculate current tide height**********
// initialize results variable, units of feet.
// (This is 3.35 if it matters to understanding how it works)
tideHeight = Datum;
for (int harms = 0; harms < 37; harms++)
{
// Step through each harmonic constituent, extract the relevant
// values of Nodefactor, Amplitude, Equilibrium argument, Kappa
// and Speed.
currNodefactor = pgm_read_float_near (&Nodefactor[YearIndx][harms]);
currAmp = pgm_read_float_near (&Amp[harms]);
currEquilarg = pgm_read_float_near (&Equilarg[YearIndx][harms]);
currKappa = pgm_read_float_near (&Kappa[harms]);
currSpeed = pgm_read_float_near (&Speed[harms]);
// Calculate each component of the overall tide equation
// The currHours value is assumed to be in hours from the start of
// the year, in the Greenwich Mean Time zone, not the local time zone.
tideHeight = tideHeight + currNodefactor * currAmp
* cos ((currSpeed * currHours + currEquilarg - currKappa) * DEG_TO_RAD);
}
//***************End of Tide Height calculation**********
// Output of tideCalc is the tide height, units of feet.
return tideHeight;
}
I've made several attempts to reverse engineer by running the code on an AVR board and trapping the input values and then work backwards but I'm just not seeing a basic part or two. In this instance knowing "kinda" what's going on falls too short.
pgm_read_float_near reads a float value from flash memory. It needs the address of the value. We give it the address of the indexed value when we use &Amp[harms] for example. Both Nodefactor and Equilarg are doubly indexed - by year and then by harmonic, while the other three are indexed by the harmonic alone.
It sounds like this is a Fourier series curve fit for the tide height. So they're summing up a series of cosine values, each with different amplitude, frequency, and phase.
As #Tom suggests, copy the code to a plain C file, make a little routine for a dummy pgm_read_float_near and see how it works on your PC. Many times I write and debug algorithms on a "big" computer, and later plop the code into the Arduino.
Have fun!

QT optimize program to execute calculations at particular time intervals (Signal & QTimer elapsed)

Hi I have a file with following format where am trying to calculate the position of aircraft from radar (approaching airport) every 10 msecs.
Position_X
Position_Y
Heading
Speed
t1
t2 w1
t3 w2
t4
Where w1, w2 = turn rate
in this case {t1, t2, t3, t4} = 200secs ~ 200000 msecs
and evaluating position after every 10 msecs
This is how am processing:
// defined in Plane.h
QElapsedTimer t;
QTimer timer;
// Plane.cpp
Plane::Plane : timer() {
QObject::connect(&timer, SIGNAL(timeout()), this, SLOT(computePosition()));
timer.start(10);
t.start();
}
void Plane::computePosition()
{
if (!t.hasExpired(t1)
{
//do
}
if (t.hasExpired(t2) || t.hasExpired(t3))
{
//do
}
if (t.hasExpired(t3) || t.hasExpired(t4))
{
// do
}
if (t.hasExpired(t5))
{
// do
}
if(t.hasExpired(t5 + 100))
timer.stop();
qDebug() << QDateTime::currentMSecsSinceEpoch()<< t.elapsed()
<< Position_X << Position_Y;
}
am not able to match system time with elapsed time or condition time. timer interval rate is 10 ms but in debug I see it varies from 15-40 secs. And also the approach time is 200 ms but with using elapsed timer to evaluate position pushes the plane matrix way out of the airport.
How do I make sure my program is running at time intervals t1, t2, t3, t4 & t5 and position is evaluated correctly.
Appreciate any ideas or help. Thanks!
Calculation of positions is not a problem.I want to do the calculations at time t1..t5 in conjugation with QTimer (interval is 10 ms).
First of all, you don't need to use timers to do calculations: you can precalculate everything in advance, the calculations use a time variable that doesn't need to be coupled to any timer. It's just a variable you increment as you execute steps of a numerical integration. You have to tell us why you think that the program has to run at some intervals - because thus far it's simply false. It's hardly even a Qt problem, it's plain old numerical methods. The calculations are simple; for every time step:
Start at t=0.
Update heading according to current turn rate.
Convert radial speed to cartesian speed.
Integrate speed into position.
Select next turn rate if current t is past given t_i.
Increment t by 10ms.
Repeat from #2 unless current time t is past end time.
That's it. You're free to choose whatever integration rule you want. t is just a variable. It doesn’t have anything to do with passage of time on the computer that computes the results.
The rest depends on what is the meaning of the times t1-t4, and what are the outputs you're looking for - whether you want time time history from starting position until some time t4+0.1s, or just 4 outputs - one for each time t1-t4, etc.
QTimer most likely won't be able to maintain strict 10 ms ticks. QElapsedTimer can be more accurate, but it's meant more to measure performance of functions, methods, etc.
If you want to simulate an interval of X ms, just set up the QTimer to fire at a particular interval. Then, you can maintain a counter that increments each time the timeout signal is emitted. From there, you can calculate your "simulated time", which would be T = X * count. There's no need for a QElapsedTimer at all.
QTimer isn't "hard real-time". If you absolutely must have hard real-time, you'll have to look elsewhere.

Simulated Gravity: Slow down on ground approach

I'm looking for some math, nothing language dependant.
"Standard" gravity for an object in a game would go something like this:
if player.y > ground.y {
player.velocity.y = player.velocity.y - gravity
}
In the little simulation I'm implementing I would actually like the gravity to weaken, and the velocity to slow, as the player approaches the ground.
IE: When the object is 100m above ground it should fall faster than when it's 1m above ground. It should land like a feather in a way.
I imagine the gravity needs to be some kind of function of the distance between the object and the ground.
I've been searching around Google but as I've not done math in a while and I don't know the name of what I'm looking for, I've not had much luck.
(Note: I considered posting on the SE: Game Dev but as it's more about math/programming than game design itself I though it would be more appropriate here)
You're correct in your assumption that gravity needs to be a function. The following snippet (source: http://gafferongames.com/game-physics/integration-basics/) applies more gravity for higher values of x, where State is a struct for position and velocity in a single dimension.
float acceleration( const State &state )
{
const float k = 10;
const float b = 1;
return -k * state.x - b*state.v;
}
You want the reverse of this, which you can achieve by changing the value of b based on distance to the ground, or applying negative acceleration after some threshold.

Using an epsilon value to determine if a ball in a game is not moving?

I have balls bouncing around and each time they collide their speed vector is reduced by the Coefficient of Restitution.
Right now my balls CoR for my balls is .80 . So after many bounces my balls have "stopped" rolling because their speed has becoming some ridiculously small number.
In what stage is it appropriate to check if a speed value is small enough to simply call it zero (so I don't have the crazy jittering of the balls reacting to their micro-velocities). I've read on some forums before that people will sometimes use an epsilon constant, some small number and check against that.
Should I define an epsilon constant and do something like:
if Math.abs(velocity.x) < epsilon then velocity.x = 0
Each time I update the balls velocity and position? Is this what is generally done? Would it be reasonable to place that in my Vector classes setters for x and y? Or should I do it outside of my vector class when I'm calculating the velocities.
Also, what would be a reasonable epsilon value if I was using floats for my speed vector?
A reasonable value for epsilon is going to depend on the constraints of your system. If you are representing the ball graphically, then your epsilon might correspond to, say, a velocity of .1 pixels a second (ensuring that your notion of stopping matches the user's experience of the screen objects stopping). If you're doing a physics simulation, you'll want to tune it to the accuracy to which you're trying to measure your system.
As for how often you check - that depends as well. If you're simulating something in real time, the extra check might be costly, and you'll want to check every 10 updates or once per second or something. Or performance might not be an issue, and you can check with every update.
Instead of an epsilon for an IsStillMoving function, maybe you could use an UpdatePosition function, scheduled on an object-by-object basis based on its velocity.
I'd do something like this (in my own make-it-up-as-you-go pseudocode):
void UpdatePosition(Ball b) {
TimeStamp now = Clock.GetTime();
float secondsSinceLastUpdate = now.TimeSince(b.LastUpdate).InSeconds;
Point3D oldPosition = b.Position;
Point3D newPosition = CalculatePosition(b.Position, b.Velocity, interval);
b.MoveTo(newPosition);
float epsilonOfAccuracy = 0.5; // Accurate to one half-pixel
float pixelDistance = Camera.PixelDistance(oldPosition, newPosition);
float fps = System.CurrentFramesPerSecond;
float secondsToMoveOnePixel = (pixelDistance * secondsSinceLastUpdate) / fps;
float nextUpdateInterval = secondsToMoveOnePixel / epsilonOfAccuracy;
b.SetNextUpdateAt(now + nextUpdateInterval);
}
Balls moving very quickly would get updated on every frame. Balls moving more slowly might update every five or ten frames. And balls that have stopped (or nearly stopped) would update only very very rarely.
IMO your epsilon approach is fine. I would just experiment to see what looks or feels natural to the animation in the game.
Epsilon by nature is the smallest possible increment. Unfortunately, computers have different "minimal" increments of their own depending on the floating point representation. I would be very careful (and might even go higher than what I would calculate just for safety) playing around with that, especially if I want a code to be portable.
You may want to write a function that figures out the minimal increment on your floats rather than use a magic value.

Simple physics-based movement

I'm working on a 2D game where I'm trying to accelerate an object to a top speed using some basic physics code.
Here's the pseudocode for it:
const float acceleration = 0.02f;
const float friction = 0.8f; // value is always 0.0..1.0
float velocity = 0;
float position = 0;
move()
{
velocity += acceleration;
velocity *= friction;
position += velocity;
}
This is a very simplified approach that doesn't rely on mass or actual friction (the in-code friction is just a generic force acting against movement). It works well as the "velocity *= friction;" part keeps the velocity from going past a certain point. However, it's this top speed and its relationship to the acceleration and friction where I'm a bit lost.
What I'd like to do is set a top speed, and the amount of time it takes to reach it, then use them to derive the acceleration and friction values.
i.e.,
const float max_velocity = 2.0;
const int ticks; = 120; // If my game runs at 60 FPS, I'd like a
// moving object to reach max_velocity in
// exactly 2 seconds.
const float acceleration = ?
const float friction = ?
I found this question very interesting since I had recently done some work on modeling projectile motion with drag.
Point 1: You are essentially updating the position and velocity using an explicit/forward Euler iteration where each new value for the states should be a function of the old values. In such a case, you should be updating the position first, then updating the velocity.
Point 2: There are more realistic physics models for the effect of drag friction. One model (suggested by Adam Liss) involves a drag force that is proportional to the velocity (known as Stokes' drag, which generally applies to low velocity situations). The one I previously suggested involves a drag force that is proportional to the square of the velocity (known as quadratic drag, which generally applies to high velocity situations). I'll address each one with regard to how you would deduce formulas for the maximum velocity and the time required to effectively reach the maximum velocity. I'll forego the complete derivations since they are rather involved.
Stokes' drag:
The equation for updating the velocity would be:
velocity += acceleration - friction*velocity
which represents the following differential equation:
dv/dt = a - f*v
Using the first entry in this integral table, we can find the solution (assuming v = 0 at t = 0):
v = (a/f) - (a/f)*exp(-f*t)
The maximum (i.e. terminal) velocity occurs when t >> 0, so that the second term in the equation is very close to zero and:
v_max = a/f
Regarding the time needed to reach the maximum velocity, note that the equation never truly reaches it, but instead asymptotes towards it. However, when the argument of the exponential equals -5, the velocity is around 98% of the maximum velocity, probably close enough to consider it equal. You can then approximate the time to maximum velocity as:
t_max = 5/f
You can then use these two equations to solve for f and a given a desired vmax and tmax.
Quadratic drag:
The equation for updating the velocity would be:
velocity += acceleration - friction*velocity*velocity
which represents the following differential equation:
dv/dt = a - f*v^2
Using the first entry in this integral table, we can find the solution (assuming v = 0 at t = 0):
v = sqrt(a/f)*(exp(2*sqrt(a*f)*t) - 1)/(exp(2*sqrt(a*f)*t) + 1)
The maximum (i.e. terminal) velocity occurs when t >> 0, so that the exponential terms are much greater than 1 and the equation approaches:
v_max = sqrt(a/f)
Regarding the time needed to reach the maximum velocity, note that the equation never truly reaches it, but instead asymptotes towards it. However, when the argument of the exponential equals 5, the velocity is around 99% of the maximum velocity, probably close enough to consider it equal. You can then approximate the time to maximum velocity as:
t_max = 2.5/sqrt(a*f)
which is also equivalent to:
t_max = 2.5/(f*v_max)
For a desired vmax and tmax, the second equation for tmax will tell you what f should be, and then you can plug that in to the equation for vmax to get the value for a.
This seems like a bit of overkill, but these are actually some of the simplest ways to model drag! Anyone who really wants to see the integration steps can shoot me an email and I'll send them to you. They are a bit too involved to type here.
Another Point: I didn't immediately realize this, but the updating of the velocity is not necessary anymore if you instead use the formulas I derived for v(t). If you are simply modeling acceleration from rest, and you are keeping track of the time since the acceleration began, the code would look something like:
position += velocity_function(timeSinceStart)
where "velocity_function" is one of the two formulas for v(t) and you would no longer need a velocity variable. In general, there is a trade-off here: calculating v(t) may be more computationally expensive than simply updating velocity with an iterative scheme (due to the exponential terms), but it is guaranteed to remain stable and bounded. Under certain conditions (like trying to get a very short tmax), the iteration can become unstable and blow-up, a common problem with the forward Euler method. However, maintaining limits on the variables (like 0 < f < 1), should prevent these instabilities.
In addition, if you're feeling somewhat masochistic, you may be able to integrate the formula for v(t) to get a closed form solution for p(t), thus foregoing the need for a Newton iteration altogether. I'll leave this for others to attempt. =)
Warning: Partial Solution
If we follow the physics as stated, there is no maximum velocity. From a purely physical viewpoint, you've fixed the acceleration at a constant value, which means the velocity is always increasing.
As an alternative, consider the two forces acting on your object:
The constant external force, F, that tends to accelerate it, and
The force of drag, d, which is proportional to the velocity and tends to slow it down.
So the velocity at iteration n becomes: vn = v0 + n F - dvn-1
You've asked to choose the maximum velocity, vnmax, that occurs at iteration nmax.
Note that the problem is under-constrained; that is, F and d are related, so you can arbitrarily choose a value for one of them, then calculate the other.
Now that the ball's rolling, is anyone willing to pick up the math?
Warning: it's ugly and involves power series!
Edit: Why doe the sequence n**F** in the first equation appear literally unless there's a space after the n?
velocity *= friction;
This doesn't prevent the velocity from going about a certain point...
Friction increases exponentially (don't quote me on that) as the velocity increases, and will be 0 at rest. Eventually, you will reach a point where friction = acceleration.
So you want something like this:
velocity += (acceleration - friction);
position += velocity;
friction = a*exp(b*velocity);
Where you pick values for a and b. b will control how long it takes to reach top speed, and a will control how abruptly the friction increases. (Again, don't do your own research on this- I'm going from what I remember from grade 12 physics.)
This isn't answering your question, but one thing you shouldn't do in simulations like this is depend on a fixed frame rate. Calculate the time since the last update, and use the delta-T in your equations. Something like:
static double lastUpdate=0;
if (lastUpdate!=0) {
deltaT = time() - lastUpdate;
velocity += acceleration * deltaT;
position += velocity * deltaT;
}
lastUpdate = time();
It's also good to check if you lose focus and stop updating, and when you gain focus set lastUpdate to 0. That way you don't get a huge deltaT to process when you get back.
If you want to see what can be done with very simple physics models using very simple maths, take a look at some of the Scratch projects at http://scratch.mit.edu/ - you may get some useful ideas & you'll certainly have fun.
This is probably not what you are looking for but depending on what engine you are working on, it might be better to use a engine built by some one else, like farseer(for C#).
Note Codeplex is down for maintenance.

Resources