From 9d26335271efe48dd79f7c730c5f0cb9ce63b00c Mon Sep 17 00:00:00 2001 From: Brandon Danyluk Date: Tue, 20 Apr 2021 18:11:44 -0600 Subject: [PATCH] Fix SACLOS missiles --- addons/hot/CfgAmmo.hpp | 7 ++- addons/metis/CfgAmmo.hpp | 16 ++++-- addons/missileguidance/ACE_GuidanceConfig.hpp | 4 ++ addons/missileguidance/XEH_PREP.hpp | 2 + .../functions/fnc_attackProfile_BEAM.sqf | 20 ++----- .../functions/fnc_attackProfile_WIRE.sqf | 7 +-- .../functions/fnc_guidancePFH.sqf | 4 +- .../functions/fnc_line_onFired.sqf | 33 +++++++++++ .../functions/fnc_navigationType_line.sqf | 55 +++++++++++++++++++ .../missileguidance/functions/fnc_onFired.sqf | 4 +- .../functions/fnc_seekerType_SACLOS.sqf | 5 +- .../functions/fnc_wire_onFired.sqf | 1 + addons/missileguidance/todo.txt | 6 +- 13 files changed, 129 insertions(+), 35 deletions(-) create mode 100644 addons/missileguidance/functions/fnc_line_onFired.sqf create mode 100644 addons/missileguidance/functions/fnc_navigationType_line.sqf diff --git a/addons/hot/CfgAmmo.hpp b/addons/hot/CfgAmmo.hpp index 1c90d42f32..6cd1086bc9 100644 --- a/addons/hot/CfgAmmo.hpp +++ b/addons/hot/CfgAmmo.hpp @@ -69,8 +69,11 @@ class CfgAmmo { defaultSeekerLockMode = "LOAL"; seekerLockModes[] = { "LOAL", "LOBL" }; - defaultNavigationType = "LineOfSight"; - navigationTypes[] = { "LineOfSight" }; + defaultNavigationType = "Line"; + navigationTypes[] = { "Line" }; + + lineGainP = 3; + lineGainD = 2.3; seekLastTargetPos = 0; // seek last target position [if seeker loses LOS of target, continue to last known pos] seekerAngle = 30; // Angle from the shooter's view that can track the missile diff --git a/addons/metis/CfgAmmo.hpp b/addons/metis/CfgAmmo.hpp index a4ff69c5e7..f041a99f30 100644 --- a/addons/metis/CfgAmmo.hpp +++ b/addons/metis/CfgAmmo.hpp @@ -22,8 +22,11 @@ class CfgAmmo { defaultSeekerLockMode = "LOAL"; seekerLockModes[] = { "LOAL", "LOBL" }; - defaultNavigationType = "LineOfSight"; - navigationTypes[] = { "LineOfSight" }; + defaultNavigationType = "Line"; + navigationTypes[] = { "Line" }; + + lineGainP = 3; + lineGainD = 2.1; seekLastTargetPos = 0; // seek last target position [if seeker loses LOS of target, continue to last known pos] seekerAngle = 15; // Angle from the shooter's view that can track the missile @@ -64,8 +67,11 @@ class CfgAmmo { defaultSeekerLockMode = "LOAL"; seekerLockModes[] = { "LOAL", "LOBL" }; - defaultNavigationType = "LineOfSight"; - navigationTypes[] = { "LineOfSight" }; + defaultNavigationType = "Line"; + navigationTypes[] = { "Line" }; + + lineGainP = 3; + lineGainD = 3; seekLastTargetPos = 0; // seek last target position [if seeker loses LOS of target, continue to last known pos] seekerAngle = 15; // Angle from the shooter's view that can track the missile @@ -74,7 +80,7 @@ class CfgAmmo { seekerMinRange = 80; seekerMaxRange = 2000; // Range from the missile which the seeker can visually search - correctionDistance = 6; // distance from center of crosshair where missile slows down + correctionDistance = 1; // distance from center of crosshair where missile slows down offsetFromCrosshair[] = { 0, 0, 0 }; // where the missile wants to stay in relation to the center of the crosshair. // Attack profile type selection diff --git a/addons/missileguidance/ACE_GuidanceConfig.hpp b/addons/missileguidance/ACE_GuidanceConfig.hpp index 5fc73110ef..fb2990b018 100644 --- a/addons/missileguidance/ACE_GuidanceConfig.hpp +++ b/addons/missileguidance/ACE_GuidanceConfig.hpp @@ -123,6 +123,10 @@ class GVAR(SeekerTypes) { }; class GVAR(NavigationTypes) { + class Line { + functionName = QFUNC(navigationType_line); + onFired = QFUNC(line_onFired); + }; class LineOfSight { functionName = QFUNC(navigationType_lineOfSight); onFired = QFUNC(proNav_onFired); diff --git a/addons/missileguidance/XEH_PREP.hpp b/addons/missileguidance/XEH_PREP.hpp index 5ec6f2e6e4..ff3268069f 100644 --- a/addons/missileguidance/XEH_PREP.hpp +++ b/addons/missileguidance/XEH_PREP.hpp @@ -36,6 +36,7 @@ PREP(navigationType_zeroEffortMiss); PREP(navigationType_augmentedProNav); PREP(navigationType_proNav); PREP(navigationType_lineOfSight); +PREP(navigationType_line); // Seeker search functions PREP(seekerType_SALH); @@ -59,6 +60,7 @@ PREP(gps_seekerOnFired); // Navigation OnFired PREP(proNav_onFired); +PREP(line_onFired); // State transitions PREP(javelin_midCourseTransition); diff --git a/addons/missileguidance/functions/fnc_attackProfile_BEAM.sqf b/addons/missileguidance/functions/fnc_attackProfile_BEAM.sqf index 7e9408b2d7..7ae09c5615 100644 --- a/addons/missileguidance/functions/fnc_attackProfile_BEAM.sqf +++ b/addons/missileguidance/functions/fnc_attackProfile_BEAM.sqf @@ -24,24 +24,12 @@ _attackProfileStateParams params["_maxCorrectableDistance", "_wireCut", "_random private _projectilePos = getPosASL _projectile; private _shooterPos = getPosASL _shooter; -private _shooterDir = vectorNormalized(_seekerTargetPos vectorDiff _shooterPos); private _distanceToProjectile = _shooterPos vectorDistanceSqr _projectilePos; -if (_distanceToProjectile > _seekerMaxRangeSqr || { _seekerTargetPos isEqualTo [0, 0, 0] } || { _distanceToProjectile < _seekerMinRangeSqr }) exitWith { - // return position 50m infront of projectile - _projectilePos vectorAdd (_projectile vectorModelToWorld [0, 50, 0]) +if (_seekerTargetPos isEqualTo [0, 0, 0] || { _distanceToProjectile < _seekerMinRangeSqr }) exitWith { + // return position 50m infront of projectile and a bit up to get out of the way of the ground + _projectilePos vectorAdd (_projectile vectorModelToWorld [0, 50, 3]) }; -private _relativeCorrection = _projectile vectorWorldToModel (_projectilePos vectorDiff _seekerTargetPos); -_relativeCorrection = _relativeCorrection vectorDiff _crosshairOffset; +_seekerTargetPos vectorAdd _crosshairOffset -private _magnitude = vectorMagnitude [_relativeCorrection select 0, 0, _relativeCorrection select 2]; -private _fovImpulse = 1 min (_magnitude / _maxCorrectableDistance); // the simulated impulse for the missile being close to the center of the crosshair - -// Adjust the impulse due to near-zero values creating wobbly missiles? -private _correction = _fovImpulse; - - -_relativeCorrection = (vectorNormalized _relativeCorrection) vectorMultiply _correction; -private _returnPos = _projectilePos vectorDiff (_projectile vectorModelToWorld _relativeCorrection); -_returnPos vectorAdd (_shooterDir vectorMultiply _distanceAheadOfMissile) diff --git a/addons/missileguidance/functions/fnc_attackProfile_WIRE.sqf b/addons/missileguidance/functions/fnc_attackProfile_WIRE.sqf index a17cb8a493..d0172187b6 100644 --- a/addons/missileguidance/functions/fnc_attackProfile_WIRE.sqf +++ b/addons/missileguidance/functions/fnc_attackProfile_WIRE.sqf @@ -24,7 +24,6 @@ _attackProfileStateParams params["_maxCorrectableDistance", "_wireCut", "_random private _projectilePos = getPosASL _projectile; private _shooterPos = getPosASL _shooter; -private _shooterDir = vectorNormalized(_seekerTargetPos vectorDiff _shooterPos); private _distanceToProjectile = _shooterPos vectorDistanceSqr _projectilePos; if ((_distanceToProjectile > _seekerMaxRangeSqr) || { _wireCut }) exitWith { @@ -44,9 +43,9 @@ if (_seekerTargetPos isEqualTo [0, 0, 0] || { _distanceToProjectile < _seekerMin /*if (lineIntersectsSurfaces [getPosASL _shooter, _projectilePos, _shooter] isNotEqualTo []) then { _attackProfileStateParams set [1, true]; };*/ - // return position 50m infront of projectile - _projectilePos vectorAdd (_projectile vectorModelToWorld [0, 50, 0]) + // return position 50m infront of projectile and a bit up to get out of the way of the ground + _projectilePos vectorAdd (_projectile vectorModelToWorld [0, 50, 3]) }; -_seekerTargetPos vectorAdd (_shooterDir vectorMultiply 30); +_seekerTargetPos vectorAdd _crosshairOffset diff --git a/addons/missileguidance/functions/fnc_guidancePFH.sqf b/addons/missileguidance/functions/fnc_guidancePFH.sqf index 9da0f0de57..dd55a5073c 100644 --- a/addons/missileguidance/functions/fnc_guidancePFH.sqf +++ b/addons/missileguidance/functions/fnc_guidancePFH.sqf @@ -61,10 +61,10 @@ if ((_pitchRate != 0 || {_yawRate != 0}) && {_profileAdjustedTargetPos isNotEqua }; - private _commandedAcceleration = [_args, _timestep, _seekerTargetPos, _profileAdjustedTargetPos] call (missionNamespace getVariable _navigationFunction); + private _commandedAcceleration = [_args, _timestep, _seekerTargetPos, _profileAdjustedTargetPos, _targetData, _navigationParameters] call (missionNamespace getVariable _navigationFunction); if (isNil "_commandedAcceleration") exitWith { - systemChat _navigationFunction; + systemChat format ["Error in %1", _navigationFunction]; ERROR_MSG("_commandedAcceleration is nil! Guidance cancelled"); }; diff --git a/addons/missileguidance/functions/fnc_line_onFired.sqf b/addons/missileguidance/functions/fnc_line_onFired.sqf new file mode 100644 index 0000000000..53726a5e9c --- /dev/null +++ b/addons/missileguidance/functions/fnc_line_onFired.sqf @@ -0,0 +1,33 @@ +#include "script_component.hpp" +/* + * Author: Brandon (TCVM) + * Sets up line state arrays (called from missileGuidance's onFired). + * + * Arguments: + * Guidance Arg Array + * + * Return Value: + * None + * + * Example: + * [] call ace_missileguidance_fnc_line_onFired + * + * Public: No + */ +params ["_firedEH", "", "", "", "_stateParams"]; +_firedEH params ["","","","","","","_projectile"]; +_stateParams params ["", "", "", "", "_navigationParams"]; + +private _ammoConfig = configOf _projectile; +private _p = getNumber (_ammoConfig >> QUOTE(ADDON) >> "lineGainP"); +private _d = getNumber (_ammoConfig >> QUOTE(ADDON) >> "lineGainD"); +private _correctionDistance = getNumber (_ammoConfig >> QUOTE(ADDON) >> "correctionDistance"); + +_navigationParams set [0, _p]; +_navigationParams set [1, _i]; +_navigationParams set [2, _d]; + +_navigationParams set [3, 0]; +_navigationParams set [4, 0]; +_navigationParams set [5, _correctionDistance]; + diff --git a/addons/missileguidance/functions/fnc_navigationType_line.sqf b/addons/missileguidance/functions/fnc_navigationType_line.sqf new file mode 100644 index 0000000000..cd1d242eb1 --- /dev/null +++ b/addons/missileguidance/functions/fnc_navigationType_line.sqf @@ -0,0 +1,55 @@ +#include "script_component.hpp" +/* + * Author: Brandon (TCVM) + * Assumes targetDir is pointing toward line we want to stay on + * + * Arguments: + * Guidance Arg Array + * + * Return Value: + * Commanded acceleration normal to LOS in world space + * + * Example: + * [] call ace_missileguidance_fnc_navigationType_line + * + * Public: No + */ +params ["_args", "_timestep", "_seekerTargetPos", "_profileAdjustedTargetPos", "_targetData", "_navigationParams"]; +_args params ["", "", "_flightParams"]; +_targetData params ["", "_targetDir", "_distance"]; +_flightParams params ["_pitchRate", "_yawRate"]; + +_navigationParams params ["_proportionalGain", "", "_derivativeGain", "_lastErrorX", "_lastErrorY", "_correctionDistance"]; +private _targetDistance = _projectile vectorWorldToModelVisual (_targetDir vectorMultiply _distance); +private _relativeDirection = _projectile vectorWorldToModelVisual _targetDir; + +private _errorX = 1 min (_targetDistance#0 / _correctionDistance); +private _errorY = 1 min (_targetDistance#2 / _correctionDistance); + +private _pX = _proportionalGain * _errorX; +private _dX = if (_timestep != 0) then { + _derivativeGain * (_errorX - _lastErrorX) / _timestep +} else { + 0 +}; + +private _pY = _proportionalGain * _errorY; +private _dY = if (_timestep != 0) then { + _derivativeGain * (_errorY - _lastErrorY) / _timestep +} else { + 0 +}; + +private _accelerationX = _pX + _dX; +private _accelerationY = _pY + _dY; + +private _commandedAcceleration = [ + _accelerationX, + 0, + _accelerationY +]; + +_navigationParams set [3, _errorX]; +_navigationParams set [4, _errorY]; + +_projectile vectorModelToWorldVisual _commandedAcceleration; diff --git a/addons/missileguidance/functions/fnc_onFired.sqf b/addons/missileguidance/functions/fnc_onFired.sqf index 482ea78c46..89b73c7f08 100644 --- a/addons/missileguidance/functions/fnc_onFired.sqf +++ b/addons/missileguidance/functions/fnc_onFired.sqf @@ -156,7 +156,7 @@ private _args = [_this, getNumber ( _config >> "seekerMaxRange" ), getNumber ( _config >> "seekerMinRange" ) ], - [ diag_tickTime, [], [], _lastKnownPosState, _navigationParameters, [_pitchYaw select 1, 0, _pitchYaw select 2]], + [ diag_tickTime, [], [], _lastKnownPosState, _navigationParameters, [_pitchYaw select 1, 0, 1.5 + (_pitchYaw select 2)]], [ // target data from missile. Must be filled by seeker for navigation to work [0, 0, 0], // direction to target @@ -199,7 +199,7 @@ if (_onFiredFunc != "") then { // _launchParams params ["_shooter","_targetLaunchParams","_seekerType","_attackProfile","_lockMode","_laserInfo","_navigationType"]; // _targetLaunchParams params ["_target", "_targetPos", "_launchPos", "_launchDir", "_launchTime"]; // _flightParams params ["_pitchRate", "_yawRate", "_isBangBangGuidance"]; -// _stateParams params ["_lastRunTime", "_seekerStateParams", "_attackProfileStateParams", "_lastKnownPosState","_navigationParams", "_guidanceParameters"]; +// _stateParams params ["_lastRunTime", "_seekerStateParams", "_attackProfileStateParams", "_lastKnownPosState", "_navigationParams", "_guidanceParameters"]; // _seekerParams params ["_seekerAngle", "_seekerAccuracy", "_seekerMaxRange", "_seekerMinRange"]; // _targetData params ["_targetDirection", "_attackProfileDirection", "_targetRange", "_targetVelocity", "_targetAcceleration"]; diff --git a/addons/missileguidance/functions/fnc_seekerType_SACLOS.sqf b/addons/missileguidance/functions/fnc_seekerType_SACLOS.sqf index a1e5fc49ac..04f59a28b9 100644 --- a/addons/missileguidance/functions/fnc_seekerType_SACLOS.sqf +++ b/addons/missileguidance/functions/fnc_seekerType_SACLOS.sqf @@ -58,7 +58,10 @@ if ((_testDotProduct < (cos _seekerAngle)) || {_testIntersections isNotEqualTo [ [0, 0, 0] }; +private _returnPos = _shooterPos vectorAdd (_lookDirection vectorMultiply _distanceToProj); + _targetData set [0, _lookDirection]; +_targetData set [2, _returnPos distance getPosASLVisual _projectile]; -_shooterPos vectorAdd (_lookDirection vectorMultiply _distanceToProj); +_returnPos diff --git a/addons/missileguidance/functions/fnc_wire_onFired.sqf b/addons/missileguidance/functions/fnc_wire_onFired.sqf index cb4020bd0f..6c9c64bd3d 100644 --- a/addons/missileguidance/functions/fnc_wire_onFired.sqf +++ b/addons/missileguidance/functions/fnc_wire_onFired.sqf @@ -46,3 +46,4 @@ _attackProfileStateParams set [5, _minDistanceSqr]; _attackProfileStateParams set [6, _wireCutSource]; _attackProfileStateParams set [7, _distanceAheadOfMissile]; + diff --git a/addons/missileguidance/todo.txt b/addons/missileguidance/todo.txt index 0345008baf..7a75651511 100644 --- a/addons/missileguidance/todo.txt +++ b/addons/missileguidance/todo.txt @@ -50,8 +50,8 @@ Navigation Types: X Dragon - NA - Metis - Wire/Beam Guidance - HOT - Wire/Beam Guidance + X Metis - Wire/Beam Guidance + X HOT - Wire/Beam Guidance Vikhr - Wire/Beam Guidance X DAGR - APN @@ -83,7 +83,7 @@ Navigation State Machine: Navigation Types: X Augmented Pro-Nav X Zero Effort Miss - Wire/Beam Guided + X Wire/Beam Guided Predicted Line of Sight General To-Do: