liabru / matter-js

a 2D rigid body physics engine for the web ▲● ■
MIT License
16.62k stars 1.96k forks source link

Velocities are incorrect, 0.016666x too big #240

Open adamgreig opened 8 years ago

adamgreig commented 8 years ago

In Body.update, the body "velocity" is computed, but this is actually a "change in position for this timestep", i.e., has units of "metres per 1/60 seconds" rather than "metres per second". If you compare to the reference for your Verlet integration scheme, the quantity computed isn't labelled v for presumably this reason.

To be more concrete, you can (I did) run a simple experiment with a falling object in gravity, logging the time, height, and velocity at each step. Then compute the velocity as "dh/dt" between each time step and you'll find the result is much (1/60) smaller than what gets saved as body.velocity.

This doesn't cause errors in the actual physics because the computations are all as they should be, but the velocity number is wrong if you try to use it for anything else (in my case, computing kinetic energy). It might also affect things like the friction calculations but I haven't looked.

The solution is to bind this as velocity in the update function, but set body.velocity to velocity / deltaTime.

liabru commented 8 years ago

This is intentional, because velocity measured per step can often be more convenient than per second in some cases when time is discrete. I understand this may be a little confusing for those expecting this to match the usual definition. I should definitely update the documentation that makes note of this.

But I'm not sure that this should be changed in the code at this stage as it might mean lots of extra conversions, or a second velocity value to be stored which would be confusing? So I think it's better at the moment that you convert or calculate your own velocities as suits your application. Also see a similar discussion in #179.

adamgreig commented 8 years ago

Ok, thanks, that makes sense. It's certainly an easy conversion to make once you know what's going on, but caused me some confusion at first!

It might be nice to also document that the base units for time are milliseconds, so forces are measured in meganewtons, if you want to apply real-world units to things.

179 says the base units for the engine are MKS, but since '1' time is 1ms (and 16.67 of them per timestep), applying '1' force gives you 1 metre/millisecond/millisecond which is 1e6 metre/second/second. I think it's fair to say the base unit of time is therefore milliseconds as that's what gets you 1 speed => 1 distance/time and 1 force per 1 mass => 1 distance/time/time. Even after scaling the velocities by 16.6 to get speed in distance/time instead of distance/timestep, you'll still be measuring metres/millisecond, etc. Obviously it's just another conversion factor and so I don't think it needs to be changed in code, but documenting that the base time unit is milliseconds would be really helpful to anyone trying to match it up with real-life physical systems.