计算球到达目的地所需时间的公式,球的 x y 在时间循环中更新

Formula to calculate time needed for a ball to reach destination where the ball's x y is updated in a time loop

我正在编写球运动的模拟代码。我有一个 updateBall 函数,它每 100 毫秒运行一次以更新球的位置。

计算到达给定目标坐标所需时间(以毫秒为单位)的公式如何计算?例如,给定目标 x=100 y=200 达到目标所需的时间约为 5300 毫秒。

下面是相关的代码片段,

        function calcDirection(a, b, c, d)
        { return 180 * Math.atan2(d - b, c - a) / Math.PI };

        let ball = {x: 0, y: 0} 

        let targetX = 100;
        let targetY = 200;

        let velocity = 0.05;
        let friction = 0.0003;

        let direction = calcDirection(ball.x,ball.y,targetX,targetY); //63.43494882292201

        let dx = targetX - ball.x;
        let dy = targetY - ball.y;
        let distance = Math.sqrt(dx*dx + dy*dy); //223.60679774997897

        // runs every 100ms
        function updateBall(){
            if (velocity > 0) {
                let pixelsPerLoop = velocity * 100;
                
                ball.x += pixelsPerLoop * Math.cos(Math.PI/180 * direction);
                ball.y += pixelsPerLoop * Math.sin(Math.PI/180 * direction);
                velocity -= friction; 
            }
        }

    //answer: ( v0 (+/-) sqrt( v0^2 - 2.0*friction*dist ) )/(friction)
    let v0 = velocity * 100;
    let fric = friction * 100;
    let p = Math.pow(v0, 2);
    let q = 2.0 * fric * distance;
    let r = p - q;
    let s = Math.sqrt(r);
    let t = ( v0 - s )/(fric);

    // test run for loop times
    let loop = Math.floor(t);
    for (let i = 0; i < loop; i++)
        updateBall();
            
        document.getElementById('result').innerHTML = 'loop ' + loop + ', ball.x = ' + ball.x + ' ball.y = ' + ball.y; 
<p id="result"></p>

我的数学有点生疏,所以如果我没记错的话应该是这样的:

v(t) = v0 - friction*t // speed
s(t)  = Integral(v(t))  // position or signed traveled distance if start position is zero
-------------------------------
s(t)  = v0*t - 0.5*friction*t^2 // s(t) = dist (distance to target)
dist  = v0*t - 0.5*friction*t^2
0.5*friction*t^2 - v0*t  + dist = 0
-----------------------------------
t = ( v0 (+/-) sqrt( v0^2 - 2.0*friction*dist ) )/(friction)

其中 t 是时间,dist 是从起点到目标的距离。

所以你得到了 t 的 2 个解决方案,所以使用一个有意义的(非负面的)。如果没有这样的一个,就意味着你的球永远不会到达你的目标。

顺便说一句,一旦你想添加重力和其他力场或障碍物,那么你应该将 math/physics 更改为 Newton D'Alembert integration 而不是使用方向向量将你的问题转换为一维相当有限。

[编辑2]

不要忘记使用兼容的单位,因为您使用 0.1 秒的更新间隔,并且您将速度乘以 100,所以:

friction = 0.0003/0.1 = 0.003 m/s^2
v0 = 0.05*100/0.1         = 50.0 m/s
dist = sqrt(100^2 + 200^2) = 223.6068 m

t = ( v0 (+/-) sqrt( v0^2 - 2.0*friction*dist ) )/(friction)
t = ( 50 (+/-) sqrt( 2500 - 2.0*0.003*223.6068 ) )/(0.003)
t = ( 50 (+/-) sqrt( 2500 - 1.3416408 ) )/(0.003)
t = ( 50 (+/-) sqrt( 2498.6583592 ) )/(0.003)
t = ( 50 (+/-) 49.9566 )/(0.003)
t1 = 33328.8603075022
t2 = 4.47273608634165

因此您在 4.47 秒内达到了目标...这里是移植到 C++ 的模拟值:

t     v       x       y
0.0   5.000   2.236   4.472
0.1   4.999   4.472   8.944
0.2   4.999   6.708  13.416
0.3   4.999   8.943  17.887
0.4   4.999  11.179  22.358
0.5   4.998  13.414  26.829
0.6   4.998  15.650  31.299
0.7   4.998  17.885  35.770
0.8   4.997  20.120  40.240
0.9   4.997  22.355  44.709
1.0   4.997  24.589  49.179
1.1   4.996  26.824  53.648
1.2   4.996  29.058  58.117
1.3   4.996  31.293  62.585
1.4   4.996  33.527  67.054
1.5   4.995  35.761  71.522
1.6   4.995  37.995  75.990
1.7   4.995  40.229  80.457
1.8   4.994  42.462  84.925
1.9   4.994  44.696  89.392
2.0   4.994  46.929  93.859
2.1   4.993  49.163  98.325
2.2   4.993  51.396 102.791
2.3   4.993  53.629 107.257
2.4   4.993  55.861 111.723
2.5   4.992  58.094 116.188
2.6   4.992  60.327 120.654
2.7   4.992  62.559 125.118
2.8   4.991  64.792 129.583
2.9   4.991  67.024 134.047
3.0   4.991  69.256 138.511
3.1   4.990  71.488 142.975
3.2   4.990  73.719 147.439
3.3   4.990  75.951 151.902
3.4   4.990  78.183 156.365
3.5   4.989  80.414 160.828
3.6   4.989  82.645 165.290
3.7   4.989  84.876 169.753
3.8   4.988  87.107 174.215
3.9   4.988  89.338 178.676
4.0   4.988  91.569 183.138
4.1   4.987  93.799 187.599
4.2   4.987  96.030 192.060
4.3   4.987  98.260 196.520
4.4   4.987 100.490 200.981

正如您所看到的,您的模拟在 4.5 秒之前就达到了目标,但是您的 5.3 秒结果太远了,因此仍然存在可疑之处。

此外,真实摩擦的行为也不同,它会按比例增加实际速度,因此它会像这样应用:

v *= 1.0-friction*dt*v^2;

其中 dt 是您使用 dt=0.1 更新的间隔,但是上面的等式将不再有效,因为它也改变了 v(t) 函数。