Плавно сделать число, приближающееся к нулю - PullRequest
1 голос
/ 03 марта 2010

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

Если это произойдет, я хочу, чтобы он плавно вернулся к 0. Я сейчас делаю что-то вроде

addToXspeed(-x * FACTOR);

// below is out of my control
function addToXspeed(bla) {
 xspeed += bla;
 x += xspeed;
}

каждый шаг в анимации, но это только заставляет X колебаться.Однако я хочу, чтобы он опирался на 0.

(я объяснил проблему в рефератах. Конкретная вещь, которую я пытаюсь сделать, это заставить игрового персонажа в прыжках сбалансировать себя в воздухе, применяя вращательную силу)

Ответы [ 5 ]

2 голосов
/ 04 марта 2010

Интересная проблема. Вы запрашиваете стабилизацию следующей линейной системы с дискретным временем:

|     x(t+1)| = | 1   dt | |     x(t)|  +  | 0 | u(t)
|xspeed(t+1)|   | 0    1 | |xspeed(t)|     | 1 | 

, где dt - время выборки, а u(t) - количество, которое вы addToXspeed(). (Кроме того, система подвержена случайным помехам в первой переменной x, которые я не показываю в приведенном выше уравнении.) Теперь, если вы «установите управляющий вход равным линейной обратной связи состояния», то есть

u(t) = [a  b] |     x(t)| = a*x(t) + b*xspeed(t)
              |xspeed(t)|

тогда «замкнутая» система становится

|     x(t+1)| = | 1   dt  | |     x(t)|
|xspeed(t+1)|   | a   b+1 | |xspeed(t)|

Теперь, чтобы получить «асимптотическую устойчивость» системы, мы оговариваем, что собственные значения матрицы с замкнутым контуром помещаются «внутри сложной единичной окружности», и мы делаем это путем настройки a и b. Мы помещаем собственные значения, скажем, в 0,5. Поэтому характеристический полином матрицы с обратной связью, который равен

(s - 1)(s - (b+1)) - a*dt = s^2 -(2+b)*s + (b+1-a*dt)

должно равняться

(s - 0.5)^2 = s^2 - s + 0.25

Этого легко достичь, если мы выберем

b = -1    a = -0.25/dt

или

u(t) = a*x(t) + b*xspeed(t) = -(0.25/dt)*x(t) - xspeed(t)
addToXspeed(u(t))

что более или менее соответствует вашему собственному ответу

targetxspeed = -x * FACTOR;
addToXspeed(targetxspeed - xspeed);

где, если нас просят поместить собственные значения в 0,5, мы должны установить FACTOR = (0.25/dt).

1 голос
/ 03 марта 2010

х = х * ФАКТОР

Это следует делать, когда коэффициент находится между 0 и 1.

Чем ниже коэффициент, тем быстрее вы перейдете к 0.

0 голосов
/ 03 марта 2010

Если вы хотите масштабировать его, но можете только добавить, то вам нужно выяснить, какое значение добавить, чтобы получить желаемое масштабирование:

Скажем, x = 0.543, и мы хотим, чтобы он быстро шел к 0, то есть уменьшив его на 95%.

Мы хотим сделать:

scaled_x = x * (1.0 - 0.95);

Это оставило бы x на 0,543 * 0,05 или 0.02715. Разница между этим значением и оригиналом заключается в том, что вам нужно добавить, чтобы получить это значение:

delta = scaled_x - x;

Это сделает дельту равной -0,51585, что вам нужно добавить, чтобы имитировать масштабирование на 5%.

0 голосов
/ 03 марта 2010

Написание вопроса часто приводит к пониманию ответа.

targetxspeed = -x * FACTOR;
addToXspeed(targetxspeed - xspeed);

// below is out of my control
function addToXspeed(bla) {
 xspeed += bla;
 x += xspeed;
}

Так просто тоже

0 голосов
/ 03 марта 2010

Почему бы вам не определить фиксированный шаг, который будет уменьшен с x?

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...