Proper time compression/dilation in NewtonUpdate()

Report any bugs here and we'll post fixes

Moderators: Sascha Willems, Thomas

Proper time compression/dilation in NewtonUpdate()

Postby misho » Thu Oct 03, 2019 4:11 pm

Hi all,

My simulator server (MS FSX) has the ability of time compression/dilation, which user can select through UI. Basically, time compression/dilation allows simulation to run faster or slower than the normal time. This is very useful in spaceflight where there may be long periods of time where spacecraft is orbiting towards the next event without any need for spacecraft control (almost like an autopilot). I need to apply this setting to my spaceflight module, which uses Newton Game dynamics. The time compression settings available are:

timeCompression: 0.25, 0.5, 1, 2, 4, 8, 16, 32, 64, 128

I use these values to multiply them with timestep and pass it on into NewtonUpdate():

Code: Select all
NewtonUpdate(m_world, timestep*timeCompression)


However, I am not getting the consistent results: As I am testing this on a spacecraft that's orbiting around Earth, time dilation is working fine with values of 0.25 and 0.5. Time compression is working, however, when I pass values of 8 and larger, there are "hiccups" (random short pauses).

This USED to work with builds from about 2 years ago, where there was a define DG_MAX_TIMESTEP, which I remember I had to adjust to make all the values work properly. However, newer builds got rid of it and, looking at the code, I am unsure what the problem might be. Obviously, NewtonUpdate() has a problem dealing with larger time steps. I am using identical code to what is in

Code: Select all
void DemoEntityManager::UpdatePhysics(dFloat timestep)


of the sandboxDemo. I have to admit that I am not entirely sure how this code works (I think it limits running physics at MAX_PHYSICS_FPS, set at 60 fps) and there is perhaps a step I am missing that will make the time dilation/compression work properly.

So, is there anything I'm doing wrong with implementing this functionality? Does anyone know how to properly speed up or slow down time in Newton?

Thanks,
Misho
Last edited by misho on Fri Oct 04, 2019 1:37 pm, edited 1 time in total.
Misho Katulic
CTO, FSX SpacePort
TerraBuilder
www.terrabuilder.com
misho
 
Posts: 673
Joined: Tue May 04, 2010 10:13 am

Re: Proper time compression/dilation in NewtonUpdate()

Postby Sweenie » Fri Oct 04, 2019 1:47 am

Increasing the timestep size will never be a good idea. You will start to get missed collisions(tunneling) and other undesired effects, in other words you will loose precision.

Instead you should keep a fixed timestep at all times, for example 1/60 second and 1 or 2 substeps.
Then keep track of the time elapsed and when 1/60 of a second has elapsed, call Newton with that fixed timestep.
Now if you want the simulation to run twice as fast. Call NewtonUpdate when half of 1/60s has passed. You simply call NewtonUpdate twice in a period of 1/60 seconds.
Now this means as you increase the timescale Newton will be called more often and require more cpu.
So if you scale the time making Newton run 128 times within a period of 1/60 s will require ALOT of CPU-power. That is the downside, but on the other hand you will not loose precision and the simulation will behave exactly the same regardless.
Sweenie
 
Posts: 498
Joined: Mon Jan 24, 2005 7:59 am
Location: Sweden

Re: Proper time compression/dilation in NewtonUpdate()

Postby misho » Fri Oct 04, 2019 3:29 am

Sweenie wrote:Increasing the timestep size will never be a good idea. You will start to get missed collisions(tunneling) and other undesired effects, in other words you will loose precision.

Instead you should keep a fixed timestep at all times, for example 1/60 second and 1 or 2 substeps.
Then keep track of the time elapsed and when 1/60 of a second has elapsed, call Newton with that fixed timestep.


Thank you! So - referring to the sandboxDemo, I was mentioning that I wasn't sure what the code in

void DemoEntityManager::UpdatePhysics(dFloat timestep)

was doing but I was guessing it was firing NewtonUpdate() at 60 fps, as defined by MAX_PHYSICS_FPS, correct?

As for your suggestion - I tried it, basically running NewtonUpdate() in a loop:

Code: Select all
            for(int i = 0; i < (int)SystemVars->fSimSpeed; i++)
               NewtonUpdate(g_world, timestepInSecunds);


It runs fine on 2x and 4x, stutters and 8x and 16x, and stops responding at 32x. I must be doing something wrong because the first method I tried (long time steps) was stuttering but it didn't stop responding, it worked all the way at 128x compression...
Misho Katulic
CTO, FSX SpacePort
TerraBuilder
www.terrabuilder.com
misho
 
Posts: 673
Joined: Tue May 04, 2010 10:13 am

Re: Proper time compression/dilation in NewtonUpdate()

Postby Sweenie » Fri Oct 04, 2019 7:03 am

I was gonna direct you to a classic article about the topic called "Fix your timestep" by Glenn Fiedler (GafferOnGames.com) but that site seems to be down.
Here is a similar article, read the whole article but the last example is most close to what I mean.
https://dewitters.com/dewitters-gameloop/

