progress update: tercom now flies to acquisition basket

This commit is contained in:
Brandon Danyluk 2021-05-23 17:38:00 -06:00
parent 2694453b56
commit f89bf62242
10 changed files with 322 additions and 7 deletions

View File

@ -128,6 +128,14 @@ class GVAR(SeekerTypes) {
functionName = QFUNC(seekerType_GPS);
onFired = QFUNC(gps_seekerOnFired);
};
class TERCOM {
name = "";
visualName = "";
description = "";
functionName = QFUNC(seekerType_TERCOM);
onFired = QFUNC(tercom_onFired);
};
};
class GVAR(NavigationTypes) {

View File

@ -50,6 +50,7 @@ PREP(seekerType_Doppler);
PREP(seekerType_MWR);
PREP(seekerType_IR);
PREP(seekerType_GPS);
PREP(seekerType_TERCOM);
// Attack Profiles OnFired
PREP(wire_onFired);
@ -62,6 +63,7 @@ PREP(doppler_onFired);
PREP(mwr_onFired);
PREP(IR_onFired);
PREP(gps_seekerOnFired);
PREP(tercom_onFired);
// Navigation OnFired
PREP(proNav_onFired);

View File

@ -23,6 +23,9 @@ _navigationParams params ["_proportionalGain", "", "_derivativeGain", "_lastErro
private _targetDistance = _projectile vectorWorldToModelVisual (_targetDir vectorMultiply _distance);
private _relativeDirection = _projectile vectorWorldToModelVisual _targetDir;
_proportionalGain = 50;
_derivativeGain = 50;
private _errorX = -1 max (1 min (_targetDistance#0 / _correctionDistance));
private _errorY = -1 max (1 min (_targetDistance#2 / _correctionDistance));

View File

@ -0,0 +1,71 @@
#include "script_component.hpp"
/*
* Author: Brandon (TCVM)
* TERCOM seeker. Checks change in height data to current change in height and figures out where it is
* TERCOM works by determining the gradient of height change where the missile is, finding the most likely candidate for that in the
* heightmap, and then plotting a course that will guide it towards the waypointed flightpath
* If you have a lot of similar gradients, this will not work as well since it could potentially lead to loss of munition
*
* Arguments:
* 1: Guidance Arg Array <ARRAY>
* 2: Seeker State <ARRAY>
*
* Return Value:
* Expected correction <ARRAY>
*
* Example:
* [] call ace_missileguidance_fnc_seekerType_TERCOM
*
* Public: No
*/
params ["", "_args", "_seekerStateParams", "", "_timestep"];
_args params ["_firedEH", "_launchParams", "", "", "", "_targetData"];
_firedEH params ["","","","","","","_projectile"];
_seekerStateParams params ["_heightBuffer", "_insPosition", "_seekerState", "_currentWaypoint", "_waypoints", "_heightmap"];
_launchParams params ["", "_targetLaunchParams"];
_targetLaunchParams params ["", "", "_launchPos"];
private _finalPosition = [0, 0, 0];
switch (_seekerState) do {
case TERCOM_STATE_SEEKING_BASKET: {
// must have at least 2 waypoints, so this will never error
private _waypoint1 = _waypoints select 0;
private _waypoint2 = _waypoints select 1;
_waypoint1 params ["_positionA", "_cruiseHeight"];
_waypoint2 params ["_positionB"];
private _direction = _positionA vectorFromTo _positionB;
private _position = _positionA vectorAdd (_direction vectorMultiply (0.5 * (_positionA vectorDistance _positionB)));
_launchPos set [2, _cruiseHeight];
_position set [2, _cruiseHeight];
private _desiredPathDir = _launchPos vectorFromTo _position;
private _missilePosProjected = _launchPos vectorAdd (_desiredPathDir vectorMultiply ((_insPosition vectorDistance _launchPos) + 100));
private _distance = _insPosition vectorDistance _missilePosProjected;
_targetData set [2, _distance];
_finalPosition = _missilePosProjected;
(_heightmap select 0) params ["", "_resolution"];
if (_insPosition inArea [_position, _resolution, _resolution, (_direction#0) atan2 (_direction#1), true]) then {
_seekerStateParams set [2, TERCOM_STATE_FOLLOWING_TERRAIN];
};
};
case TERCOM_STATE_FOLLOWING_TERRAIN: {
// just brute force it, we won't usually have a lot of grids to check
};
case TERCOM_STATE_TERMINAL: {
};
};
if (!isGamePaused && accTime > 0) then {
private _projectileVelocity = velocity _projectile;
_insPosition = _insPosition vectorAdd (_projectileVelocity vectorMultiply _timestep);
_seekerStateParams set [1, _insPosition];
};
_finalPosition

View File

@ -0,0 +1,94 @@
#include "script_component.hpp"
/*
* Author: Brandon (TCVM)
* Sets up TERCOM state arrays
*
* Arguments:
* Guidance Arg Array <ARRAY>
*
* Return Value:
* None
*
* Example:
* [] call ace_missileguidance_fnc_TERCOM_onFired
*
* Public: No
*/
params ["_firedEH", "", "", "", "_stateParams"];
_firedEH params ["","","","","","","_projectile"];
_stateParams params ["", "_seekerStateParams"];
// need a number that denotes maximum grid width at specified resolution
// 3 grid cells in either direction
#define MAX_GRID_WIDTH 5
private _minResolution = 50;
private _maxResolution = 300;
private _waypoints = [
[[22255.6,14042.3,0], 50],
[[19708.9,14668.1,0], 50],
[[17334.5,16922.6,0], 50],
[[13809.5,18171.9,0], 30],
[[11167.8,20575.4,0], 20],
[[6294.59,20780.3,0], 20],
[[4552.04,21492.6,0], 20]
];
private _heightmap = [];
private _maxWaypoints = (count _waypoints) - 1;
{
// at last waypoint, dont process
if (_forEachIndex == _maxWaypoints) exitWith {};
private _nextWaypoint = _waypoints select (_forEachIndex + 1);
_x params ["_positionA", "_cruiseHeight"];
_nextWaypoint params ["_positionB", "_cruiseHeight"];
private _distance = _positionA vectorDistance _positionB;
private _direction = _positionA vectorFromTo _positionB;
private _normalDirection = [-(_direction#1), _direction#0, _direction#2];
private _resolution = linearConversion [0, 1, (_forEachIndex + 1) / _maxWaypoints, _maxResolution, _minResolution];
private _startingGridPos = _positionA vectorAdd (_normalDirection vectorMultiply (MAX_GRID_WIDTH * _resolution));
_startingGridPos = _startingGridPos vectorDiff (_normalDirection vectorMultiply -(_resolution * 0.5));
for "_y" from 0 to (MAX_GRID_WIDTH * 2) do {
private _gridPos = _startingGridPos vectorAdd (_normalDirection vectorMultiply -(_resolution * _y));
private _firstHeightmapCell = [];
for "_x" from 0 to ceil (_distance / _resolution) step 1 do {
private _heightAtPos = 0 max getTerrainHeightASL _gridPos;
_firstHeightmapCell pushBack [_gridPos#0, _gridPos#1, _heightAtPos];
_gridPos = _gridPos vectorAdd (_direction vectorMultiply _resolution);
};
_heightmap pushBack [_firstHeightmapCell, _resolution * MAX_GRID_WIDTH];
};
} forEach _waypoints;
{
{
private _m = createMarker [format ["%1", random 1e10], _x];
_m setMarkerType "mil_dot";
_m setMarkerText format ["%1m", _x select 2];
} forEach (_x select 0);
} forEach _heightmap;
{
_x params ["_position", "_cruiseAltitude"];
private _m = createMarker [format ["%1", random 1e10], _position];
_m setMarkerType "mil_dot";
_m setMarkerText format ["%1m", _cruiseAltitude];
_m setMarkerColor "ColorRed";
} forEach _waypoints;
_seekerStateParams set [0, []]; // internal buffer of heights
_seekerStateParams set [1, getPosASLVisual _projectile]; // calculated current position - simulating INS guidance
_seekerStateParams set [2, TERCOM_STATE_SEEKING_BASKET]; // current state
_seekerStateParams set [3, 0]; // current waypoint
_seekerStateParams set [4, _waypoints];
_seekerStateParams set [5, _heightmap];

View File

@ -1,3 +1,77 @@
class CfgAmmo {
class ammo_Missile_Cruise_01;
class ammo_Missile_Cruise_01_Cluster;
class GVAR(c): ammo_Missile_Cruise_01 {
maneuvrability = 0;
class ace_missileguidance {
enabled = 1;
pitchRate = 25; // Minium flap deflection for guidance
yawRate = 25; // Maximum flap deflection for guidance
canVanillaLock = 1; // Can this default vanilla lock? Only applicable to non-cadet mode
// Guidance type for munitions
defaultSeekerType = "TERCOM";
seekerTypes[] = { "TERCOM" };
defaultSeekerLockMode = "LOBL";
seekerLockModes[] = { "LOBL" };
defaultNavigationType = "Line";
navigationTypes[] = { "Line" };
lineGainP = 50;
lineGainD = 50;
seekLastTargetPos = 0; // seek last target position [if seeker loses LOS of target, continue to last known pos]
seekerAngle = 45; // Angle from the shooter's view that can track the missile
seekerAccuracy = 0.8; // seeker accuracy multiplier
seekerMinRange = 75;
seekerMaxRange = 5000; // Range from the missile which the seeker can visually search
// Attack profile type selection
defaultAttackProfile = "DIR";
attackProfiles[] = {"DIR"};
};
};
class GVAR(d): ammo_Missile_Cruise_01_Cluster {
maneuvrability = 0;
class ace_missileguidance {
enabled = 1;
pitchRate = 25; // Minium flap deflection for guidance
yawRate = 25; // Maximum flap deflection for guidance
canVanillaLock = 1; // Can this default vanilla lock? Only applicable to non-cadet mode
// Guidance type for munitions
defaultSeekerType = "TERCOM";
seekerTypes[] = { "TERCOM" };
defaultSeekerLockMode = "LOBL";
seekerLockModes[] = { "LOBL" };
defaultNavigationType = "Line";
navigationTypes[] = { "Line" };
lineGainP = 50;
lineGainD = 50;
seekLastTargetPos = 0; // seek last target position [if seeker loses LOS of target, continue to last known pos]
seekerAngle = 45; // Angle from the shooter's view that can track the missile
seekerAccuracy = 0.8; // seeker accuracy multiplier
seekerMinRange = 75;
seekerMaxRange = 5000; // Range from the missile which the seeker can visually search
// Attack profile type selection
defaultAttackProfile = "DIR";
attackProfiles[] = {"DIR"};
};
};
};

View File

@ -1,4 +1,16 @@
class CfgMagazines {
class magazine_Missiles_Cruise_01_x18;
class GVAR(c): magazine_Missiles_Cruise_01_x18 {
displayName = CSTRING(c);
displayNameShort = CSTRING(c);
descriptionShort = CSTRING(c_description);
ammo = QGVAR(c);
};
class GVAR(d): magazine_Missiles_Cruise_01_x18 {
displayName = CSTRING(d);
displayNameShort = CSTRING(d);
descriptionShort = CSTRING(d_description);
ammo = QGVAR(d);
};
};

View File

@ -4,18 +4,24 @@ class CfgVehicles {
class Turrets;
};
class B_Ship_MRLS_01_base_F: StaticMGWeapon {
class AnimationSources;
class Turrets: Turrets {
class MainTurret;
};
};
// Use a custom ACE variant due to custom interface for launching
class GVAR(vls): B_Ship_MRLS_01_base_F {
displayName = "[ACE] Mk41 VLS";
class AnimationSources {
class GVAR(vls_c): B_Ship_MRLS_01_base_F {
displayName = CSTRING(vls_c);
scope = 2;
scopeCurator = 2;
side = 1;
faction = "BLU_F";
crew = "B_UAV_AI";
class AnimationSources: AnimationSources {
class Missiles_revolving {
source = "ammo";
source = "revolving";
weapon = QGVAR(c);
animPeriod = 0.001;
};
};
class Turrets: Turrets {
@ -29,4 +35,29 @@ class CfgVehicles {
};
};
};
class GVAR(vls_d): B_Ship_MRLS_01_base_F {
displayName = CSTRING(vls_d);
scope = 2;
scopeCurator = 2;
side = 1;
faction = "BLU_F";
crew = "B_UAV_AI";
class AnimationSources: AnimationSources {
class Missiles_revolving {
source = "ammo";
weapon = QGVAR(d);
animPeriod = 0.001;
};
};
class Turrets: Turrets {
class MainTurret: MainTurret {
weapons[] = {
QGVAR(d)
};
magazines[] = {
QGVAR(d)
};
};
};
};
};

View File

@ -1,7 +1,12 @@
class CfgWeapons {
class weapon_VLS_01;
class GVAR(c): weapon_VLS_01 {
displayName = "Venator Cruise Missile";
magazines[] = {"magazine_Missiles_Cruise_01_x18", "magazine_Missiles_Cruise_01_Cluster_x18"};
displayName = CSTRING(c);
magazines[] = { QGVAR(c) };
};
class GVAR(d): weapon_VLS_01 {
displayName = CSTRING(d);
magazines[] = { QGVAR(d) };
};
};

View File

@ -1,8 +1,23 @@
<?xml version="1.0" encoding="utf-8"?>
<Project name="ACE">
<Package name="TOMAHAWK">
<Key ID="STR_ACE_TOMAHAWK_vls_c">
<English>[ACE] Mk41 VLS [BGM-109C]</English>
</Key>
<Key ID="STR_ACE_TOMAHAWK_c">
<English>BGM-109C</English>
</Key>
<Key ID="STR_ACE_TOMAHAWK_c_description">
<English>Cruise missile with terrain-following capabilites and an HE warhead</English>
</Key>
<Key ID="STR_ACE_TOMAHAWK_vls_d">
<English>[ACE] Mk41 VLS [BGM-109D]</English>
</Key>
<Key ID="STR_ACE_TOMAHAWK_d">
<English>BGM-109D</English>
</Key>
<Key ID="STR_ACE_TOMAHAWK_d_description">
<English>Cruise missile with terrain-following capabilites and a cluster-munition warhead</English>
</Key>
</Package>
</Project>