viblo / pymunk

Pymunk is a easy-to-use pythonic 2d physics library that can be used whenever you need 2d rigid body physics from Python
http://www.pymunk.org
MIT License
903 stars 187 forks source link

Slows down at no friction #216

Closed milen-prg closed 1 year ago

milen-prg commented 1 year ago

I make pendulum:

p1 = pm.Body(body_type=pm.Body.STATIC) p1.position = 300, 100 shape1 = pm.Circle(p1, 10) shape1.mass = 1 shape1.friction = 0 shape1.elasticity = 1 space.add(p1, shape1) p2 = pm.Body() p2.position = 600, 100 shape2 = pm.Circle(p2, 10) shape2.mass = 1 shape2.friction = 0 shape2.elasticity = 1 space.add(p2, shape2)

Which slows down visually for about a minute! The friction, elasticity not changes nothing. Also decreasing the time step, not change the tendency to stop. How to set ideal not slowing pendulum in pymunk?

viblo commented 1 year ago

Can you post a full example?

But in general I dont think its possible, there will be small inconsistencies that build up over time. You can easily see this in the newtons cradle example https://github.com/viblo/pymunk/blob/master/examples/newtons_cradle.py

milen-prg commented 1 year ago
import sys
import pygame
import pymunk as pm
import pymunk.pygame_util

pygame.init()
screen = pygame.display.set_mode((600, 600))
pygame.display.set_caption("Joints.")
clock = pygame.time.Clock()

draw_options = pm.pygame_util.DrawOptions(screen)
space = pm.Space()
space.gravity = (0.0, 981.0)

p1 = pm.Body(body_type=pm.Body.STATIC)
p1.position = 300, 100
shape1 = pm.Circle(p1, 10)
shape1.mass = 1
shape1.friction = 0
shape1.elasticity = 1
space.add(p1, shape1)
p2 = pm.Body()
p2.position = 600, 100
shape2 = pm.Circle(p2, 10)
shape2.mass = 1
shape2.friction = 0
shape2.elasticity = 1
space.add(p2, shape2)

l = pm.PinJoint(p2, p1)
space.add(l)

while True:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            sys.exit(0)
        elif event.type == pygame.KEYDOWN and event.key == pygame.K_ESCAPE:
            sys.exit(0)

    screen.fill((0, 55, 55))

    space.step(1/150.0) #3

    space.debug_draw(draw_options)

    pygame.display.flip()

    clock.tick(150)

Initially the red circle half outs of the window, after a minute the slowing is visible, after about two-three minutes, the red circle stops touching the window edges. I seen the newton cradle example, but there is "energy losses" in slow moving of the other circles, also after some time (not long), the mode may changes - starts to move more circles, not only the edges. Seems that these libraries (I also tried with the same result Box2D) have no such high accuracy (even at very small time step) to make virtual physics experiments and are proper only for games. I search some simple Python alternative of the popular Algodoo simulator.

viblo commented 1 year ago

Ok, then I understand better. Pymunk uses the C-library Chipmunk2D for the actual physics simulation. Chipmunk and Box2D are quite similar, since Chipmunk used some base ideas from Box2d when it was started. (At the same time, many things have changed since then, so they are not so similar anymore).

The Algodoo simulator uses its own physics engine, which is built on the SPOOK solver. I very quickly skimmed the original SPOOK paper, and it claims to be more stable/accurate than other methods such as Euler and RK. I suspect this is why it handles the pendulum much better than Pymunk does, and unfortunately I dont think there's an easy fix.

milen-prg commented 1 year ago

Yes, these libraries are more for games, not so scientific. Thank you, I had to ensure that it is not some my fault in my code (some missed settings).