开发者

Smoothly make a number approach zero

开发者 https://www.devze.com 2022-12-21 23:23 出处:网络
I have 开发者_JAVA技巧a floating point value X which is animated. When in rest it\'s at zero, but at times an outside source may change it to somewhere between -1 and 1.

I have 开发者_JAVA技巧a floating point value X which is animated. When in rest it's at zero, but at times an outside source may change it to somewhere between -1 and 1.

If that happens I want it to go smoothly back to 0. I currently do something like

addToXspeed(-x * FACTOR);

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

every step in the animation, but that only causes X to oscillate. I want it to rest on 0 however.

(I've explained the problem in abstracts. The specific thing I'm trying to do is make a jumping game character balance himself upright in the air by applying rotational force)


Interesting problem. What you are asking for is the stabilization of the following discrete-time linear system:

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

where dt is the sampling time and u(t) is the quantity you addToXspeed(). (Further, the system is subject to random disturbances on the first variable x, which I don't show in the equation above.) Now if you "set the control input equal to a linear feedback of the state", i.e.

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

then the "closed-loop" system becomes

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

Now, in order to obtain "asymptotic stability" of the system, we stipulate that the eigenvalues of the closed-loop matrix are placed "inside the complex unit circle", and we do this by tuning a and b. We place the eigenvalues, say, at 0.5. Therefore the characteristic polynomial of the closed-loop matrix, which is

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

should equal

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

This is easily attained if we choose

b = -1    a = -0.25/dt

or

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

which is more or less what appears in your own answer

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

where, if we are asked to place the eigenvalues at 0.5, we should set FACTOR = (0.25/dt).


x = x*FACTOR

This should do the trick when factor is between 0 and 1.

The lower the factor the quicker you'll go to 0.


Why don't you define a fixed step to be decremented from x?

You just have to be sure to make it small enough so that the said person doesn't seem to be traveling at small bursts at a time, but not small enough that she doesn't move at a perceived rate.


Writing the question oftens results in realising the answer.

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

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

So simple too


If you want to scale it but can only add, then you have to figure out which value to add in order to get the desired scaling:

Let's say x = 0.543, and we want to cause it to rapidly go towards 0, i.e. by dropping it by 95%.

We want to do:

scaled_x = x * (1.0 - 0.95);

This would leave x at 0.543 * 0.05, or 0.02715. The difference between this value and the original is then what you need to add to get this value:

delta = scaled_x - x;

This would make delta equal -0,51585, which is what you need to add to simulate a scaling by 5%.

0

精彩评论

暂无评论...
验证码 换一张
取 消