Home   Help Search Login Register  

Author Topic: More Math Woes  (Read 8785 times)

0 Members and 1 Guest are viewing this topic.

Offline drbobcat

  • Members
  • *
  • Rawr
Re: More Math Woes
« Reply #45 on: 24 Jun 2008, 13:49:38 »
Why would I have to guide the shell entirely to its destination when I could simply give it a higher initial velocity? The drag coefficient could remain the same regardless of which propellant I am wanting to simulate:

Charge 7 - initial velocity 'x' so that the shell travels roughly 11,400 meters
Charge 8 - initial velocity 'y' zo that the shell travels roughly 14,000 meters
Et cetera, et cetera...

As we already have found out, even a 0.005 (roughly the point at which an ArmA sqf can just barely complete math equations) loop is not fast enough to lead the shell to where it needs to be. However, changing the initial velocity is quite easy.

- dRb

Offline Mandoble

  • Former Staff
  • ****
    • Grunt ONE and MandoMissile suite
Re: More Math Woes
« Reply #46 on: 24 Jun 2008, 13:56:44 »
Well, if you plan to adjust initial velocity based on range to be reached, then certainly you dont need anything else.

Offline Mr.Peanut

  • Former Staff
  • ****
  • urp!
Re: More Math Woes
« Reply #47 on: 24 Jun 2008, 15:59:35 »
drb-cat,
I have misunderstood your requirements. All you need is the script traj.sqf. Just stuff in the initial velocity you want to use and you will get the shell range including all terrain effects. You don't need anything else. I didn't realize that you were going to twiddle with the shell's initial velocity. I was assuming the initial velocity was to be the config value. You will want to use a function in your fired eventhandler to make sure the shell is reassigned a velocity immediately.
« Last Edit: 24 Jun 2008, 16:03:36 by Mr.Peanut »
urp!

Offline drbobcat

  • Members
  • *
  • Rawr
Re: More Math Woes
« Reply #48 on: 24 Jun 2008, 22:14:31 »
The only reason why I wanted to get the velocity of the round from the config is for when the mission editor wishes to use addons that may already be utilizing accurate velocities. Also, it makes testing far easier as we were dealing solely with data ArmA gave us. I swayed from many of my initial plans because of their complexity and just because I knew determining the range would be more simple than obtaining the required angle of launch. Anyway, when I return from the errands I must perform today, I will study more closely Mr.Peanut's traj.sqf and try once more inputting everything that must be put in. I'll return here with the complete script in case I do not have any additional questions. *crosses fingers*

Thank you,
-dRb

Offline Mr.Peanut

  • Former Staff
  • ****
  • urp!
Re: More Math Woes
« Reply #49 on: 25 Jun 2008, 14:51:35 »
Here is the trajectory function with a minor bug fix, and a commented example of calling it.

Example
Code: [Select]
//Example of calling trajectory script. In this case for M119. I know a priori that the drag coefficient is 4.5e-4
//so I will not bother pulling it from config
_muzzleOffset = 1.0; // height from ground to axis about which barrel rotates. My estimate for M119.
_muzzleLength = 2.0; // length of barrel from axis about which barrel rotates to the muzzle mouth.  My estimate for M119.
_pos = getPosASL _gun;
_vectorDir = _gun weaponDirection _muzzle;
_elev = 90 - acos ((_vectorDir select 2) /
      sqrt ((_vectorDir select 0)^2 + (_vectorDir select 1)^2 + (_vectorDir select 2)^2));//barrel elevation i.e. angle
                                                                                                                      // between horizontal and barrel
_x = _pos select 0;
_y = _pos select 1;
_theta = (360 + (_vectorDir select 0) atan2 (_vectorDir select 1)) mod 360; // compass heading of your barrel
//get ASL pos of muzzle mouth
_x = _x + _muzzleLength * (cos _elev) * (sin _theta);
_y = _y + _muzzleLength * (cos _elev) * (cos _theta);
_z = _muzzleOffset + (_pos select 2) + _muzzleLength * sin _elev; // ASL height of muzzle
//other parameters
_initSpeed = whatever you want; //M119 config value is 1100 m/s.
_drag = 4.5e-4; // drag for M119 shell
_dt = 0.005; // time increment for calculation. Smaller is more accurate but takes longer to calculate.
_maxRange = 5000; //distance at which to stop bothering with calculation.

//call function. takes about 1 second.
_return = [[_x,_y,_z], _vectorDir, _initSpeed, _drag, _maxRange, _dt] call smb_trajectory ;
_npos = _return select 0; // Final position of shell.
_elapsed = _return select 1; // Flight time
_d = _return select 2; // Straight line distance to target.

Trajectory function
Code: [Select]
private ["_pos", "_vectorDir", "_vm", "_k", "_max", "_dt", "_gl_start","_gl","_posASL", "_x", "_y", "_z",
         "_u", "_v", "_w", "_zASL_Land", "_lastPos", "_vel", "_d", "_elapsed"];
