Почему коробка продолжает двигаться после полного включения тормозов? - PullRequest
0 голосов
/ 30 октября 2019

Я сделал минимальный симулятор горизонтального движения с квадратичным сопротивлением, который можно найти здесь (управляется клавишами со стрелками влево и вправо). В качестве упражнения я попытался реализовать торможение в дополнение к приложенному усилию и сопротивлениюОн работает, когда пробел удерживается нажатым, но после того, как коробка отпущена, коробка начинает снова двигаться с низкой скоростью в, казалось бы, случайном направлении. Вот что я считаю соответствующим кодом:

let vt = 500 // terminal velocity
let amag = 1000 // magnitude of applied acceleration
let bmag = 1000 // magnitude of brake's acceleration
let drag = amag / (vt*vt) // coeffcient of quadratic drag

let x  = 0 // horizontal position
let vx = 0 // horizontal velocity

function update(timestamp) {
  let dt = ... // compute time delta from timestamp

  // current acceleration
  let ax = (keyStates.ArrowRight * amag) + (keyStates.ArrowLeft * -amag) - (keyStates[' '] * bmag * Math.sign(vx))

  // forward euler method; solves (x'(t), vx'(t)) = (vx(t), ax(t) - drag * vx(t)^2)
  x  += dt * vx
  vx += dt * (ax - Math.sign(vx) * drag * vx * vx)
}

1 Ответ

0 голосов
/ 30 октября 2019

Величина вашего тормоза больше, чем ваша vx при медленном движении. Кроме того, ваше тормозное усилие действует в направлении, противоположном направлению движения. Следовательно, торможение не 0-out vx, а вместо этого отскакивает vx в районе 0.

Например, представьте bmag = 1, dt = 1 и vx = 2.6. Вместо vx происходит 2.6 -> 1.6 -> 0.6 -> 0 вместо этого идет 2.6 -> 1.6 -> 0.6 -> -0.4 -> 0.6 -> -0.4...

Это не заметно во время торможения, потому что движения взаимно компенсируют друг друга, поскольку оно постоянно меняет направление. Но как только вы отпускаете тормоз, он продолжается либо на 0.6, либо на -0.4 в зависимости от времени, отсюда и ваше наблюдаемое «кажущееся случайным направление».

Чтобы исправить это, просто обнулите vx, когда bmag * dt > vx.

  // current acceleration
  let ax = (keyStates.ArrowRight * amag) + (keyStates.ArrowLeft * -amag);

  // forward euler method; solves (x'(t), vx'(t)) = (vx(t), ax(t) - drag * vx(t))
  x  += dt * vx
  vx += dt * (ax - Math.sign(vx) * drag * vx * vx)

  if (keyStates[' '])
     if (Math.abs(vx) > dt * bmag)
       vx -= dt * bmag * Math.sign(vx);
     else
       vx = 0;

Кстати, спасибо за предоставленный воспроизводимый пример и небольшое подмножество, которое уместно. Это помогает как потенциальным ответчикам, так и будущим читателям.

...