That article also implements a protection from what Fiedler called the "spiral of death" meaning that the physics(or logic) updates takes so much time that your game can't keep up the frame rate and eventually everything will stall. In that case you will need to "skip frames" or rather skip some physics updates to uphold the frame rate. That is what I meant with running the simulation 128 times faster than realtime will require a very fast computer depending on how heavy your simulation is.

[EDIT] Here is another article on the topic.
https://medium.com/@tglaiel/how-to-make ... c61210fe75
Sweenie
 
Posts: 498
Joined: Mon Jan 24, 2005 7:59 am
Location: Sweden

Re: Proper time compression/dilation in NewtonUpdate()

Postby misho » Fri Oct 04, 2019 12:54 pm

Thanks - I'll give it a read.

However - My sim is not "heavy" at all... at least, my test case isn't. I remember that 2 years ago, demoSandBox had a physics frame rate counter and it would run easily at 500 fps (so, I assume 500 calls to NewtonUpdate()) with hundreds of bodies colliding.

My test scene has only 3 Newton Bodies which are connected via a hard joint (they comprise a spacecraft) and there are no collisions happening.
Misho Katulic
CTO, FSX SpacePort
TerraBuilder
www.terrabuilder.com
misho
 
Posts: 673
Joined: Tue May 04, 2010 10:13 am

Re: Proper time compression/dilation in NewtonUpdate()

Postby Sweenie » Mon Oct 07, 2019 2:45 am

It's plenty of space in space :lol:

The most basic version of the loop goes like this...
Code: Select all
PHYSICS_STEP = 1.0/60.0

*Mainloop*

accumulator += elapsedtime
while(accumulator >= PHYSICS_STEP)
{
  NewtonUpdate(world, PHYSICS_STEP)
  accumulator -= PHYSICS_STEP
}

interpolationparam = accumulator / PHYSICS_STEP



In the above code one simple way to slow down or speed up the simulation is to manipulate the elapsed time.
accumulator += elapsedtime * timescale

The interpolationparam calculated here can be used to interpolate between the previous and current transform to get smooth movement. This will render all physics objects one frame behind but is worth it due to the visual quality you get by interpolating.
When speeding up the simulation I guess interpolation won't be that important since you probably won't be able to notice any stuttering but it will be extremely noticable when slowing down the simulation. It will look like a crappy "Stop motion"-animation without interpolation.
Sweenie
 
Posts: 498
Joined: Mon Jan 24, 2005 7:59 am
Location: Sweden

Re: Proper time compression/dilation in NewtonUpdate()

Postby misho » Tue Oct 08, 2019 4:28 am

Thanks! Ok - let's see if I am getting this right. Here is what I have: (direct from your pseudo code)

Code: Select all
unsigned64 m_accumulator = 0;
#define PHYSICS_STEP  1.0/60.0
void UpdatePhysics(void)
{
   if (g_world && !SystemVars->bSuspendPhysics) {

      m_accumulator += dGetTimeInMicroseconds()/1000000*(int)SystemVars->fSimSpeed;

      while (m_accumulator >= PHYSICS_STEP)
      {
         NewtonUpdate(g_world, PHYSICS_STEP);
         m_accumulator -= PHYSICS_STEP;
      }
   }
}


And the result I am getting is a very fast sim at 1x time compression, and even faster, jerky sim at higher rates. I am concentrating only on time compression for now. Obviously, I am doing something wrong, and I'm guessing it is the confusion between microseconds and seconds conversion...
Misho Katulic
CTO, FSX SpacePort
TerraBuilder
www.terrabuilder.com
misho
 
Posts: 673
Joined: Tue May 04, 2010 10:13 am

Re: Proper time compression/dilation in NewtonUpdate()

Postby Sweenie » Tue Oct 08, 2019 6:55 am

Hmm, you are mixing floats and big ints...

Try this instead...
Code: Select all
float m_accumulator = 0;
#define PHYSICS_STEP  1.0f/60.0f
void UpdatePhysics(void)
{
   if (g_world && !SystemVars->bSuspendPhysics) {

      m_accumulator += dGetElapsedSeconds() * SystemVars->fSimSpeed;

      while (m_accumulator >= PHYSICS_STEP)
      {
         NewtonUpdate(g_world, PHYSICS_STEP);
         m_accumulator -= PHYSICS_STEP;
      }
   }
}


Check first if that works and later you can change the code to use unsigned64 and microseconds instead like Julio does in the sandbox demo. I guess that eliminates floating point errors.
Sweenie
 
Posts: 498
Joined: Mon Jan 24, 2005 7:59 am
Location: Sweden

Re: Proper time compression/dilation in NewtonUpdate()

Postby misho » Tue Oct 08, 2019 1:08 pm

Thanks!

Sorry, but that didn't work at all. It has a capsule in orbit, not moving against the ground, just suspended... Here is my code:

