init
This commit is contained in:
388
processors/timeline_agents/weapon_defs.txt
Normal file
388
processors/timeline_agents/weapon_defs.txt
Normal file
@@ -0,0 +1,388 @@
|
||||
# ****************************************************************************
|
||||
# CUI
|
||||
#
|
||||
# The Advanced Framework for Simulation, Integration, and Modeling (AFSIM)
|
||||
#
|
||||
# The use, dissemination or disclosure of data in this file is subject to
|
||||
# limitation or restriction. See accompanying README and LICENSE for details.
|
||||
# ****************************************************************************
|
||||
|
||||
script_struct WeaponData
|
||||
script_variables
|
||||
string type = "";
|
||||
double rangeMin = 0; #meters
|
||||
double rangeMax = 0; #meters
|
||||
bool onlyUseInRange = true;
|
||||
double averageSpeed = 0; #meters/second
|
||||
double maxTimeFlight = 0; #seconds, note: should == rangeMax / averageSpeed
|
||||
int numActiveMax = 0;
|
||||
bool domainAir = false;
|
||||
bool domainLand = false;
|
||||
double maxFiringAngle = 0;
|
||||
end_script_variables
|
||||
end_script_struct
|
||||
|
||||
script_variables
|
||||
Map<string, struct> gWeaponDefs = Map<string, struct>();
|
||||
|
||||
gWeaponDefs["MEDIUM_RANGE_MISSILE"] = struct.New("WeaponData");
|
||||
gWeaponDefs["MEDIUM_RANGE_MISSILE"]->type = "MEDIUM_RANGE_MISSILE";
|
||||
gWeaponDefs["MEDIUM_RANGE_MISSILE"]->rangeMin = 50; # (meters)
|
||||
gWeaponDefs["MEDIUM_RANGE_MISSILE"]->rangeMax = 111120; # ~60 nm (meters)
|
||||
gWeaponDefs["MEDIUM_RANGE_MISSILE"]->averageSpeed = 1657.283; #mach 5 (m/s)
|
||||
gWeaponDefs["MEDIUM_RANGE_MISSILE"]->maxTimeFlight = 67.05; #for 60 nm range (seconds)
|
||||
gWeaponDefs["MEDIUM_RANGE_MISSILE"]->numActiveMax = 2;
|
||||
gWeaponDefs["MEDIUM_RANGE_MISSILE"]->domainAir = true;
|
||||
gWeaponDefs["MEDIUM_RANGE_MISSILE"]->domainLand = false;
|
||||
gWeaponDefs["MEDIUM_RANGE_MISSILE"]->maxFiringAngle = 45.0;
|
||||
|
||||
gWeaponDefs["MEDIUM_RANGE_RADAR_MISSILE"] = struct.New("WeaponData");
|
||||
gWeaponDefs["MEDIUM_RANGE_RADAR_MISSILE"]->type = "MEDIUM_RANGE_RADAR_MISSILE";
|
||||
gWeaponDefs["MEDIUM_RANGE_RADAR_MISSILE"]->rangeMin = 50; # (meters)
|
||||
gWeaponDefs["MEDIUM_RANGE_RADAR_MISSILE"]->rangeMax = 111120; # ~60 nm (meters)
|
||||
gWeaponDefs["MEDIUM_RANGE_RADAR_MISSILE"]->averageSpeed = 1657.283; #mach 5 (m/s)
|
||||
gWeaponDefs["MEDIUM_RANGE_RADAR_MISSILE"]->maxTimeFlight = 67.05; #for 60 nm range (seconds)
|
||||
gWeaponDefs["MEDIUM_RANGE_RADAR_MISSILE"]->numActiveMax = 2;
|
||||
gWeaponDefs["MEDIUM_RANGE_RADAR_MISSILE"]->domainAir = true;
|
||||
gWeaponDefs["MEDIUM_RANGE_RADAR_MISSILE"]->domainLand = false;
|
||||
gWeaponDefs["MEDIUM_RANGE_RADAR_MISSILE"]->maxFiringAngle = 45.0;
|
||||
|
||||
end_script_variables
|
||||
|
||||
#returns a 'WeaponData' struct
|
||||
script struct GetWeaponData(string aType)
|
||||
if (gWeaponDefs.Exists(aType))
|
||||
{
|
||||
return gWeaponDefs.Get(aType);
|
||||
}
|
||||
else
|
||||
{
|
||||
return struct.New("WeaponData");
|
||||
}
|
||||
end_script
|
||||
|
||||
|
||||
include_once processors/quantum_agents/common/common_platform_script.txt
|
||||
|
||||
script_debug_writes off
|
||||
|
||||
script bool WeaponCapableAvailableAgainstThreat(WsfWeapon weapon, WsfTrack track)
|
||||
writeln_d(" checking weapon ", weapon.Name(), " valid=", weapon.IsValid());
|
||||
if (weapon.IsNull() || !weapon.IsValid() || track.IsNull() || !track.IsValid())
|
||||
{
|
||||
writeln_d("weapon or track is not valid!");
|
||||
return false;
|
||||
}
|
||||
if ((weapon.QuantityRemaining()-weapon.WeaponsPendingFor(WsfTrackId())) <= 0)
|
||||
{
|
||||
writeln_d("no unassigned weapons left to fire!");
|
||||
return false;
|
||||
}
|
||||
|
||||
#check manually input user data first
|
||||
struct weaponData = GetWeaponData(weapon.Type());
|
||||
if (weaponData->type == weapon.Type())
|
||||
{
|
||||
if ((track.AirDomain() && !weaponData->domainAir) ||
|
||||
(track.LandDomain() && !weaponData->domainLand) )
|
||||
{
|
||||
writeln_d("weapon not capable against target domain!");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
writeln_d("could not find weapon type ", weapon.Type() ," in weapon database; query returned type ", weaponData->type);
|
||||
#check if it has a launch computer of the necessary type
|
||||
WsfLaunchComputer lcPtr = weapon.LaunchComputer();
|
||||
if (lcPtr.IsValid())
|
||||
{
|
||||
if (track.AirDomain() && lcPtr.IsA_TypeOf("WSF_AIR_TO_AIR_LAUNCH_COMPUTER"))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else if (track.LandDomain() && lcPtr.IsA_TypeOf("WSF_ATG_LAUNCH_COMPUTER"))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
writeln_d("nor could an applicable launch computer be found!");
|
||||
return false; #dont have weapon data
|
||||
}
|
||||
return true;
|
||||
end_script
|
||||
|
||||
|
||||
#could return -1 for an invalid max range
|
||||
#(from a launch computer or weapon struct not found)
|
||||
script double MaxRange(WsfPlatform shooter, WsfWeapon weapon, WsfTrack track)
|
||||
WsfLaunchComputer lcPtr = weapon.LaunchComputer();
|
||||
if (lcPtr.IsValid() &&
|
||||
lcPtr.IsA_TypeOf("WSF_AIR_TO_AIR_LAUNCH_COMPUTER"))
|
||||
{
|
||||
double rmax = lcPtr.LookupResult(track)[0];
|
||||
return rmax;
|
||||
}
|
||||
else
|
||||
{
|
||||
struct weaponData = GetWeaponData(weapon.Type());
|
||||
if (weaponData->type == weapon.Type())
|
||||
{
|
||||
return weaponData->rangeMax;
|
||||
}
|
||||
else
|
||||
{
|
||||
return -1.0;
|
||||
}
|
||||
}
|
||||
end_script
|
||||
|
||||
#if beyond max range: returns time to hit if launched at max range
|
||||
#if before min range: returns time to hit if launched at min range
|
||||
#could return -1 for an invalid max range
|
||||
#(from a launch computer or weapon struct not found)
|
||||
script double TimeToHit(WsfPlatform shooter, WsfWeapon weapon, WsfTrack track)
|
||||
double range = shooter.SlantRangeTo(track);
|
||||
WsfLaunchComputer lcPtr = weapon.LaunchComputer();
|
||||
if (lcPtr.IsValid() &&
|
||||
lcPtr.IsA_TypeOf("WSF_AIR_TO_AIR_LAUNCH_COMPUTER"))
|
||||
{
|
||||
Array<double> arr = lcPtr.LookupResult(track);
|
||||
double rmax = arr[0];
|
||||
double rmaxTOF = arr[1];
|
||||
double rmin = arr[4];
|
||||
double rminTOF = arr[5];
|
||||
if (range >= rmax)
|
||||
{
|
||||
return rmaxTOF;
|
||||
}
|
||||
else if (range<=rmin)
|
||||
{
|
||||
return rminTOF;
|
||||
}
|
||||
else
|
||||
{
|
||||
# in between, interpolate
|
||||
double scale = (range-rmin)/(rmax-rmin);
|
||||
double tof = scale*(rmaxTOF-rminTOF) + rminTOF;
|
||||
return tof;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
struct weaponData = GetWeaponData(weapon.Type());
|
||||
if (weaponData->type == weapon.Type())
|
||||
{
|
||||
if (range > weaponData->rangeMax)
|
||||
{
|
||||
range = weaponData->rangeMax;
|
||||
}
|
||||
else if (range < weaponData->rangeMin)
|
||||
{
|
||||
range = weaponData->rangeMin;
|
||||
}
|
||||
double tof = range / weaponData->averageSpeed;
|
||||
return tof;
|
||||
}
|
||||
else
|
||||
{
|
||||
return -1.0;
|
||||
}
|
||||
}
|
||||
end_script
|
||||
|
||||
# Calculate time for the weapon to fly a given range
|
||||
#if beyond max range: returns time to hit if launched at max range
|
||||
#if before min range: returns time to hit if launched at min range
|
||||
#could return -1 for an invalid max range
|
||||
#(from a launch computer or weapon struct not found)
|
||||
script double TimeToRange(double range, WsfWeapon weapon, WsfTrack track)
|
||||
WsfLaunchComputer lcPtr = weapon.LaunchComputer();
|
||||
if (lcPtr.IsValid() &&
|
||||
lcPtr.IsA_TypeOf("WSF_AIR_TO_AIR_LAUNCH_COMPUTER"))
|
||||
{
|
||||
Array<double> arr = lcPtr.LookupResult(track);
|
||||
double rmax = arr[0];
|
||||
double rmaxTOF = arr[1];
|
||||
double rmin = arr[4];
|
||||
double rminTOF = arr[5];
|
||||
if (range >= rmax)
|
||||
{
|
||||
return rmaxTOF;
|
||||
}
|
||||
else if (range<=rmin)
|
||||
{
|
||||
return rminTOF;
|
||||
}
|
||||
else
|
||||
{
|
||||
# in between, interpolate
|
||||
double scale = (range-rmin)/(rmax-rmin);
|
||||
double tof = scale*(rmaxTOF-rminTOF) + rminTOF;
|
||||
return tof;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
struct weaponData = GetWeaponData(weapon.Type());
|
||||
if (weaponData->type == weapon.Type())
|
||||
{
|
||||
if (range > weaponData->rangeMax)
|
||||
{
|
||||
range = weaponData->rangeMax;
|
||||
}
|
||||
else if (range < weaponData->rangeMin)
|
||||
{
|
||||
range = weaponData->rangeMin;
|
||||
}
|
||||
double tof = range / weaponData->averageSpeed;
|
||||
return tof;
|
||||
}
|
||||
else
|
||||
{
|
||||
return -1.0;
|
||||
}
|
||||
}
|
||||
end_script
|
||||
|
||||
script bool InRangeToFire(WsfPlatform shooter, WsfWeapon weapon, WsfTrack track, double percentRangeMax, double percentRangeMin)
|
||||
|
||||
##do not check this again
|
||||
#if ( ! WeaponCapableAvailableAgainstThreat(weapon, track) )
|
||||
#{
|
||||
# return false;
|
||||
#}
|
||||
|
||||
WsfLaunchComputer lcPtr = weapon.LaunchComputer();
|
||||
|
||||
if (lcPtr.IsValid() &&
|
||||
lcPtr.IsA_TypeOf("WSF_AIR_TO_AIR_LAUNCH_COMPUTER"))
|
||||
{
|
||||
writeln_d(" using air-to-air launch computer");
|
||||
|
||||
# The returned array contains: Rmax, RmaxTOF, Rne, RneTOF, Rmin, RminTOF
|
||||
# in that order. -1.0 means "not valid".
|
||||
|
||||
Array<double> returnedValues = lcPtr.LookupResult(track);
|
||||
|
||||
# Now have to consider whether we have enough information to continue with a weapon shot:
|
||||
double theRmax = returnedValues[0]; #"Rmax";
|
||||
double theRmaxTOF = returnedValues[1]; #"RmaxTOF";
|
||||
double theRne = returnedValues[2]; #"Rne";
|
||||
double theRneTOF = returnedValues[3]; #"RneTOF";
|
||||
double theRmin = returnedValues[4]; #"Rmin";
|
||||
double theRminTOF = returnedValues[5]; #"RminTOF";
|
||||
double range = shooter.GroundRangeTo(track.CurrentLocation());
|
||||
|
||||
# Check for track range less than Rmin * scaleFactor, if not, return.
|
||||
# But do not check for min range constraint at all unless we are likely to be needing it.
|
||||
if (range < 5000)
|
||||
{
|
||||
if (theRmin == -1.0)
|
||||
{
|
||||
writeln_d(" Engagement did not shoot since Rmin was not valid.");
|
||||
return false;
|
||||
}
|
||||
double RminConstraint = theRmin * percentRangeMin;
|
||||
if (range < RminConstraint)
|
||||
{
|
||||
writeln_d(" Engagement did not shoot since inside the k * Rmin constraint distance.");
|
||||
writeln_d(" Range versus Rmin constraint = ", range, ", ", RminConstraint);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
# Check for track range less than Rne, if so, FORCE a weapon fire.
|
||||
bool forceWeaponFire = false;
|
||||
if (range < theRne)
|
||||
{
|
||||
writeln_d(" Engagement is forcing a weapon fire due to inside Rne.");
|
||||
writeln_d(" Range versus Rne constraint = ", range, ", ", theRne);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (forceWeaponFire == false)
|
||||
{
|
||||
######################################TRY THIS######################################
|
||||
WsfPlatform plat = WsfSimulation.FindPlatform( track.TargetName() );
|
||||
if (plat.IsValid() && plat.CategoryMemberOf("fighter"))
|
||||
{
|
||||
#theRmax = theRne;
|
||||
theRmax = (theRmax + theRne)/2.0; #for highly maneuverable fighter targets
|
||||
}
|
||||
####################################END TRY THIS####################################
|
||||
# Check for track range less than k * Rmax, if not, return.
|
||||
if (theRmax == -1.0)
|
||||
{
|
||||
writeln_d(" Engagement did not shoot since Rmax was not valid.");
|
||||
return false;
|
||||
}
|
||||
#double RmaxConstraint = theRmax * DefaultPercentRangeMax;
|
||||
if (range > (theRmax * percentRangeMax))
|
||||
{
|
||||
writeln_d(" Engagement did not shoot since outside the k * Rmax constraint distance.");
|
||||
writeln_d(" Range versus Rmax constraint = ", range, ", ", (theRmax * percentRangeMax));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
writeln_d(" Engagement meets constraints for firing a weapon (continue).");
|
||||
}
|
||||
else if (lcPtr.IsValid() &&
|
||||
lcPtr.IsA_TypeOf("WSF_ATG_LAUNCH_COMPUTER"))
|
||||
{
|
||||
writeln_d(" using air-to-ground launch computer");
|
||||
if (lcPtr.CanIntercept(track))
|
||||
{
|
||||
#intercept works, this weapon is a candidate
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
struct weaponData = GetWeaponData(weapon.Type());
|
||||
|
||||
writeln_d(" using input WeaponData struct values");
|
||||
#check our own ranges & angles --> hacky!!!
|
||||
#extern double EffectiveRange (WsfPlatform, WsfTrack);
|
||||
double effectiveRange = EffectiveRange(shooter, track);
|
||||
double absRelativeBearing = MATH.Fabs(shooter.RelativeBearingTo( track ));
|
||||
|
||||
if ((weaponData->rangeMin * percentRangeMin) > effectiveRange)
|
||||
{
|
||||
writeln_d(" target too close");
|
||||
return false;
|
||||
}
|
||||
if (absRelativeBearing > weaponData->maxFiringAngle)
|
||||
{
|
||||
writeln_d(" target firing angle too large");
|
||||
return false;
|
||||
}
|
||||
if (weaponData->rangeMax * percentRangeMax < effectiveRange)
|
||||
{
|
||||
writeln_d(" target too far away");
|
||||
return false;
|
||||
}
|
||||
|
||||
double range = shooter.SlantRangeTo(track);
|
||||
#double closingSpeed = PLATFORM.ClosingSpeedOf(track);
|
||||
double relBearing = track.RelativeBearingTo(shooter);
|
||||
if (relBearing > 90.0)
|
||||
{
|
||||
if (track.Speed() > weaponData->averageSpeed)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
double speedDiff = weaponData->averageSpeed - track.Speed();
|
||||
if ((range/speedDiff) > weaponData->maxTimeFlight)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
end_script
|
||||
|
||||
Reference in New Issue
Block a user