From 6d3cd257788bd9f6170a8a36c5a428c2821b4e9f Mon Sep 17 00:00:00 2001 From: Bailey Danyluk Date: Wed, 28 Aug 2024 01:43:18 -0600 Subject: [PATCH] Fix javelin flight profile --- .../functions/fnc_midCourseTransition.sqf | 1 + addons/missileguidance/CfgAmmo.hpp | 4 +- .../functions/fnc_attackProfile_JAV_DIR.sqf | 22 +++++++--- .../functions/fnc_attackProfile_JAV_TOP.sqf | 44 ++++++++++++------- .../functions/fnc_guidancePFH.sqf | 2 +- .../fnc_javelin_midCourseTransition.sqf | 19 +++++++- .../functions/fnc_navigationType_direct.sqf | 22 ++++++++-- 7 files changed, 84 insertions(+), 30 deletions(-) diff --git a/addons/hellfire/functions/fnc_midCourseTransition.sqf b/addons/hellfire/functions/fnc_midCourseTransition.sqf index ee56773410..034bd25d61 100644 --- a/addons/hellfire/functions/fnc_midCourseTransition.sqf +++ b/addons/hellfire/functions/fnc_midCourseTransition.sqf @@ -15,6 +15,7 @@ * Public: No */ +params ["_args", "_timestep"]; _args params ["_firedEH", "_launchParams", "_flightParams", "_seekerParams", "_stateParams", "_targetData", "_navigationStateData"]; _firedEH params ["_shooter","","","","_ammo","","_projectile"]; _launchParams params ["_shooter","_targetLaunchParams","_seekerType","_attackProfile","_lockMode","_laserInfo","_navigationType"]; diff --git a/addons/missileguidance/CfgAmmo.hpp b/addons/missileguidance/CfgAmmo.hpp index d9813fdf77..8f913e9965 100644 --- a/addons/missileguidance/CfgAmmo.hpp +++ b/addons/missileguidance/CfgAmmo.hpp @@ -71,8 +71,8 @@ class CfgAmmo { class ADDON { enabled = 1; - pitchRate = 100; // degrees per second - yawRate = 100; + pitchRate = 120; // degrees per second + yawRate = 120; stabilityCoefficient = 0.2; bangBangGuidance = 0; diff --git a/addons/missileguidance/functions/fnc_attackProfile_JAV_DIR.sqf b/addons/missileguidance/functions/fnc_attackProfile_JAV_DIR.sqf index 6b06c0dd91..64895a3e54 100644 --- a/addons/missileguidance/functions/fnc_attackProfile_JAV_DIR.sqf +++ b/addons/missileguidance/functions/fnc_attackProfile_JAV_DIR.sqf @@ -22,6 +22,9 @@ #define STAGE_COAST 3 #define STAGE_TERMINAL 4 +#define CLIMB_ANGLE 12 +#define ATTACK_ANGLE 2 + params ["_seekerTargetPos", "_args", "_attackProfileStateParams"]; _args params ["_firedEH"]; _firedEH params ["_shooter","","","","","","_projectile"]; @@ -30,6 +33,7 @@ if (_seekerTargetPos isEqualTo [0,0,0]) exitWith {_seekerTargetPos}; if (_attackProfileStateParams isEqualTo []) then { _attackProfileStateParams set [0, STAGE_LAUNCH]; + _attackProfileStateParams set [1, 0]; }; private _shooterPos = getPosASL _shooter; @@ -44,24 +48,28 @@ TRACE_2("",_distanceToTarget,_distanceToShooter); // Add height depending on distance for compensate private _returnTargetPos = _seekerTargetPos; +private _attackDirection = _seekerTargetPos vectorDiff _projectilePos; +private _horizon = velocity _projectile; +_horizon set [2, 0]; +_horizon = vectorNormalized _horizon; +private _attackAngle = acos (_horizon vectorCos _attackDirection); + switch (_attackProfileStateParams select 0) do { case STAGE_LAUNCH: { TRACE_1("STAGE_LAUNCH",""); if (_distanceToShooter < 6) then { - _returnTargetPos = _seekerTargetPos vectorAdd [0,0,_distanceToTarget*2]; + _returnTargetPos = _seekerTargetPos vectorAdd [0,0,5]; } else { _attackProfileStateParams set [0, STAGE_CLIMB]; }; }; case STAGE_CLIMB: { TRACE_1("STAGE_CLIMB",""); - // 65 is min range - private _cruisAlt = 60 * ((0 max (_distanceShooterToTarget - 65))/2000); - - if ( ((ASLToAGL _projectilePos) select 2) - ((ASLToAGL _seekerTargetPos) select 2) >= _cruisAlt) then { + if (_attackAngle >= ATTACK_ANGLE) then { _attackProfileStateParams set [0, STAGE_TERMINAL]; } else { - _returnTargetPos = _seekerTargetPos vectorAdd [0,0,_distanceToTarget*1.5]; + private _height = _distanceShooterToTarget * tan CLIMB_ANGLE; + _returnTargetPos = _seekerTargetPos vectorAdd [0,0,_height]; }; }; case STAGE_TERMINAL: { @@ -70,5 +78,7 @@ switch (_attackProfileStateParams select 0) do { }; }; +_attackProfileStateParams set [2, _returnTargetPos]; + TRACE_1("Adjusted target position",_returnTargetPos); _returnTargetPos; diff --git a/addons/missileguidance/functions/fnc_attackProfile_JAV_TOP.sqf b/addons/missileguidance/functions/fnc_attackProfile_JAV_TOP.sqf index 347d144914..a3ae233eba 100644 --- a/addons/missileguidance/functions/fnc_attackProfile_JAV_TOP.sqf +++ b/addons/missileguidance/functions/fnc_attackProfile_JAV_TOP.sqf @@ -22,6 +22,10 @@ #define STAGE_COAST 3 #define STAGE_TERMINAL 4 +#define CRUISE_ALT 160 +#define CLIMB_ANGLE 22 +#define ATTACK_ANGLE 12 + params ["_seekerTargetPos", "_args", "_attackProfileStateParams"]; _args params ["_firedEH"]; _firedEH params ["_shooter","","","","","","_projectile"]; @@ -30,6 +34,7 @@ if (_seekerTargetPos isEqualTo [0,0,0]) exitWith {_seekerTargetPos}; if (_attackProfileStateParams isEqualTo []) then { _attackProfileStateParams set [0, STAGE_LAUNCH]; + _attackProfileStateParams set [1, 0]; }; private _shooterPos = getPosASL _shooter; @@ -44,39 +49,44 @@ TRACE_2("",_distanceToTarget,_distanceToShooter); // Add height depending on distance for compensate private _returnTargetPos = _seekerTargetPos; +private _attackDirection = _seekerTargetPos vectorDiff _projectilePos; +private _horizon = velocity _projectile; +_horizon set [2, 0]; +_horizon = vectorNormalized _horizon; +private _attackAngle = acos (_horizon vectorCos _attackDirection); + switch( (_attackProfileStateParams select 0) ) do { case STAGE_LAUNCH: { TRACE_1("STAGE_LAUNCH",""); if (_distanceToShooter < 10) then { - _returnTargetPos = _seekerTargetPos vectorAdd [0,0,_distanceToTarget*2]; + _returnTargetPos = _seekerTargetPos vectorAdd [0,0,5]; } else { _attackProfileStateParams set [0, STAGE_CLIMB]; }; }; case STAGE_CLIMB: { TRACE_1("STAGE_CLIMB",""); - private _cruisAlt = 140; - if (_distanceShooterToTarget < 1250) then { - _cruisAlt = 140 * ((0 max (_distanceShooterToTarget - 150))/1250); - TRACE_1("_cruisAlt",_cruisAlt); - }; - if ( ((ASLToAGL _projectilePos) select 2) - ((ASLToAGL _seekerTargetPos) select 2) >= _cruisAlt) then { - if (_cruisAlt < 140) then { - _attackProfileStateParams set [0, STAGE_TERMINAL]; - } else { + private _altitude = (ASLToAGL _projectilePos) select 2; + switch (true) do { + case (_altitude >= CRUISE_ALT): { _attackProfileStateParams set [0, STAGE_COAST]; }; - } else { - _returnTargetPos = _seekerTargetPos vectorAdd [0,0,_distanceToTarget*1.5]; - }; + case (_attackAngle >= ATTACK_ANGLE): { + _attackProfileStateParams set [0, STAGE_TERMINAL]; + }; + default { + private _height = _distanceShooterToTarget * tan CLIMB_ANGLE; + _returnTargetPos = _seekerTargetPos vectorAdd [0,0,_height]; + } + } }; case STAGE_COAST: { TRACE_1("STAGE_COAST",""); - TRACE_1("",((ASLToAGL _projectilePos) select 2) - (( ASLToAGL _seekerTargetPos) select 2)); - if (_distanceToTarget < ( ((ASLToAGL _projectilePos) select 2) - (( ASLToAGL _seekerTargetPos) select 2) ) * 2) then { + TRACE_1("",_attackAngle); + if (_attackAngle >= ATTACK_ANGLE) then { _attackProfileStateParams set [0, STAGE_TERMINAL]; } else { - _returnTargetPos = _seekerTargetPos vectorAdd [0,0,(_projectilePos select 2)]; + _returnTargetPos = _seekerTargetPos vectorAdd [0,0,(_projectilePos select 2) min CRUISE_ALT]; }; }; case STAGE_TERMINAL: { @@ -86,5 +96,7 @@ switch( (_attackProfileStateParams select 0) ) do { }; }; +_attackProfileStateParams set [2, _returnTargetPos]; + TRACE_1("Adjusted target position",_returnTargetPos); _returnTargetPos; diff --git a/addons/missileguidance/functions/fnc_guidancePFH.sqf b/addons/missileguidance/functions/fnc_guidancePFH.sqf index 28f677bbdd..4d3e4b6750 100644 --- a/addons/missileguidance/functions/fnc_guidancePFH.sqf +++ b/addons/missileguidance/functions/fnc_guidancePFH.sqf @@ -54,7 +54,7 @@ if ((_pitchRate != 0 || {_yawRate != 0})) then { private _navigationFunction = getText (configFile >> QGVAR(NavigationTypes) >> _navigationType >> "functionName"); if (_navigationStateData isNotEqualTo []) then { (_navigationStateData select _currentState) params ["_transitionCondition"]; - private _transition = (_args call (missionNamespace getVariable [_transitionCondition, { false }])); + private _transition = ([_args, _timestep] call (missionNamespace getVariable [_transitionCondition, { false }])); if (_transition) then { _currentState = _currentState + 1; _navigationStateParams set [0, _currentState]; diff --git a/addons/missileguidance/functions/fnc_javelin_midCourseTransition.sqf b/addons/missileguidance/functions/fnc_javelin_midCourseTransition.sqf index ad0eca65cb..58995dee31 100644 --- a/addons/missileguidance/functions/fnc_javelin_midCourseTransition.sqf +++ b/addons/missileguidance/functions/fnc_javelin_midCourseTransition.sqf @@ -19,6 +19,10 @@ #define STAGE_COAST 3 #define STAGE_TERMINAL 4 +#define REQUIRED_STABLE_TIME 0.2 +#define REQUIRED_ANGLE 1 + +params ["_args", "_timestep"]; _args params ["_firedEH", "_launchParams", "_flightParams", "_seekerParams", "_stateParams", "_targetData", "_navigationStateData"]; _firedEH params ["_shooter","","","","_ammo","","_projectile"]; _launchParams params ["_shooter","_targetLaunchParams","_seekerType","_attackProfile","_lockMode","_laserInfo","_navigationType"]; @@ -28,6 +32,17 @@ _stateParams params ["_lastRunTime", "_seekerStateParams", "_attackProfileStateP _seekerParams params ["_seekerAngle", "_seekerAccuracy", "_seekerMaxRange", "_seekerMinRange"]; _targetData params ["_targetDirection", "_attackProfileDirection", "_targetRange", "_targetVelocity", "_targetAcceleration"]; -_attackProfileStateParams params ["_state"]; -_state isEqualTo STAGE_TERMINAL +_attackProfileStateParams params ["_state", "_stableTime", "_target"]; +private _projectileDirection = vectorNormalized velocity _projectile; +private _targetDistance = _target vectorDistance getPosASLVisual _projectile; +private _targetDirection = (getPosASLVisual _projectile) vectorFromTo _target; +private _angle = _projectileDirection vectorCos _targetDirection; +if (_angle > cos REQUIRED_ANGLE) then { + _stableTime = _stableTime + _timestep; +} else { + _stableTime = 0; +}; + +_attackProfileStateParams set [1, _stableTime]; +_state isEqualTo STAGE_TERMINAL && _stableTime > REQUIRED_STABLE_TIME diff --git a/addons/missileguidance/functions/fnc_navigationType_direct.sqf b/addons/missileguidance/functions/fnc_navigationType_direct.sqf index 7b4763b44e..e8e9f5e42d 100644 --- a/addons/missileguidance/functions/fnc_navigationType_direct.sqf +++ b/addons/missileguidance/functions/fnc_navigationType_direct.sqf @@ -14,8 +14,24 @@ * * Public: No */ -params ["_args", "", "", "_profileAdjustedTargetPos"]; -_args params ["_firedEH"]; +params ["_args", "_timestep", "", "_profileAdjustedTargetPos"]; +_args params ["_firedEH", "", "_flightParams"]; +_flightParams params ["_pitchRate", "_yawRate"]; _firedEH params ["","","","","","","_projectile"]; -_profileAdjustedTargetPos vectorDiff getPosASLVisual _projectile +private _projectilePos = getPosASLVisual _projectile; +private _magnitude = _profileAdjustedTargetPos vectorDistance _projectilePos; + +private _targetDirection = _projectilePos vectorFromTo _profileAdjustedTargetPos; +private _projectileDirection = vectorNormalized velocity _projectile; + +private _deltaDirection = _targetDirection vectorDiff _projectileDirection; +_deltaDirection = _projectile vectorWorldToModelVisual _deltaDirection; +_deltaDirection = _deltaDirection vectorMultiply [_yawRate, 0, _pitchRate]; +_deltaDirection = _projectile vectorModelToWorldVisual _deltaDirection; + +private _iTimestep = 0; +if (_timestep != 0) then { + _iTimestep = 1 / _timestep; +}; +_deltaDirection vectorMultiply _iTimestep \ No newline at end of file