liabru / matter-js

a 2D rigid body physics engine for the web ▲● ■

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Energy loss, despite air friction 0

miwick opened this issue · 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}));
commented

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).