Хаотический маятник, демонстрирующий хаотическое поведение с одинаковыми начальными условиями
Мой первый пост о переполнении стека, так что терпите меня. Я построил модель хаотического двойного маятника в python, используя физическую библиотеку pymunk, которая в свою очередь использует библиотеку C chipmunk. Маятник, будучи хаотичным, проявляет чрезвычайную чувствительность к начальным условиям. Тем не менее, я понял, что даже если я запустил симуляцию с точно такими же начальными условиями (без изменения нулевого кода), эти две симуляции расходятся довольно быстро.
В моем коде есть что-то, что может давать разные результаты при каждом запуске. Поскольку симуляция хаотична, любая крошечная ошибка, которая не является постоянной между моими прогонами, может привести к большим изменениям.
Что может быть причиной этого? Я не уверен, является ли это следствием небольшого недостатка в бурундуке, пирунке или даже в питоне или моей ОС / ПК.
РЕДАКТИРОВАТЬ:
Вот мой код:
import pyglet
import pymunk
import pymunk.pyglet_util
def add_pendulum(space):
static_body = pymunk.Body()
static_body.position = 400, 400
mass = 10
inertia = pymunk.moment_for_box(mass, 5, 100)
body1 = pymunk.Body(mass, inertia)
body1.position = 350, 400
l1 = pymunk.Poly(body1, [(50, 0), (-50, 0), (-50, 5), (50, 5)])
l1.friction = 0.1
l1.collision_type = 2
pivot_joint = pymunk.PivotJoint(static_body, body1, (400, 400))
space.add(body1, l1, pivot_joint)
mass = 10
inertia = pymunk.moment_for_box(mass, 5, 100)
body2 = pymunk.Body(mass, inertia)
body2.position = 250, 400
l2 = pymunk.Poly(body2, [(50, 0), (-50, 0), (-50, 5), (50, 5)])
l2.friction = 0.1
l2.collision_type = 2
pivot_joint2 = pymunk.PivotJoint(body1, body2, (300, 402.5))
space.add(body2, l2, pivot_joint2)
# A hack to disable all collisions
nocollisions = lambda space, arbiter: False
space.add_collision_handler(2, 2, nocollisions, nocollisions, nocollisions, nocollisions)
window = pyglet.window.Window(800, 600)
space = pymunk.Space()
add_pendulum(space)
space.gravity = (0, -10)
test = [()] # A temporary hack to hide the tuple in a mutable object
def on_draw(dt): #For graphing the moving pendulum
points = test[0]
space.step(dt)
pyglet.gl.glClearColor(0, 0, 0, 1)
window.clear()
pymunk.pyglet_util.draw(space)
points += (int(tuple(space.shapes[1].get_vertices()[1])[0]), int(tuple(space.shapes[1].get_vertices()[1])[1]))
pyglet.gl.glClearColor(200, 200, 200, 1)
pyglet.graphics.draw(len(points)/2, pyglet.gl.GL_POINTS,
('v2i', points)
)
test[0] = points
pyglet.clock.schedule_interval(on_draw, 1/1000.0)
pyglet.app.run()
1 ответ
Относительно вашего on_draw(dt)
функция вызывается из pyglet.clock.schedule_interval
Документ Pyglet Docs гласит:
Параметр dt указывает количество секунд (из-за задержки, нагрузки и погрешности таймера это может быть немного больше или меньше запрошенного интервала).
- Акцент мой.
Каждый раз, когда вы запускаете вашу программу, она будет вызывать on_draw
с немного другим dt
параметр. Вы продолжаете звонить space.step(dt)
который будет немного отличаться при каждом вызове. Учитывая, насколько чувствительна ваша программа к изменяющимся условиям, я думаю, что это виновник.
Не уверен, поможет ли это, но вот еще один вопрос, касающийся фиксированных или переменных временных шагов и физики (ну и движков игры).