Jump to content

Recommended Posts

Hello, I recently made an Iron Dome mod: Steam workshop link

I am also releasing a standalone script used for guiding the missile, currently, 3 modes are available:

  • Augmented proportional navigation APN
  • Proportional navigation PN
  • Pure pursuit LOS

 

Here is the code:

You can call this function (script) by using:

[missile, target, [parameters]] execVM...

Parameter is an array containing:

  • Missile max speed: The speed the missile will travel (good values between 200 and 1000)
  • Guidance law: The law that will be used: 0 - APN (best), 1 - PN, 2 - LOS
  • Guidance gain: A constant typically between 3 and 5
  • Time to max: Missile speed will increase linearly until it reaches the max
//params ["_missile", "_target", "_speed",];
private _missile 	= param[0];
private _target 	= param[1];
private _parameters = param[2];

//Speed, guidance, N
private _speed 		= _parameters select 0;
private _guidance 	= _parameters select 1;
private _N 			= _parameters select 2;
private _timeToMax	= _parameters select 3;

if(isNull _target) exitWith {};

//Weird issue with APN when engaging missiles idk 
_targetIsMissile = (_target isKindOf "MissileBase");

//Variables for the missile and logic
private _increment = 0.02;
private _currSpeed = _speed / 100;
private _k = 1;
private _initialDist = (_missile distance _target);
private _closeEncounter = false;
private _medianLoops = 5;

_lowestDist = _initialDist;
_incrementSpeed = (_speed - _currSpeed) / _timeToMax;

//Vectorial quantities
_guidVel = [0,0,0];
_leadAcc = [0,0,0];
_lastB = [0,0,0];
_tgtAccNorm = [0,0,0];

private _time = time;
_loop = 0;
while {alive _target and alive _missile} do {
	//Elapsed time
	_deltaT = (time - _time);

	//Speed
	_currSpeed = _currSpeed + _incrementSpeed * _deltaT;
	_currSpeed = _currSpeed min _speed;

	//LOS
	_posA = getPosASL _missile;
	_posB = getPosASL _target;
	_LOS = _posB vectorDiff _posA;
	_steering = _posA vectorFromTo _posB;
	_dist = _missile distance _target;

	//Relative velocity
	_velA = velocity _missile;
	_velB = velocity _target;
	_relVelocity = _velB vectorDiff _velA;

	if(_dist < _lowestDist) then {
		_lowestDist = _dist;
	};

	//Was close
	if(_dist < 1000) then {
		_closeEncounter = true;
	};
	//Now is far
	if(_closeEncounter and (_dist > 1500)) then {
		_mine = createMine ["DemoCharge_F", getPosATL _missile, [], 0];
		_mine setDamage 1;
		deletevehicle _missile;
	};

	switch (_guidance) do {
		//APN
		case 0: {
			//Impact Time Control Cooperative Guidance Law Design Based on Modified Proportional Navigation
			//https://www.mdpi.com/2226-4310/8/8/231/pdf
			//formula [30]
			_tGo = (_dist/(speed _missile)*(1+ ((acos(_velA vectorCos _steering)/90)^2)/(2*(2 * _N - 1))));
			if(isNil "_tgo") then {continue};

			//Zero effort miss
			_ZEM = _LOS vectorAdd (_relVelocity vectorMultiply _tGo);
			_losZEM = _ZEM vectorDotProduct _steering;
			_nrmZEM = (_ZEM vectorDiff (_steering vectorMultiply _losZEM));

			//Weird behaviour when attacking missiles
			if(!_targetIsMissile) then {
				if(_loop == _medianLoops) then {
				//Target accelleration 
					_tgtAcc = _leadAcc vectorMultiply (1/_medianLoops);
					_tgtAccLos = _tgtAcc vectorDotProduct _steering;
					_tgtAccNorm = _tgtAcc vectorDiff (_steering vectorMultiply _tgtAccLos); 		
					_loop = 0;		
				} else {
					_tgtAcc = (_velB vectorDiff _lastB) vectorMultiply (1/_increment);
					_lastB = _velB;
					_leadAcc = _leadAcc vectorAdd _tgtAcc;
					_loop = _loop + 1;
				};
			};

			//augmented prop nav with ZEM and lowered proportional gain
			_leadAcc = (_nrmZEM vectorMultiply _N) vectorMultiply (1/(_tGo ^ 2)) vectorAdd (_tgtAccNorm vectorMultiply (_N/4));
			_guidVel = (_leadAcc vectorMultiply _increment) vectorAdd _velA;
		};

		//PN
		case 1: {
			//Calculate omega
			_rotation = _LOS vectorCrossProduct _relVelocity;
			_distance = _LOS vectorDotProduct _LOS;
			_rotation = _rotation vectorMultiply (1/_distance);
			
			//Desired accelleration to intercept
			_leadAcc = (_relVelocity vectorMultiply _N) vectorCrossProduct _rotation;
			_guidVel = (_leadAcc vectorMultiply _increment) vectorAdd _velA;
		};

		//Pure pursuit
		case 2: {
			_guidVel = _steering;
		}
	};

	//Set new speed
	_guidVel = ((vectorNormalized _guidVel) vectorMultiply _currSpeed);
	_missile setVectorDir _guidVel;
	_missile setVelocity _guidVel;	

	//drawLine3D [_posA, _posA vectorAdd _LOS, [1,1,1,1]];
	sleep _increment;
};

//If the target died or the missile timedout make it blow in mid air
if(alive _missile) then {
	waitUntil {(getposATL _missile select 2) > 100};
	if(alive _target) then {
		sleep random 1;
	};
	
	deletevehicle _missile;
	_mine = createMine ["DemoCharge_F", getPosATL _missile, [], 0];
	_mine setDamage 1;
};


true;

This is more aimed at developers who want to build missile-based systems and for one reason or the other can't use the missile locking capability.

  • Like 5

Share this post


Link to post
Share on other sites

Please sign in to comment

You will be able to leave a comment after signing in



Sign In Now

×