Интегратор верлет + трение

Я следовал " Основанному на Verlet подходу к физике 2D-игр" на Gamedev.net, и я написал нечто подобное.

У меня проблема в том, что ящики слишком сильно скользят по земле. Как я могу добавить простую вещь в состоянии покоя, где коробки будут иметь большее трение и будут скользить лишь чуть-чуть?

3 ответа

Решение

Просто введите небольшое постоянное ускорение на движущиеся объекты, которые указывают в направлении, противоположном движению. И убедитесь, что он не может полностью изменить движение; если вы обнаружите это на этапе интеграции, просто установите скорость на ноль.

Если вы хотите быть более реалистичным, ускорение должно происходить от силы, которая пропорциональна нормальной силе между объектом и поверхностью, по которой он скользит.

Вы можете найти это в любом основном физическом тексте, как "кинетическое трение" или "трение скольжения".

Вот простая схема временного шага (симплектический метод Эйлера с ручным разрешением LCP) для коробки с кулоновским трением и пружиной ( фрикционный осциллятор ).

mq'' + kq + mu*sgn(q') = F(t)

      import numpy as np
import matplotlib.pyplot as plt

q0 = 0   # initial position
p0 = 0  # initial momentum
t_start = 0   # initial time
t_end = 10   # end time
N = 500 # time points
m = 1   # mass
k = 1   # spring stiffness

muN = 0.5   # friction force (slip and maximal stick)
omega = 1.5   # forcing radian frequency [RAD]
Fstat = 0.1   # static component of external force
Fdyn = 0.6   # amplitude of harmonic external force
F = lambda tt,qq,pp: Fstat + Fdyn*np.sin(omega*tt) - k*qq - muN*np.sign(pp)  # total force, note sign(0)=0 used to disable friction
zero_to_disable_friction = 0

omega0 = np.sqrt(k/m)
print("eigenfrequency   f = {} Hz;   eigen period   T = {} s".format(omega0/(2*np.pi), 2*np.pi/omega0))
print("forcing frequency   f = {} Hz;   forcing period   T = {} s".format(omega/(2*np.pi), 2*np.pi/omega))

time = np.linspace(t_start, t_end, N)   # time grid
h = time[1] - time[0]   # time step
q = np.zeros(N+1)   # position
p = np.zeros(N+1)   # momentum
absFfriction = np.zeros(N+1)

q[0] = q0   
p[0] = p0
for n, tn in enumerate(time):
   
    p1slide = p[n] + h*F(tn, q[n], p[n])   # end-time momentum, assuming sliding
    q1slide = q[n] + h*p1slide/m   # end-time position, assuming sliding
    
    if p[n]*p1slide > 0:   # sliding goes on
        q[n+1] = q1slide
        p[n+1] = p1slide
        absFfriction[n] = muN
        
    else:
        q1stick = q[n]   # assume p1 = 0 at t=tn+h
        Fstick = -p[n]/h - F(tn, q1stick, zero_to_disable_friction)    # friction force needed to stop at t=tn+h
        if np.abs(Fstick) <= muN:
            p[n+1] = 0   # sticking
            q[n+1] = q1stick
            absFfriction[n] = np.abs(Fstick)
        else:  # sliding starts or passes zero crossing of velocity
            q[n+1] = q1slide   # possible refinements (adapt to slip-start or zero crossing)
            p[n+1] = p1slide
            absFfriction[n] = muN

При интеграции verlet: r(t)=2.00*r(t-dt)-1.00*r(t-2dt)+2at²измените множители на 1,99 и 0,99 для трения

Изменить: это более верно:

r(t)=(2.00-friction_mult.)*r(t-dt)-(1.00-friction_mult.)*r(t-2dt)+at²

Другие вопросы по тегам