-1

I am coding a simulation of ball movement. I have an updateBall function which runs every 100 miliseconds to update the location of the ball.

How is the formula to find out the time in miliseconds needed to reach a given target coordinate? For example, given target x=100 y=200 the time needed to reach is approximately 5300ms.

Below is the relevant code snippet,

        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>
Eddi
  • 479
  • 5
  • 22
  • That's a physics questions and therefor off-topic for SO. – Andreas Sep 24 '21 at 14:54
  • By running your code it looks like the `updateBall()` will run 167 times before velocity drops below 0. This will take 16.7s if you call `updateBall()` every 100ms. During this time the ball (x,y) updates to (1.87, 3.75) which is nowhere near your target. It looks like your ball never gets there... – Hitesh Lala Sep 24 '21 at 15:09
  • @HiteshLala Yes you are right, i have corrected the code now and changed to code snippet. Please have a look again, thanks! – Eddi Sep 25 '21 at 02:29
  • @Andreas How so? It's math and physics applied in a programming context. – Eddi Sep 25 '21 at 02:32
  • 1
    If you have a given formula and your actual implementation in a particular language fails with an error or yields a wrong result, then yes. But a general physics problem is nothing that is specific to programming. Just because you then try to implement it in a programming language of your choice doesn't make it less Off-topic -> [What topics can I ask about here?](https://stackoverflow.com/help/on-topic) – Andreas Sep 25 '21 at 08:41

1 Answers1

1

My math is a bit rusty so if I am not mistaken it should be like this:

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)

where t is time and dist is the distance from start to target.

so you got 2 solutions for t so use the one that makes sense (non negative). If there is no such one it means your ball never gets to your target.

Btw once you want to add stuff like gravity and other force fields or obstacles then you should change your math/physics to Newton D'Alembert integration instead of using direction vector to convert your problem to 1D as that is rather limiting.

[Edit2]

Do not forget to use compatible units as you use 0.1 sec interval for update and also you multiply speed by 100 so:

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

so you reach the target in 4.47 sec ... Here values of your simulation ported to 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

As you can see your simulation reaches the target slightly before 4.5 sec However yours 5.3 sec result is way too far off so there still must be something fishy.

Also Real friction behaves differently and it scales up actual speed instead so it would by applied like this:

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

where dt is the interval you update with so dt=0.1 however then the above equations will no longer work as it changes the v(t) function too.

Spektre
  • 49,595
  • 11
  • 110
  • 380
  • Thanks for the answer. v0^2 means initial velocity to the power of 2 correct? So v0 = 0.05, Math.pow(v0, 2) returns 0.0025000000000000005. 2.0 * friction * distance = 2.0 * 0.0003 * 223.60679774997897 = 0.13416407864998736. (v0^2 - 2.0*friction*dist) = 0.0025000000000000005 - 0.13416407864998736 = -0.13166407864998736. Next is sqrt(-0.13166407864998736) and that seems wrong? – Eddi Sep 25 '21 at 11:43
  • @Eddi yes `x^2` means `x*x`... I added edit1 with some details as you did not use correct values... negative value inside sqrt just means: the friction is too big or initial velocity is too small or distance to target is too big or any combination of that ... so the object stops (or in your case even reverse as its not computed in physically correct manner) before it reaches target destination ... – Spektre Sep 25 '21 at 12:32
  • Thanks for edit1. In my code snippet above and my actual code the ball did reached the target location after looped 53 times or 5300 miliseconds. So a correct formula should produce the same result 5300? – Eddi Sep 25 '21 at 13:03
  • @Eddi you are multiplying speed by 100 inside update so you have to use `v0=50` then the result is `t = 4.47273608634165 sec` which complies with my C++ port of your simulation .. however your snipped return 5.3 sec that is weird I added edit with updated numbers – Spektre Sep 25 '21 at 13:55
  • Comparing your c++ values with my code snippet, my code at second loop which is at t0.1 v is 0.0497 where velocity -= friction (velocity = 0.05 - 0.0003 = 0.0497). While your c++ values at t0.1 v is 4.999, shouldn't it be 4.997? – Eddi Sep 25 '21 at 14:26
  • @Eddi no as `0.05*100 - 0.0003 = 4.9997` ... you still forgetting that you are multiplying speed by 100 as you got `let pixelsPerLoop = velocity * 100;` but not the `friction` ... pixel scaling is usually used on final position result to avoid this kind of confusions – Spektre Sep 25 '21 at 15:39
  • Sorry i don't understand. Your values when t=0.1 v=4.999, so v=5-0.001 friction? How does 0.001 friction value comes from? Friction in my code is 0.0003 and if multiply by 100 it'll be 0.003 – Eddi Sep 25 '21 at 16:12
  • @Eddi that is 4.999 is 5 just a slightly off due to FPU rounding, you multiply velocity by 100 but not the friction so 0.0003 is still the same – Spektre Sep 25 '21 at 16:16
  • Ok so, t0.1, 5 - 0.0003 = 4.9997 rounded to 4.999 t0.2, 4.9997 - 0.0003 = 4.9994 rounded to 4.999 t0.3, 4.9994 - 0.0003 = 4.9991 rounded to 4.999 t0.4, 4.9991 - 0.0003 = 4.9988 rounded to 4.998 But in your values at t0.4 v is 4.999? Shouldn't it be 4.998? – Eddi Sep 25 '21 at 16:48
  • Yes finally got it right, your answer is correct i just need to multiply both velocity and friction with 100. Thanks so much! – Eddi Sep 26 '21 at 09:30