如何计算负加速度? [英] how to calculate a negative acceleration?

查看:122
本文介绍了如何计算负加速度?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在实现触摸屏UI的滚动行为,但此刻我太累了,无法将精力集中在一些琐碎的数学上:

I'm implementing the scrolling behaviour of a touch screen UI but I'm too tired in the moment to wrap my mind around some supposedly trivial piece of math:

y (distance/velocity)
|********
|        ******
|              ****
|                  ***
|                     ***
|                        **
|                          **
|                            *
|                             *
-------------------------------- x (time)

f(x)->?

该UI应该允许用户在任何方向上拖动和扔"一个视图,并且即使在用户从屏幕上松开手指后也可以保持滚动一段时间.动力的大小取决于用户在脱下手指之前拖动的速度.

The UI is supposed to allow the user to drag and "throw" a view in any direction and to keep it scrolling for a while even after he releases the finger from the screen. It's sort of having a momentum that depends on how fast the user was dragging before he took off the finger.

所以我有一个起始速度(v0),每20ms滚动一次相对于当前速度的量.每次滚动迭代时,我都会稍微降低速度,直到停止时它降至阈值以下.当我将其递减固定量(线性)时,它看起来并不正确,因此我需要对负加速度建模,但无法提出一个不错的简单公式来计算如何降低速度在每次迭代中.

So I have a starting velocity (v0) and every 20ms I scroll by a amount relative to the current velocity. With every scrolling iteration I lower the velocity a bit until it falls below a threshold when I stop it. It just doesn't look right when I decrement it by a fixed amount (linear), so I need to model a negative acceleration but fail to come up with a decent simple formula how to calculate the amount by which I have to lower the velocity in every iteration.

更新:

到目前为止,感谢您的回复,但是我仍然无法从反馈中得出令人满意的功能.我可能没有很好地描述所需的解决方案,因此我将尝试给出一个真实的示例,该示例应说明我想进行哪种计算:

Thank you for your responses so far but I still didn't manage to derive a satisfying function from the feedback yet. I probably didn't describe the desired solution good enough, so I'll try to give a real world example that should illustrate what kind of calculation I would like to do:

假设在某条街道上有某辆汽车在行驶,并且驾驶员踩下了刹车,直到汽车停下为止.驾驶员多次在同一条街道上使用同一辆汽车执行此操作,但开始以不同的速度制动.当汽车减速时,我希望能够计算出速度,仅根据当前速度,它就会精确到一秒钟.对于此计算,驾驶员在开始休息时以什么速度行驶并不重要,因为所有环境因素都保持不变.当然,公式中会有一些常数,但是当汽车降到30 m/s时,下一秒它会走相同的距离,而无论驾驶员开动时是驾驶100 m/s还是行驶50 m/s .因此,击中中断后的时间也不是该函数的参数.一定速度下的减速度始终是相同的.

Assume there is a certain car driving on a certain street and the driver hits the brakes to a max until the car comes to a halt. The driver does this with the same car on the same street multiple times but begins to brake at varying velocities. While the car is slowing down I want to be able to calculate the velocity it will have exactly one second later solely based on it's current velocity. For this calculation it should not matter at which speed the car was driving when the driver began to break since all environmential factors remain the same. Of course there will be some constants in the formula but when the car is down to i.e. 30 m/s it will go the same distance in the next second, regardless whether it was driving 100 or 50 m/s when the driver began to break. So the time since hitting the breaks would also not be a parameter of the function. The deceleration at a certain velocity would always be the same.

在这种情况下,如何假设减速,质量,摩擦力等任意常数,并忽略诸如空气阻力等复杂影响,如何在一秒钟后计算速度?我只是在动能和它的消耗,因为动车会产生摩擦.

How do you calculate the velocity one second later in such a situation assuming some arbitrary constants for deceleration, mass, friction or whatever and ignoring complicating influences like air resistance? I'm only after the kinetic energy and the it's dissipation due to the friction from breaking the car.

更新2 现在,我知道汽车的加速度将很小,而这实际上并不是我想要的.我会收拾干净,明天再尝试新的建议.到目前为止,谢谢您的投入.

Update 2 I see now that the acceleration of the car would be liniear and this is actually not what I was looking for. I'll clean this up and try out the new suggestions tomorrow. Thank you for your input so far.

推荐答案

[简短回答(假设C语法)]

[Short answer (assuming C syntax)]