_pos = _this select 0;
_vectorDir = _this select 1;
_vm = _this select 2;
_k = _this select 3;
_max = _this select 4;
_dt = _this select 5;
_gl_start = "logic" createVehicleLocal [0,0,0];
_gl = "logic" createVehicleLocal [0,0,0];
_gl_start setPosASL _pos;
_x = _pos select 0;
_y = _pos select 1;
_z = _pos select 2;
_u = _vm * (_vectorDir select 0);
_v = _vm * (_vectorDir select 1);
_w = _vm * (_vectorDir select 2);
_gl_start setPosASL [_x, _y, _z];
_zASL_Land = -666;
_d = -666;
_lastPos =[];
_elapsed = 0;

while {_z > _zASL_Land and _d < _max} do
{
   _lastPos = getPos _gl;
   _vel = sqrt(_u*_u + _v*_v +_w*_w);
   _u = _u - _k *_u*_vel*_dt;
   _v = _v - _k *_v*_vel*_dt;
   _w = _w - (_k *_w*_vel + 9.8)*_dt;
   _x = _x + _u*_dt;
   _y = _y + _v*_dt;
   _z = _z + _w*_dt;
   _gl setPos [_x, _y, 0];
   _d = _gl_start distance _gl;
   _zASL_Land = (getPosASL _gl) select 2;
   _elapsed = _elapsed + _dt;
   //hint format ["%1 %2 %3\n%4 %5 %6\n%7 %8",_x,_y,_z,_u,_v,_w,_d,_zASL_Land];
//   sleep 0.5;
};
deleteVehicle _gl;
deleteVehicle _gl_start;
if (_d >= _max) then
{
   [nil, _elapsed, _d]
}
else
{
   [_lastPos, _elapsed, _d]
};

I have used the most primitive means of integrating the trajectory. I also tried a "leap-frog" type scheme similar to RK2(Runge-Kutta 2), but it did not seem to make much difference. I am presently trying a modified RK4 to see if I can keep the same accuracy but increase the function speed. If you can not stand the hiccup that the function causes, test to see if adding a small sleep in the main loop improves things. I can not remember the status of the sleep command in functions. You could also rewrite the function as a script.
« Last Edit: 25 Jun 2008, 15:01:31 by Mr.Peanut »
urp!

Offline The_Mark

  • Members
  • *
Re: More Math Woes
« Reply #50 on: 25 Jun 2008, 16:13:59 »
I think in OFP you couldn't sleep functions, dunno how it applies to ArmA.