Code: Select all
float m_accumulator = 0;
#define PHYSICS_STEP  1.0f/60.0f
void UpdatePhysics(dFloat timestep)
{
   if (g_world && !SystemVars->bSuspendPhysics) {

      m_accumulator += (float)dGetElapsedSeconds() * SystemVars->fSimSpeed;

      while (m_accumulator >= PHYSICS_STEP)
      {
         NewtonUpdate(g_world, PHYSICS_STEP);
         m_accumulator -= PHYSICS_STEP;
      }
   }
}


The argument timestep in UpdatePhysics() is not used at all, just like in Julio's code. I included it for conformity.
Misho Katulic
CTO, FSX SpacePort
TerraBuilder
www.terrabuilder.com
misho
 
Posts: 673
Joined: Tue May 04, 2010 10:13 am

Re: Proper time compression/dilation in NewtonUpdate()

Postby Sweenie » Tue Oct 08, 2019 3:39 pm

im not sure about dGetElapsedSeconds(), i assumed it would return the time elapsed between each call. But if you pass the elapsed time via the timestep parameter use that instead of dGetElapsedSeconds()
Sweenie
 
Posts: 498
Joined: Mon Jan 24, 2005 7:59 am
Location: Sweden

Re: Proper time compression/dilation in NewtonUpdate()

Postby misho » Tue Oct 08, 2019 6:21 pm

dGetElapsedSeconds(); returns the time step, in seconds, between each call:

Code: Select all
dFloat dGetElapsedSeconds()
{
   dFloat timeStep;
   unsigned64 miliseconds;

   miliseconds = dGetTimeInMicroseconds();

   // optimal keep the fps below 120 fps
   timeStep = dFloat(miliseconds - m_prevTime) * TICKS2SEC;
   m_prevTime = miliseconds;

   return timeStep;
}


But, to make it more clear:

Code: Select all
float m_accumulator = 0;
#define PHYSICS_STEP  1.0f/60.0f
unsigned64 m_lastTime = 0;
void UpdatePhysics(dFloat timestep)
{
   if (g_world && !SystemVars->bSuspendPhysics) {

      unsigned64 thisTime = dGetTimeInMicroseconds();
      unsigned64 timeStep = thisTime - m_lastTime;
      m_lastTime = thisTime;
      float timeStepSeconds = (float)timeStep / 1000000.0f;

      m_accumulator += timeStepSeconds * SystemVars->fSimSpeed;

      while (m_accumulator >= PHYSICS_STEP)
      {
         NewtonUpdate(g_world, PHYSICS_STEP);
         m_accumulator -= PHYSICS_STEP;
      }
   }
}


The above code works, but again, I am getting hiccups and stutters, and it is unfortunately no different than the default demo code in the demoSandbox... back to square one? :roll:
Misho Katulic
CTO, FSX SpacePort
TerraBuilder
www.terrabuilder.com
misho
 
Posts: 673
Joined: Tue May 04, 2010 10:13 am

Re: Proper time compression/dilation in NewtonUpdate()

Postby Sweenie » Thu Oct 10, 2019 5:27 am

Not sure what could cause hiccups or stutter in your simulation.
Without using interpolation it will definitely stutter if your simTime is slowed down but when running the sim in normal speed hiccups or stutter shouldn't be that visible even when not using interpolation.

See if this demo works...
http://www.svenberra.net/InterpolationDemo.zip

It uses the loop as we discussed here.

Run mygame.exe under the bin-folder then click on the Rootnode in the treeview and uncheck/check the interpolation box for the NewtonWorld component to see the difference.
The simspeed is reduced to 1/10 of normal speed.
Press space on the keyboard to reset the stack of boxes.
Sweenie
 
Posts: 498
Joined: Mon Jan 24, 2005 7:59 am
Location: Sweden

Re: Proper time compression/dilation in NewtonUpdate()

Postby misho » Fri Oct 11, 2019 12:33 pm

Thanks, I'll check it out ASAP!

To be clear, once again, I am getting stutters and hiccups at around 8x compression. Up to that, at normal speed, 2x and 4x, it is smooth. Also, I am not testing time dilation (slowing down of the sim to 1/2x and 1/4x speeds), but time dilation wasn't the problem from the getgo - that always worked and I got the smooth movement in both cases. Only the speed up from 4x and higher introduces stutters.
Misho Katulic
CTO, FSX SpacePort
TerraBuilder
www.terrabuilder.com
misho
 
Posts: 673
Joined: Tue May 04, 2010 10:13 am

Re: Proper time compression/dilation in NewtonUpdate()

Postby misho » Fri Oct 11, 2019 3:08 pm

Package not working. No idea why - the dll reported is right there with the executable

Image
Misho Katulic
CTO, FSX SpacePort
TerraBuilder
www.terrabuilder.com
misho
 
Posts: 673
Joined: Tue May 04, 2010 10:13 am

Re: Proper time compression/dilation in NewtonUpdate()

Postby Sweenie » Sat Oct 12, 2019 1:06 pm

Hmm, never seen that. Its partly usling .NET 4.7 but most computer have that nowadays.
Sweenie
 
Posts: 498
Joined: Mon Jan 24, 2005 7:59 am
Location: Sweden


Return to Bugs and Fixes

Who is online

Users browsing this forum: No registered users and 3 guests