Files
lab1/processors/timeline_agents/timeline_proc.txt
2025-09-12 15:20:28 +08:00

329 lines
13 KiB
Plaintext

# ****************************************************************************
# 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.
# ****************************************************************************
include_once behavior_timeline_reposition.txt #drag to restart further back on timeline
include_once behavior_timeline_delay.txt #maneuver to delay enemy's engagement
include_once behavior_timeline_engage.txt #intercept/shoot timeline targets
#include_once behavior_timeline_support.txt #fly support role on a timeline (usually behind lead shooter role)
include_once behavior_weapon_support.txt #crank & support weapon
include_once behavior_planned_route.txt #no timeline tasks, just return to route
include_once behavior_evade.txt #evade iminent threats (missiles)
include_once behavior_go_home.txt #disengage, go back to initial location
#include_once behavior_fly_timeline.txt
processor TIMELINE_PROC WSF_QUANTUM_TASKER_PROCESSOR
update_interval 2 sec
script_variables
double mGeesToTurnWith = 6.0; #update this however intelligently you can (based on risk level?)
#double mOffsetAngle = 45.0; #TODO - calculate half sensor angle?
double mOffsetAngle = 30.0; #TODO - calculate half sensor angle?
double mDelaySpeed = 204; #0.6
double mEngageSpeed = 237; #0.8
double mDragSpeed = 309; #1.2
double mDefaultAltitude = 35000 * MATH.M_PER_FT();
#double mDragAltitude = 30000 * MATH.M_PER_FT();
double mDragAltitude = 35000 * MATH.M_PER_FT(); #testing
bool mConsiderPeersWeapons = true; #do not shoot if peers already are
#bool mRequiredToSupportWeapons = true; #TODO - update dynamically somehow?
bool mRequiredToSupportWeapons = true; #TODO - update dynamically somehow?
double DefaultPercentRangeMax = 0.80; # don't launch unless within this percent of Rmax
double DefaultPercentRangeMin = 1.20; # don't launch unless beyond this percent of Rmin
##weapon + threat specific shooting parameters
##specify an Rmax based on which weapon used and which threat engaged
#Map<string, Map<string, double>> WeaponThreatRmaxMap = Map<string, Map<string, double>>();
#WeaponThreatRmaxMap["base_weapon"] = Map<string, double>();
#WeaponThreatRmaxMap["base_weapon"].Set("fighter", 0.80);
bool mDrawSeparationData = true;
string mSeparateSide = "LEFT"; #this is dynamically updated based on engagement axis
#do not edit these:
bool mSeparateEngagement = false;
double mEngagementTrueBearing = -1.0; #valid if in [0,360], update based on engagement axis
WsfDraw mDraw = WsfDraw();
Array<WsfLocalTrack> mTimeLineLocalTargets;
WsfLocalTrack mNearestTimeLineTarget;
Array<WsfLocalTrack> mTimeLineLocalTargetsToShoot = Array<WsfLocalTrack>();
end_script_variables
on_update
#update these if necessary
mSeparateEngagement = false;
mEngagementTrueBearing = -1.0;
#populate shared variables
WsfTask timeline = GetTimeLineTask(PROCESSOR);
mTimeLineLocalTargets = GetTimeLineTaskLocalTargets(PLATFORM, timeline);
Array<double> times = Array<double>();
foreach(WsfLocalTrack target in mTimeLineLocalTargets)
{
double time = TimeToReachPoint(target, PLATFORM.Location(), mGeesToTurnWith);
times.PushBack(time);
}
SortLocalTracksByValue(mTimeLineLocalTargets, times);
mNearestTimeLineTarget = GetNearestTimeLineTaskLocalTarget(PLATFORM, timeline);
if (timeline.IsValid() &&
timeline.AuxDataExists("point_a") &&
timeline.AuxDataExists("point_b") )
{
WsfGeoPoint SeparateA = (WsfGeoPoint)timeline.AuxDataObject("point_a");
WsfGeoPoint SeparateB = (WsfGeoPoint)timeline.AuxDataObject("point_b");
if (SeparateA.IsValid() && SeparateB.IsValid())
{
WsfGeoPoint near;
WsfGeoPoint far;
if (PLATFORM.GroundRangeTo(SeparateA) < PLATFORM.GroundRangeTo(SeparateB))
{
near = SeparateA;
far = SeparateB;
}
else
{
near = SeparateB;
far = SeparateA;
}
mDraw.SetLayer("timeline_proc");
mDraw.SetId("timeline_proc");
mDraw.SetDuration(PROCESSOR.UpdateInterval());
mDraw.SetLineSize(1);
mDraw.SetLineStyle("solid");
Array<WsfTrack> targets = (Array<WsfTrack>)timeline.AuxDataObject("targets");
#check if platform is on the correct side of separation line
WsfGeoPoint clusterMeanLocation = (WsfGeoPoint)timeline.AuxDataObject("cluster_mean");
double refAz = near.TrueBearingTo(far);
#save this engagement axis true bearing!
mSeparateEngagement = true;
mEngagementTrueBearing = MATH.NormalizeAngle0_360(refAz);
double ownAz = near.TrueBearingTo(PLATFORM.Location()) - refAz;
double tgtAz = near.TrueBearingTo(clusterMeanLocation) - refAz;
ownAz = MATH.NormalizeAngleMinus180_180(ownAz);
tgtAz = MATH.NormalizeAngleMinus180_180(tgtAz);
#save off turn direction
if (tgtAz < 0) {
mSeparateSide = "LEFT";
} else {
mSeparateSide = "RIGHT";
}
bool CorrectSide = ((ownAz * tgtAz) > 0);
#draw lines for separation divide
mDraw.SetColor(0.0, 0.0, 0.0); #black
mDraw.BeginLines();
mDraw.Vertex(near);
mDraw.Vertex(far);
mDraw.End();
if (CorrectSide) {
mDraw.SetColor(0.0, 1.0, 1.0); #aqua
} else {
mDraw.SetColor(1.0, 0.0, 0.0); #red
}
#draw line from me to target center of gravity
mDraw.BeginLines();
mDraw.Vertex(PLATFORM);
#mDraw.Vertex(targetCluster.MeanLocation());
mDraw.Vertex(mTimeLineLocalTargets.Front().CurrentLocation());
mDraw.End();
# mDraw.SetEllipseMode("line");
# mDraw.BeginCircle(0.0, 4.0 * MATH.M_PER_NM());
# mDraw.Vertex(PLATFORM);
# mDraw.End();
}
}
#update the "mTimeLineLocalTargetsToShoot" list
mTimeLineLocalTargetsToShoot.Clear();
if (timeline.IsValid())
{
string RISK = timeline.AuxDataString("RISK");
foreach(WsfLocalTrack target in mTimeLineLocalTargets)
{
writeln_d("T=",TIME_NOW," ", PLATFORM.Name(), " checking if shootable: ", target.TargetName());
if (FiredOn(PLATFORM, target, mConsiderPeersWeapons))
{
writeln_d(" NO - already fired on!");
continue;
}
if (mRequiredToSupportWeapons == true && RISK != "HIGH") #can support any shot when risk is high (won't be dragging)
{
double gate = timeline.AuxDataDouble("DOR"); #range (meters)
if (RISK == "MEDIUM")
{
gate = timeline.AuxDataDouble("MAR"); #range (meters)
}
#calculate if we have time or range to support a shot to this target:
###################################################################
###################################################################
###################################################################
#figure out weapon range & time of flight
double weaponMaxRange = 0.0;
WsfWeapon maxRangeWeapon;
for (int i=0; i < PLATFORM.WeaponCount(); i+=1)
{
WsfWeapon weapon = PLATFORM.WeaponEntry(i);
if (WeaponCapableAvailableAgainstThreat(weapon, target))
{
double weaponRange = MaxRange(PLATFORM,weapon,target);
if (weaponRange > weaponMaxRange)
{
weaponMaxRange = weaponRange;
maxRangeWeapon = weapon;
}
}
}
if (!maxRangeWeapon.IsValid())
{
writeln_d(" NO - do not have a weapon for the target");
continue; #no weapon for this target
}
#estimate time before we can shoot
#hypothetical shot
#estimate time cranking (based on weapon travel time)
#does this leave us enough time to turn to drag?
double weaponTOF = TimeToHit(PLATFORM, maxRangeWeapon, target);
if (weaponTOF <= 0)
{
writeln_d(" NO - could not find TOF data for weapon");
#good weapon data no found
continue;
}
double firingRange = DefaultPercentRangeMax * weaponMaxRange;
writeln_d(" INFO - weapon \"", maxRangeWeapon.Name(), "\" firing range = ", firingRange, " TOF = ", weaponTOF);
double targetRange = PLATFORM.GroundRangeTo(target.CurrentLocation());
double rangeToGo = targetRange - firingRange;
double timeTilShot = 0.0;
double range = PLATFORM.GroundRangeTo(mNearestTimeLineTarget.CurrentLocation());
if (rangeToGo > 0)
{
#assume target continues on its current heading
#assume nearest threat closes towards you
#assume we close towards target
double myRelativeBearingToThreat = MATH.Fabs(MATH.NormalizeAngleMinus180_180(PLATFORM.TrueBearingTo(mNearestTimeLineTarget) - PLATFORM.TrueBearingTo(target)));
double targetRelativeBearingToMe = target.RelativeBearingTo(PLATFORM);
double closingSpeedToTarget = PLATFORM.Speed() + MATH.Cos(targetRelativeBearingToMe) * target.Speed();
double closingSpeedOfThreat = mNearestTimeLineTarget.Speed() + MATH.Cos(myRelativeBearingToThreat) * PLATFORM.Speed();
if (closingSpeedToTarget <= 0)
{
writeln_d(" NO - negative closing speed to target with range remaining to shoot");
continue;
}
writeln_d(" INFO - closing to target = ", closingSpeedToTarget, " closing of threat = ", closingSpeedOfThreat);
#subtract off closing distance to nearest threat during the time before shot
timeTilShot = rangeToGo / closingSpeedToTarget;
double temp = range;
range -= (timeTilShot * closingSpeedOfThreat);
writeln_d(" INFO - starting threat range = ", temp, " range after closing to shot loc = ", range);
}
#subtract off closing distance to nearest target during the time of weapon's flight
double closingSpeedOfThreat = (mDelaySpeed * MATH.Cos(mOffsetAngle)) + mNearestTimeLineTarget.Speed();
double temp = range;
range -= (weaponTOF * closingSpeedOfThreat);
writeln_d(" INFO - range at shot = ", temp, " range after supporting shot = ", range);
# #calculate time to turn to drag (after cranking)
# Array<double> vals = Array<double>();
# double turnAngle = 180 - mOffsetAngle;
# TurnAngleTimeAndDistance(turnAngle, mEngageSpeed, mGeesToTurnWith, vals);
# double turnTime = vals[0];
# double distSep = vals[1];
# #subtract off closing distance to nearest target during the time of turning to drag
# range += distSep;
# range -= (turnTime*mNearestTimeLineTarget.Speed());
if (range >= gate)
{
writeln_d(" YES - have time & range to support the shot.");
mTimeLineLocalTargetsToShoot.PushBack(target);
}
else
{
writeln_d(" NO - do not have time & range to support the shot.");
##TODO - should we break here?
## its highly unlikely futher away targets will be shootable
#break;
}
###################################################################
###################################################################
###################################################################
}
else if (mRequiredToSupportWeapons == false || RISK == "HIGH")
{
writeln_d(" YES - risk is high or not required to support.");
#all targets are for shooting (if not already shot on)
mTimeLineLocalTargetsToShoot.PushBack(target);
}
}
}
end_on_update
behavior_tree
selector
behavior_node evade #
behavior_node go_home #
behavior_node timeline_reposition #
#behavior_node timeline_support #TODO - integrate kyle's grinder behavior support stuff
behavior_node timeline_delay #TODO - integrate nick's delay script
behavior_node timeline_engage #TODO - only shoot if there is time to support it
behavior_node weapon_support #
behavior_node planned_route #
end_selector
end_behavior_tree
end_processor