matter-js icon indicating copy to clipboard operation
matter-js copied to clipboard

Energy loss, despite air friction 0

Open miwick opened this issue 1 year ago • 1 comments

First of all, this project is great. Liam, Thank you very much for it!

I would like to use matter.js to teach physics. One of the first examples is a simple pendulum. I have set air friction to 0, but energy is still lost and the pendulum slows down. Is this simply a consequence of the numerical implementation or am I doing something wrong?

Here is an example:

let engine = Matter.Engine.create();
world = engine.world;
let render = Matter.Render.create({element: document.body,engine: engine,options: {width: 600,height: 800,wireframes: false,background: '#f8f9fa'}});
Matter.Render.run(render);
let runner = Matter.Runner.create();
Matter.Runner.run(runner, engine);
var ball = Matter.Bodies.circle(100, 400, 50, {frictionAir: 0});
Matter.Composite.add(world, ball);
Matter.Composite.add(world, Matter.Constraint.create({pointA: { x: 300, y: 100 },bodyB: ball}));

miwick avatar Nov 05 '23 06:11 miwick

Yes, that is indeed a consequence of this implementation of Verlet integration.

One way would be to keep track of energy yourself, and after each engine update slightly modify the velocity of the pendulum to conserve energy.

const g = engine.gravity.y / 3.625;   // empirically determined
const energy = ball.speed**2 / 2      // kinetic
             + g * -ball.position.y;  // + potential

Matter.Events.on(engine, 'afterUpdate', _event => {
  let speed = Math.sqrt( 2 * (energy - g * -ball.position.y) );
  if (speed > 0.01) Matter.Body.setSpeed(ball, speed);
  // (the conditional prevents getting 'stuck' at extremes)
});

To make this work for more complex systems like Newton's cradle you would probably have to determine which bodies you want to adjust to conserve the speed (probably the one that's moving the fastest).

wilcooo avatar Nov 15 '23 23:11 wilcooo