Calculation of elevation: differential equations method

Added by q1184 almost 6 years ago

Looking for a versatile way of finding the needed elevation to hit the target that would not require pre-tabulated range-elevation data, I came up with this method. It integrates the system of differential equations of motion used by the game to simulate the projectile, and does it within one frame. It does accumulate error with time, but I found its performance more than satisfactory when used with tank cannons at distances up to 5 km, as well as helicopter cannons. Slower ammunition and higher distances generate a noticeable error. The script is meant to work with a laser rangefinder script, taking distance to target and relative target elevation from it (could be altered to take vector to target instead, doesn't really matter). I'm not sure I will be able to continue with this project, so I'm posting it here in case someone becomes interested.

// Finds the angle (elevation) needed to hit a target with the given type of ammo
// Takes airfriction, muzzle velocity, distance to target and its relative height
// Returns elevation (degrees) and time of flight (seconds)

// Calculates within one frame, so might lead to slowdowns if time of flight is high
// Accumulates an error over time
// (not recommended to use for slow ammo/high distances)
// System of coordinates used: X is horizontal line passing through shooter and target, Y is vertical. Center
// of coordinates is at shooter's position.
// Recommended timestep (dt) 0.001
// Needs a better protection against invalid initial conditions (ie ammo too slow/high drag to reach the target).
// Currently uses velocity check (if drops below 50, aborts)

// by q1184

private ["_it","_t","_x","_y","_dist","_mv","_dt","_vx","_vy","_v","_yfinal","_xfinal","_af","_g","_elev"];

_af = _this select 0;         // airfriction
_mv = _this select 1;        // muzzle velocity
_dist = _this select 2;        // distance to target
_yfinal = _this select 3;    // vertical coordinate of the target relative to the gun
_dt = _this select 4;        // integration step, seconds

_xfinal = sqrt (_dist^2 - _yfinal^2);     // horizontal distance to target
_it = 0;                    // number of iterations
_elev = 0;                // resulting elevation needed to hit the target
_angle = 0;
_los = _yfinal atan2 _xfinal;        // angle to target

// ** initial conditions ** //
_x = 0;
_y = 0;
_vx = _mv*cos (_los);
_vy = _mv*sin (_los);
_t = 0;
_v = _mv;
_g = 9.8;

// ** trajectory equations ** //
while {_x <= _xfinal && _vx > 50} do
    _t = _t + _dt;
    _vx = _vx + _af*_vx*_v*_dt;
    _vy = _vy + (_af*_vy*_v - _g)*_dt;
    _v = [_vx,_vy,0] distance [0,0,0];
    _x = _x + _vx*_dt;
    _y = _y + _vy*_dt;
    _it = _it + 1;

_cos = (_xfinal*_x + _y*_yfinal)/sqrt((_xfinal^2 + _yfinal^2)*(_x^2 + _y^2));
_elev = acos _cos;
hint format ["iterations %1 angle %2 ",_it, _elev];