double v(double old_v, double dt) {
    t = t_for(old_v); 
    new_t = t - dt; 
    return (new_t <= 0)?0:v_for(t);
} 

double t_for(double v)double v_for(double t)是从v到t双向映射(数学意义上的函数)的返回值,该值是任意的,且约束条件是单thonic且为v >=0定义(因此具有点v=0).一个例子是:

double t_for(double v) and double v_for(double t) are return values from a v-to-t bidirectional mapping (function in mathematical sence), which is arbitrary with the constraint that it is monothonic and defined for v >=0 (and hence has a point where v=0). An example is:

double v_for(double t) { return pow(t, k); }
double t_for(double v) { return pow(v, 1.0/k); }

具有以下位置:

  1. k>1随着时间的流逝,模数使减速度降低.
  2. k<1随着时间的流逝,模数使减速度增加.
  3. k=1给出恒定的减速速度.
  1. k>1 gives deceleration decreasing by modulo as time passes.
  2. k<1 gives deceleration increasing by modulo as time passes.
  3. k=1 gives constant deceleration.

[更长的一个(包含基本原理和情节)]

所以目标要点是:

  1. 寻找一个函数v(t+dt)=f(v(t),dt),该函数采用当前速度值v和时间增量dt并返回时刻t+dt的速度(由于t >是已知的,并作为参数提供,而dt只是时间增量. 换句话说,任务是实现具有特定属性的例程double next_v(curr_v, dt);(请参见下文).

  1. To find a function v(t+dt)=f(v(t),dt) which takes current velocity value v and time delta dt and returns the velocity at the moment t+dt (it does not require actually specifying t since v(t) is already known and supplied as a parameter and dt is just time delta). In other words, the task is to implement a routine double next_v(curr_v, dt); with specific properties (see below).

[请注意] 有问题的函数具有有用的(并且是理想的)属性,无论先前速度的历史"如何,都可以返回相同的结果变化.这意味着,例如,如果一系列连续速度为[100,50,10,0](对于起始速度v0=100),则大于此速度的任何其他序列将具有相同的尾巴":[150] ,100、50、10、0](对于起始速度v0=150)等. 换句话说,无论起始速度如何,所有速度-时间图将有效地复制每个 .

