Jump to content
  • Advertisement
taby

SUVAT problem

Recommended Posts

I'm trying to solve for the SUVAT equations. What is known is the start position and end position. The initial velocity is what I'm trying to solve for. Can anyone please help me with this problem? I don't know why I'm having so much trouble with such a simple thing.

Share this post


Link to post
Share on other sites
Advertisement

No. I'm doing an open-source tennis trajectory finder, and I have it working with RK4 integration, but there are some cases where a lob is required, and the easiest way to do that is by using a parabola. I realize that the SUVAT equations don't include wind, drag, or the Magnus effect, but I'm still interested in knowing how to get the initial velocity.

Share this post


Link to post
Share on other sites

Fair enough :)

 

In your scenario (assuming constant acceleration = gravity), you will have to constrain it more somehow. There's an infinite amount of solutions, depending on the angle of the velocity.

Just imagine holding a ball, and wanting it to land 1m beneath its starting point. You can either drop it (0 initial velocity), or throw it directly up or down at any velocity (less than escape velocity), and it will eventually hit its target, although at different times.

 

I would suggest trying to constrain it either by angle, or by max height of the parabola. Once you have y displacement, you can calculate time needed for gravity to pull the ball to target level, to get your required time.

Using time, you can then solve for initial velocity.

Share this post


Link to post
Share on other sites

I would like to constrain the initial direction, with only the speed to be variable. I was wondering if you had any code? I learn from code way faster than from English.

In any case, thank you for your posts. :)

Share this post


Link to post
Share on other sites

OK so I got a bit further.

I have the equation final_velocity = sqrt(initial_velocity^2 + 2*acceleration*displacement), which I solve for each of the three dimensions.

However, I have the equation t = 2*displacement / (initial_velocity + final_velocity). How do I solve for that when t is a scalar and displacement, initial_velocity, and final_velocity are vectors? Like I said, I'm stuck on something simple here, but I just can't figure it out.

Share this post


Link to post
Share on other sites
Posted (edited)

Now that I think of it, t = (v - u) / (2*a) is only valid for the y dimension, because the acceleration along the x and z dimensions is zero. Am I progressing?

Edited by taby

Share this post


Link to post
Share on other sites
Posted (edited)

I figured it out! It's unsatisfactory however, since it doesn't support wind, drag, or the Magnus effect -- for instance, the red path travels further into the opponent's side of the court because it is not affected by drag.

custom_math::vector_3 V(1, 1, 0);
V.normalize();
V *= out_server_vel.length();

custom_math::vector_3 V_norm = V;
V_norm.normalize();
custom_math::vector_3 basis(1, 0, 0);
float v0 = V.length();
float launch_angle = acos(V_norm.dot(basis));
float a = g / 2;
float b = v0 * sin(launch_angle);
float c = in_server_pos.y;
float t2 = (-b + sqrt(b*b - 4.0 * a*c)) / (2.0 * a);
float t3 = (-b - sqrt(b*b - 4.0 * a*c)) / (2.0 * a);
cout << t2 << endl;
cout << t3 << endl;
float pi = 4.0 *atan(1.0);

for (double i = 0; i <= t3; i += 0.01)
{
	custom_math::vector_3 s = in_server_pos + V * i + 0.5*g*i*i;
	parabola.push_back(s);
}

for (size_t i = 0; i < parabola.size(); i++)
{
	parabola[i].rotate_z(pi / 2.0);
}
	
custom_math::vector_3 end_position = parabola[parabola.size() - 1];
custom_math::vector_3 v1 = in_out_target_pos - in_server_pos;
v1.y = 0;
custom_math::vector_3 v2 = end_position - in_server_pos;
v2.y = 0;
v1.normalize();
v2.normalize();
double angle = acos(v1.dot(v2));

for (size_t i = 0; i < parabola.size(); i++)
{
	parabola[i].rotate_y(angle);
}
	
custom_math::vector_3 d = parabola[0] - in_server_pos;

for (size_t i = 0; i < parabola.size(); i++)
	parabola[i] = parabola[i] - d;
	 
	

court.png

Edited by taby

Share this post


Link to post
Share on other sites

This might be beyond your powers at this point, but there is a general solution that would work with all the complexity of a more complete Physics simulation. Start with a quick-and-dirty approximate solution (what you did above is probably fine). If you can quickly compute the trajectory going forward with the more complete Physics model, you can define a differentiable measure of error (e.g., the square of the distance between the landing point and the target) and use backpropagation (a.k.a. "reverse-mode automatic differentiation") to compute the gradient of the error with respect to whatever parameters you are trying to solve for. You can then use gradient descent to refine your solution.

This may or may not be too much work for what you are trying to do, but I think it would work.

Share this post


Link to post
Share on other sites
Posted (edited)

I do calculate a slope of sorts, and use it to hone the server velocity so that the ball lands at the target point, using RK4 and symplectic4, etc.

The code is small, and reasonably fast (like, 2400 frames per second in C++). It's also due for replacement because it doesn't really take the input server velocity length into account. In the next version, which will be closed-source at first, will be better. :)

In any case, the code (my dog's breakfast) is something else, but is it gradient descent?

for (size_t i = 0; i < num_length_adjustment_iterations; i++)
{
    // adjust velocity length to get closer to the target position
    custom_math::vector_3 begin_pos = p[0];
    custom_math::vector_3 end_pos = p[p.size() - 1];
    custom_math::vector_3 diff_a = end_pos - begin_pos;
    custom_math::vector_3 diff_b = target_position - begin_pos;
    double len_a = diff_a.length();
    double len_b = diff_b.length();
    double slope = len_a / len_b;
    server_velocity /= slope;
	
    // refresh path using new input server velocity
    get_path(p,
        server_position,
        server_velocity,
        server_angular_velocity,
        target_position,
        0);
}

// rotate vectors on y axis to get closer to the target position
custom_math::vector_3 end_position = p[p.size() - 1];
custom_math::vector_3 v1 = server_position - target_position;
custom_math::vector_3 v2 = server_position - end_position;
v1.normalize();
v2.normalize();

double angle = acos(v1.dot(v2));

server_velocity.rotate_y(-angle);

// refresh path
get_path(p,
	server_position,
	server_velocity,
	server_angular_velocity,
	target_position,
	0);
Edited by taby

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!