2

I am trying to simulate javelin throw on android. I calculate slope of tangent line in every point of javelin trajectory. To calculate trajectory coordinates I am using Projectile motion equations

x = (int) (x0 + v0 * t * Math.cos(radians));    //for coordinate x 

and

y = (int) (y0 - v0 * t * Math.sin(radians) + 0.5 * g * t * t);

To calculate slope of tangent line to javelin trajectory I derivated this equation with respect to x:

y = Math.tan(radians) * x - g / (2 * Math.pow(v0, 2) * Math.pow(Math.cos(radians), 2)) * x^2
dy = Math.tan(radians) - (g * x) / (Math.pow(v0, 2) * Math.pow(Math.cos(radians), 2))

Problem is, that it works correctly with elevation angle < than approximately 60 degrees. If elevation angle is bigger, it doesn't calculate correct slope.

Here is the code:

public class ThrowJavelin extends ImageView {
    private Context mContext;
    int x0 = -1;
    int y0 = -1;
    int x = x0;
    int y = y0;
    private Handler h;
    private final int FRAME_RATE = 5;
    private double t = 0;
    private float g = 9.81f;
    //initial velocity
    private int v0;
    //elevation angle in radians
    private double radians;
    //javelin current angle in degrees
    private double javelin_angle;



    public ThrowJavelin(Context context, AttributeSet attr)  { super(context, attr); }
    public ThrowJavelin(Context context, AttributeSet attrs, int defStyleAttr){ super(context, attrs, defStyleAttr); }

    public ThrowJavelin(Context context, Bundle args)  {
        super(context);
        mContext = context;
        h = new Handler();
        //input values
        v0 = args.getInt("velocity");
        radians = args.getDouble("radians");
   }

    private Runnable r = new Runnable() {
        @Override
        public void run() {
            invalidate();
        }
    };

    protected void onDraw(Canvas c) {

        Bitmap javelin = BitmapFactory.decodeResource(getResources(), R.drawable.jav);
        DerivativeStructure alpha = null;
        if (x < 0 && y < 0) {
            x0 = 0;
            y0 = c.getHeight() - 200;
            x = x0;
            y = y0;
            javelin = rotateBitmap(javelin, (float) Math.toDegrees(radians));
        } else if (y > y0) { //reset to beginning
            x = x0;
            y = y0;
            t = 0;
            javelin = rotateBitmap(javelin, (float) Math.toDegrees(radians));
        } else {
            //calculate current coordinates (depends on t)
            x = (int) (x0 + v0 * t * Math.cos(radians));
            y = (int) (y0 - v0 * t * Math.sin(radians) + 0.5 * g * t * t);

            if (x == 0) {
                javelin_angle = Math.toDegrees(radians);
            } else {
                // dy of 3rd equation 
                javelin_angle = Math.toDegrees(Math.tan(radians) - (g * x) / (Math.pow(v0, 2) * Math.pow(Math.cos(radians), 2)));
            }
            javelin = rotateBitmap(javelin, javelin_angle);
            t += 0.3;
        }
        c.drawBitmap(javelin, x, y, null);

        h.postDelayed(r, FRAME_RATE);

    }



    public Bitmap rotateBitmap(Bitmap image, double angle){
        float alpha = (float) angle;

        Matrix mat = new Matrix();
        System.out.println(-alpha);
        mat.postRotate(-alpha);
       return Bitmap.createBitmap(image, 0, 0, image.getWidth(), image.getHeight(), mat, true);
    }
}

I really don't understand, why ot doesn't work correctly for bigger angles. Any ideas please?

  • What is this second equation supposed to be? The derivative of `y` with respect to `t` is `dy = g * t - v0 * Math.sin(radians)`. The resulting angle is `tan(dy)`. – Nico Schertler Sep 27 '16 at 13:15
  • @NicoSchertler Hi Nico, second equation is supposed to calculate y coordinate with respect to time t. What I need is to calculate derevative of 3rd equation, which represents trajectory of my javelin with respect to coordinate x . By the way I don't know why I am using DerivativeStructure when I can use directly `javelin_angle = Math.toDegrees(Math.tan(radians) - (g * x) / (Math.pow(v0, 2) * Math.pow(Math.cos(radians), 2)));` But situation is the same and and everything works correctly only while elevation angle is lower than 65 degrees –  Sep 27 '16 at 20:48

1 Answers1

0

Firstly, your solution for y(x) seems to drop a few variables (e.g. x0). Here is the full solution:

y(x) = y0 + (0.5 * g * (x - x0)^2)/(v0^2 * cos(radians)^2) - (x - x0) * tan(radians)

The derivative with respect to x is:

dy/dx = (g * (x - x0)) / (v0^2 * cos^2(radians)) - tan(radians)

Your solution looks very similar except that its y-axis is inverted and it misses the initial positions.

The angle that corresponds to this derivative is its arctangens:

double c = Math.cos(radians);
javelin_angle = Math.toDegrees(Math.atan((g * (x - x0) / (v0 * v0 * c * c) - Math.tan(radians)));

I assume, there was a reason why you swapped the y-axis. So you may do that again in this formula.

The reason why your formula worked for small angles is that the arctangens is close to the identity for small angles (identity in red, arctangens in blue):

Arctangens

Nico Schertler
  • 32,049
  • 4
  • 39
  • 70
  • Thanks! It works perfectly now. I also needed to change `mat.postRotate(-alpha);' to positive value 'mat.postRotate(alpha);'. Thanks for your explanation. –  Sep 28 '16 at 10:30