[Please Note] The function in question has a useful (and desired) property of returning the same result regardless of the "history" of previous velocity changes. That means, that, for example, if the series of consecutive velocities is [100, 50, 10, 0] (for the starting velocity v0=100), any other sequence larger than this will have the same "tail": [150, 100, 50, 10, 0] (for the starting velocity v0=150), etc. In other words, regardless of the starting velocity, all velocity-to-time plots will effectively be copies of each other just offset along the time axis each by its own value (see the graph below, note the plots' parts between the lines t=0.0 and t=2.0 are identical) .

此外,加速度w(t)=dv(t)/dt必须是时间t的下降函数(出于在此建模的移动GUI对象的视觉愉悦和直观"行为的目的.)

Besides, acceleration w(t)=dv(t)/dt must be a descending function of time t (for the purpose of visually pleasing and "intuitive" behaviour of the moving GUI object which we model here).

建议的想法是:

  1. 首先,选择一个具有所需特性的 单音速函数 (在您的情况下,它是逐渐减小加速度,但是,如下面的示例所示,它是更容易使用加速"的). 此函数也必须没有上限 ,以便您可以将其用于任何较大的速度值.另外, 它必须具有一个速度为零的点 .一些例子是:v(t) = k*t(不完全是您的情况,因为减速k在这里是恒定的),v=sqrt(-t)(可以,在间隔t <= 0上定义).

  1. First you choose a monothonic velocity function with desired properties (in your case it is gradually decreasing acceleration, though, as the example below shows, it is easier to use "accelerated" ones). This function must not also have an upper boundary, so that you could use it for whatever large velocity values. Also, it must have a point where velocity is zero. Some examples are: v(t) = k*t (not exactly your case, since deceleration k is constant here), v=sqrt(-t) (this one is ok, being defined on the interval t <= 0).

然后,对于任何给定的速度,您都会在上述函数的图上找到具有该速度值的点(由于该函数未绑定,因此将存在一个点,由于其为单音阶,因此只有一个点)前进通过时间δ向较小的速度值移动,从而获得下一个速度值.迭代将逐渐(不可避免地)使您到达速度为零的位置.

Then, for any given velocity, you find the point with this velocity value on the above function's plot (there will be a point, since the function is not bound, and only one since it is monothonic), advance by time delta towards smaller velocity values, thus acquiring the next one. Iteration will gradually (and inevitably) bring you to the point where velocity is zero.

基本上就是全部, 甚至不需要生成一些最终"公式,对时间值或初始(不是当前)速度的依赖就消失了,编程变得非常简单 .

That's basically all, there is even no need to produce some "final" formula, dependencies on time value or initial (not current) velocities go away, and the programming becomes really simple.

在两个简单的情况下,这个小的python脚本会产生下面的图(给定的初始速度为1.010.0),并且,如您所见, 来自任何给定的速度水平"和向下"将情节表现"相同 ,这是因为 无论您以何种速度开始减速(减速),您都将沿着运动"相对于速度为(变为)零的点的相同曲线 :

For two simple cases this small python script produces the plots below (initial velocities given were 1.0 to 10.0), and, as you can see, from any given velocity "level" and "downwards" the plots "behave" the same which is of couse because no matter at what velocity you start to slow down (decelerate), you are "moving" along the same curve RELATIVE to the point where velocity is (becomes) zero:

import numpy
import pylab

import math


class VelocityCurve(object):
    """
    An interface for the velocity 'curve'.
    Must represent a _monotonically_ _growing_
        (i.e. with one-to-one correspondence
        between argument and value) function
        (think of a deceleration reverse-played)
    Must be defined for all larger-than-zero 'v' and 't'
    """
    def v(self, t):
        raise NotImplementedError

    def t(self, v):
        raise NotImplementedError



class VelocityValues(object):

    def __init__(self, v0, velocity_curve):
        assert v0 >= 0
        assert velocity_curve

        self._v = v0
        self._vc = velocity_curve

    def next_v(self, dt):
        t = self._vc.t(self._v)
        new_t = t - dt

        if new_t <= 0:
            self._v = 0
        else:
            self._v = self._vc.v(new_t)

        return self._v


class LinearVelocityCurve(VelocityCurve):

    def __init__(self, k):
        """k is for 'v(t)=k*t'"""
        super(LinearVelocityCurve, self).__init__()

        self._k = k

    def v(self, t):
        assert t >= 0
        return self._k*t

    def t(self, v):
        assert v >= 0
        return v/self._k


class RootVelocityCurve(VelocityCurve):

    def __init__(self, k):
        """k is for 'v(t)=t^(1/k)'"""
        super(RootVelocityCurve, self).__init__()

        self._k = k

    def v(self, t):
        assert t >= 0
        return math.pow(t, 1.0/self._k)

    def t(self, v):
        assert v >= 0
        return math.pow(v, self._k)


def plot_v_arr(v0, velocity_curve, dt):
    vel = VelocityValues(v0, velocity_curve)
    v_list = [v0]

    while True:
        v = vel.next_v(dt)
        v_list.append(v)

        if v <= 0:
            break

    v_arr = numpy.array(list(v_list))
    t_arr = numpy.array(xrange(len(v_list)))*dt

    pylab.plot(t_arr, v_arr)


dt = 0.1

for v0 in range(1, 11):
    plot_v_arr(v0, LinearVelocityCurve(1), dt)

for v0 in range(1, 11):
    plot_v_arr(v0, RootVelocityCurve(2), dt)


pylab.xlabel('Time ')
pylab.ylabel('Velocity')

pylab.grid(True)

pylab.show()

这给出了以下图表(线性减速(即恒定减速)的线性图,曲线"-对于平方根"的情况(请参见上面的代码)):

This gives the following plots (linear ones for the linear decelerating (i.e. constant deceleration), "curvy" -- for the case of the "square root" one (see the code above)):

还请注意,要运行上述脚本,需要安装 pylab,numpy 和朋友(但仅对于绘图部分,核心"类不依赖任何内容,当然可以在自己的).

Also please beware that to run the above script one needs pylab, numpy and friends installed (but only for the plotting part, the "core" classes depend on nothing and can be of course used on their own).

P.S.通过这种方法,人们可以真正构建"他喜欢的拖动"(例如,为不同的t间隔增加不同的功能,甚至平滑手绘的(记录的)人体工程学"曲线):

P.S. With this approach, one can really "construct" (for example, augmenting different functions for different t intervals or even smoothing a hand-drawn (recorded) "ergonomic" curve) a "drag" he likes:)

这篇关于如何计算负加速度?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