在速度和距离不一致和/或嘈杂的向量之间平滑渐变

问题描述 投票:0回答:2

我正在可视化一级方程式比赛中赛车提供的 GPS 数据,并试图为它们在路径上的位置设置动画。 Formula 1 API 提供矢量坐标和时间戳,但时间戳各不相同:它们大约在 100 到 400 毫秒之间更新:

timestamp                   x       y       z
2023-03-19 18:23:39.562     -1396   503     118
2023-03-19 18:23:39.842     -1443   630     118
2023-03-19 18:23:40.142     -1531   868     117
2023-03-19 18:23:40.342     -1589   1028    117
2023-03-19 18:23:40.501     -1636   1157    117
2023-03-19 18:23:40.842     -1772   1527    117
2023-03-19 18:23:41.101     -1813   1640    117
2023-03-19 18:23:41.361     -1932   1964    117
2023-03-19 18:23:41.782     -2015   2190    117
2023-03-19 18:23:42.002     -2080   2368    117
...

可视化数据点如下所示:

我正在使用协程在向量之间进行 Lerp 并更新时间增量,但由于间隙不同,它会产生相当不稳定的动画:

我的协程看起来像这样(感谢@derHugo 这个答案):

private IEnumerator AnimationRoutine()
{
    if (alreadyAnimating) yield break;

    alreadyAnimating = true;

    var lastSample = _samples[0];
    Car.transform.position = lastSample.Position;

    yield return null;
    for (var i = 1; i < _samples.Count; i++)
    {
        var lastPosition = lastSample.Position;
        var currentSample = _samples[i];
        var targetPosition = currentSample.Position;

        var duration = currentSample.TimeDelta;
        var timePassed = 0f;
        while (timePassed < duration)
        {
            var factor = timePassed / duration;

            Car.transform.position = Vector3.Lerp(lastPosition, targetPosition, factor);
            yield return null;
            timePassed += Time.deltaTime;


        }

        Car.transform.position = targetPosition;
        lastSample = currentSample;
    }

    alreadyAnimating = false;

}

有没有一种方法可以维护我拥有的时间数据,但对点之间的过渡进行插值,使它们看起来更平滑?

c# unity3d lerp
2个回答
1
投票

你计算物体在两点之间的平均速度并相应地移动球体而不是加速度。您需要跟踪球体的速度,以便在两点之间应用线性加速度。将加速度累积到球体的速度中,并随着时间的推移将该速度应用到它的位置应该会减少它的波动。

要计算平均加速度,您需要将 B 点的速度减去 A 点的速度除以距离:

(v2 - v1) / d
。要知道球体到达 B 点时的速度,它只是随时间变化的距离。


0
投票

这里发生的事情是点集只定义了汽车的路径而不是汽车的速度。您将需要额外的信息来了解汽车在一圈内的速度。除了空间遥测之外,这还需要时间遥测。

理想情况下,您采用一组(x,y,z)点对应的时间(t)并定义一个空间三次样条曲线,允许您在节点之间进行插值。

Vector3.Lerp
在这里是不够的,因为坡度在节点处不匹配,你将有不连续的速度。

样条参数化了一些参数

t = 0 .. t_lap
描述汽车沿着一圈的位置

float[] t_data, float[] x_data, float[] y_data, float[] z_data;
...
Spline spline_x = new Spline(t_data, x_data);
Spline spline_y = new Spline(t_data, y_data);
Spline spline_z = new Spline(t_data, z_data);

for( int i=0; i<spline.Count; i++)
{ 
    float t = (t_end/(spline.Count-1))*i;
    posVector = new Vector(
        spline_x.Value(t),
        spline_y.Value(t),
        spline_z.Value(t));
    // draw position Vector
}

你可以找到很多在线帖子关于 C# 中的三次样条甚至我自己在 Fortan 中的例子

如果你的问题是你没有时间遥测,如果你可以通过假设沿着轨道的某种速度分布(比如常数,这是不现实的)来弥补它,那么这是一个不同的数学问题。

您需要节点之间的总行进距离(样条曲线的长度),它总是大于

Vector3.Distance()
给出的直线段。

这个距离是用每个距离段的数值积分器评估的

Δs
,它对应于一个小的时间步长
Δt
使用样条斜率(速度)函数

float speed_x = spline_x.Slope(t);
float speed_y = spline_y.Slope(t);
float speed_z = spline_z.Slope(t);
float speed = Math.SqrtF( speed_x*speed_x + speed_y*speed_y + speed_z*speed_z);

float distInterval = Δt / speed;
    

完整的数学处理相当复杂,所以我不确定你是否想沿着这条路走下去,你在这里只需快速估计就足够了。


我在这里找到了一个类似的我的答案关于在 3D 飞机数据之间平滑插值。


还有一个

[Math.NET] Spline
对象你可以使用。

© www.soinside.com 2019 - 2024. All rights reserved.