unity3d 在速度和距离不一致和/或有噪声的矢量之间平滑地重叠

5lhxktic  于 2023-04-12  发布在  其他
关注(0)|答案(2)|浏览(128)

我正在可视化F1比赛中的汽车提供的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的this answer):

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;

}

有没有一种方法可以保持我的时间数据,但插入点之间的过渡,使他们看起来更平滑?

vwhgwdsa

vwhgwdsa1#

计算物体在两点之间的平均速度,并相应地移动球体,但不计算加速度。您需要跟踪球体的速度,以便在两点之间应用线性加速度。将加速度累积到球体的速度中,并将该速度应用到其随时间推移的位置中,应该会使其不那么起伏。
要计算平均加速度,您需要将B点的速度减去A点的速度,再除以距离:(v2 - v1) / d,要知道球体到达B点时的速度,就是距离对时间的变化.

a7qyws3x

a7qyws3x2#

这里发生的事情是,这组点只定义了汽车的路径,而不是汽车的速度。您将需要额外的信息来获得汽车沿着圈的速度。除了空间遥测外,还需要时间遥测。
理想情况下,取对应时间(t)的(x,y,z)点的集合,并定义一条空间三次样条曲线,该曲线允许在节点之间进行插值。
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
}

您可以找到许多在线帖子about cubic splines in C#甚至my own example in Fortan
如果你的问题是你没有时间遥测,如果你可以通过假设沿着轨道的某种速度剖面(比如不现实的常数)来弥补,那么这是一个不同的数学问题。
你需要节点之间的总距离(样条曲线的长度),它总是大于Vector3.Distance()给出的直线段。
使用样条斜率(速度)函数,利用对应于小时间步长Δt的每个距离段Δs的数值积分器来评估该距离

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;

完整的数学处理是相当复杂的,所以我不确定你想沿着这条路走下去,你只需要快速估计一下就足够了。
我在这里发现了一个类似的answer of mine,它是关于在3D中平滑地内插飞机数据的。
还有一个[Math.NET] Spline对象可以使用。

相关问题