But, well, crud. My internet dies for a week and I miss all the fun :(.
Silent enim leges inter arma.

Offline Mr.Peanut

  • Former Staff
  • ****
  • urp!
Re: More Math Woes
« Reply #51 on: 25 Jun 2008, 16:51:55 »
The fun is not over yet!  :P  Although drbob does not require it, I am still plugging away at improving the numerical solver for elevation. The biggest computational demand is the trajectory integration, but reducing the number of iterations to solve for elevation is critical. It is a little confusing, because the trajectory is an initial value problem, but when you take the target into consideration, it bcomes a boundary value problem albeit but one for which the derivatives are only know at t=0.

My first stab involved taking the error in distance and solving for the root using Newton-Raphson. However, the solution does not always converge nicely and I had to scale down the derivative to prevent angles greater than 90 or less than -90 which rapidly blow up.  Right now I am usually getting convergence in 10-20 iterations, which is not bad, but I think it should converge faster. The advantage of this method is that I can easily specify to search for either the  low or high solution without having to provide bounds.

My second attempt is using RK4 for the trajectory integration. I am hoping that I will be able to increase the integration time step, but I do not know offhand how much performance gain I might get. My bastardised RK2 did not make a significant difference much to my dismay. I will then solve for elevation by searching for a minimum, probably using Brent's method, transliterated from Numerical Recipes (not robust but what the hell. free source code if you know F77).

If you have the time to perform a few quick tests in Mathematica to see if any performance can be gained by these methods, that would be great.

edit: tested RK4 integration in Matlab. It can have a timestep 50 times larger and still work!

edit2: okay. the fun is over now. :shhh: Solving for elevation can be approached as either solving a root, or finding the minimum of a function in a given range of angles. Finding the minimum takes on average 30 calls to the integration function. Solving for the root takes 80. However, finding the minimum requires the user to specify an elevation range, which is problematic.
« Last Edit: 25 Jun 2008, 20:22:52 by Mr.Peanut »
urp!

Offline drbobcat

  • Members
  • *
  • Rawr
Re: More Math Woes
« Reply #52 on: 26 Jun 2008, 00:01:01 »
Well, I have finished testing out a slightly modified version of Mr.Peanut's trajectory function...

Code: [Select]
_gun = _this select 0;
_gType = format ["%1",(typeOf _gun)];
_wep = (getArray (configFile >> "cfgVehicles" >> _gType >> "turrets" >> "mainTurret" >> "weapons")) select 0;
_mag = (getArray (configFile >> "cfgWeapons" >> _wep >> "magazines")) select 0;
_ammo = getText (configFile >> "cfgMagazines" >> _mag >> "ammo");
_gPos = [getPosASL _gun select 0, getPosASL _gun select 1, 0];
_wVec = _gun weaponDirection _wep;
_drag = abs (getNumber (configFile >> "cfgAmmo" >> _ammo >> "airFriction"));
_xPos = (getPosASL _gun) select 0;
_yPos = (getPosASL _gun) select 1;
_zPos = ((getPosASL _gun) select 2) + 3;
_mVel = getNumber (configFile >> "cfgMagazines" >> _mag >> "initSpeed");
_xVel = _mVel * (_wVec select 0);
_yVel = _mVel * (_wVec select 1);
_zVel = _mVel * (_wVec select 2);
_tVel = 0;
_dist = 0;
_time = 0;
_zCheck = 0;
_rPos = [];

_rLogic = "logic" createVehicleLocal [0,0,0];

while {(_zPos > _zCheck)} do
{
_rPos = getPos _rLogic;
_tVel = sqrt ((_xVel ^ 2) + (_yVel ^ 2) + (_zVel ^ 2));
  _xVel = _xVel - _drag *_xVel*_tVel*0.005;
    _yVel = _yVel - _drag *_yVel*_tVel*0.005;
    _zVel = _zVel - (_drag *_zVel*_tVel + 9.8)*0.005;
    _xPos = _xPos + _xVel*0.005;
    _yPos = _yPos + _yVel*0.005;
    _zPos = _zPos + _zVel*0.005;   
    _rLogic setPos [_xPos, _yPos, 0];
_dist = _gPos distance [getPos _rLogic select 0, getPos _rLogic select 1, 0];
_zCheck = (getPosASL _rLogic) select 2;
    _time = _time + 0.005;
};

"tMark" setMarkerPos [_rPos select 0,_rPos select 1,0];
deleteVehicle _rLogic;
titleText [(format ["%1 meters\n%2 seconds", _dist, _time]),"plain down"];

... I have come to the conclusion that finding the required launch angle may not be so bad an idea after all. Sure, the current method is fairly quick and accurate, but because it must be ran multiple times as the gunner adjusts his aim, it becomes tiresome having to press the action button over and over again.  Additionally, it is far too demanding on performance to call constantly within even a 0.5 seconds loop.  An elevation function, conversely, would only need to be executed one time for the current target and propellant in use. I understand it is more challenging to determine, but we can at least ignore the terrain along the way now. Instead, why don't we just return the two angles for the given target, let him scan over the map, and decide whether to take the high one or the low. *rubs chin* In all honesty, it is up to you at this point, Mr.Peanut. Because your mathematical abilities far surpass my own, it is not much of my position to decide whether one idea is more practical than another.

- dRb
« Last Edit: 26 Jun 2008, 01:42:18 by drbobcat »

Offline Mr.Peanut

  • Former Staff
  • ****
  • urp!
Re: More Math Woes
« Reply #53 on: 26 Jun 2008, 13:47:24 »
Yes. That is what I thought you wanted.

Now here is the odd part. My last attempt for "improvements" fared worse than my previous version even though I tested it rigorously in Matlab before implementing. Very strange. In particular it is terrible for low elevations. It keeps bouncing around the solution but will not converge. At this point I am a bit perplexed and wonder if I might be running into precision problems with ArmA's 4 byte reals. I'll be off for an extra long weekend (Canada Day) so it is unlikely I'll have anything to post until late next week. If I have a chance I'll post a demo of the code so far, in all it's ugly glory, when I get home tonight.

EDIT: Okay here is the previous version before my last round of attempted "improvements". No error handling and code is a hard coded mess. This is more of a proof of concept. Arty angles constantly displayed in hint. Use actions to select a Low or High elevation angle search. Final answer is displayed as titletext: theta, elevation +/- error, distance from target, flight time
It is hard-coded to find an angle that will deliver the M119 shell within 2m of target, without displaying whether the shot is blocked by topography(which it can do but is not implemented). If the shot is impossible, the script fails with an error. The shot will fail if the target is not within range of the M119.

Your target is a fuel truck. I've put it in an interesting place that yields both a high and low elevation solution, but try moving it around in the map. When the truck takes damage a hint displays very briefly before being overwritten.

You will need to crank your mouse sensitivity down to zero to get the angles close enough to hit the target.

« Last Edit: 27 Jun 2008, 18:51:38 by Mr.Peanut »
urp!