This commit is contained in:
2025-09-12 15:20:28 +08:00
commit 3257a14c32
449 changed files with 388780 additions and 0 deletions

View File

@@ -0,0 +1,894 @@
# ****************************************************************************
# 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.
# ****************************************************************************
#with a commander:
#bids on "zone" and "flank" jobs
#creates "pursue-target" and "pursue-point" jobs
#does not perform any jobs
#without a commander:
#creates "pursue-target" jobs from threats in it's tracklist
#does not perform any jobs
include_once processors/ripr_agents/common/common_platform_script.txt
processor AIFL-thinker WSF_AIFL_PROCESSOR
#script_debug_writes off
#debug
script_debug_writes on
update_interval 3.0 sec
script_variables
bool windowToggle = false;
WsfDraw draw = WsfDraw();
bool mDrawFlankLines = false;
Array<string> mEscortNames = Array<string>();
string mEscortName = "";
double mEscortProtectRange = 1E8;
string mEscortZoneName = "";
// We need to keep references to all the jobs we create so they don't get
// garbage collected when they go out of scope
Map<string, WsfRIPRJob> mTrackJobMap = Map<string, WsfRIPRJob>();
Map<int, WsfGeoPoint> mFlankJobIdToFlankPointMap = Map<int, WsfGeoPoint>();
int maxJobWinnersForPursueTrack = 1;
int maxJobWinnersForWeaponUplink = 1;
double cPursuePointPriority = 0.00001;
double cFlankPointPriority = 25000.0;
double cPursueTargetPriority = 10000.0;
//bool fastAndDirtyBidding = false;
bool fastAndDirtyBidding = true;
double cFlankWeighting = 100000.0;
string cPreferredFlank = "auto"; //or "left" or "right"
int cMaxPeersToComeAlong = 1000;
WsfRIPRJob mCurrentJob;
WsfRIPRJob mLastJob;
double mJobStickiness = 1.0;
Array<string> mZoneNames = Array<string>(); #dlc
bool mUseThreatTypeEngageZones = true;
Map<string, string> ThreatTypeEngageZone = Map<string, string>();
ThreatTypeEngageZone["unknown"] = "";
ThreatTypeEngageZone["uav"] = "";
ThreatTypeEngageZone["sam"] = "";
ThreatTypeEngageZone["ship"] = "";
ThreatTypeEngageZone["awacs"] = "";
ThreatTypeEngageZone["bomber"] = "";
ThreatTypeEngageZone["jammer"] = "";
ThreatTypeEngageZone["fighter"] = "";
ThreatTypeEngageZone["missile"] = "";
ThreatTypeEngageZone["missile_fast"] = "";
##extern string DeterminePlatformCategory(WsfPlatform);
# string catg = DeterminePlatformCategory(target);
# WsfGeoPoint WsfPlatform.Location()
# bool WsfGeoPoint.WithinZone(string aZoneName) #Return true if the point is within the global zone.
end_script_variables
script bool CreateGuidanceJobFor(WsfPlatform activeWeapon, WsfTrack target)
string uniqueName = activeWeapon.Name() + "_uplink";
if ( ! mTrackJobMap.Exists(uniqueName) )
{
double jobPriority = cPursueTargetPriority * 3.0;
WsfRIPRJob temp = WsfRIPRJob.Create( PROCESSOR,
"weapon_uplink",
uniqueName,
jobPriority,
maxJobWinnersForWeaponUplink);
temp.SetData("weaponPlatformIndex", activeWeapon.Index());
temp.SetData("targetPlatformIndex", target.TargetIndex());
temp.SetData("targetTrackName", target.TargetName());
AddJob(temp);
mTrackJobMap.Set(uniqueName, temp);
string NewComment = "AIFL - new job: " + temp.Name() + " - " + temp.GetDescription();
PLATFORM.Comment(NewComment);
//writeln_d("--- ", PLATFORM.Name(), " job change, ADD: ", uniqueName );
writeln_d(NewComment);
return true;
}
else
{
writeln_d("Guidance job already exists: ", uniqueName);
return false;
}
end_script
script void CreateJobsIndependently()
WsfLocalTrackList localTracks = PLATFORM.MasterTrackList();
Map<string, int> updatedTracks = Map<string, int>();
WsfPlatform escortPlatform = WsfSimulation.FindPlatform( mEscortName );
writeln_d(" Flight Lead, Considering Num Tracks: ", localTracks.Count() );
foreach (WsfTrack x in localTracks)
{
//writeln_d(" Considering: ", x.TargetName());
WsfTrackId tid = x.TrackId();
writeln_d(" Considering: ", tid.Name(), ".", tid.Number(), " -> ", x.TargetName());
updatedTracks.Set(x.TargetName(), 0);
// if the track is not a foe or is damaged, we'll ignore it
if (!(x.IsValid())) // || !x.IFF_Foe())// || x.TargetDamaged() > 0)
{
writeln_d("!!! Need to remove track: ", !(x.IsValid()), ", ", !x.IFF_Foe(), ", ", x.TargetDamaged() > 0);
continue;
}
#extern string DetermineTrackCategory(WsfTrack);
string category = DetermineTrackCategory(x);
if (category == "unknown")
{
writeln_d(" - Unknown type: ", x.TargetName(), " - ", x.TargetType() );
continue;
}
if (ThreatTypeEngageZone.Exists(category) && ThreatTypeEngageZone[category].Length()>0)
{
writeln_d(PLATFORM.Name(), " checking target ", x.TargetName(), " in zone ", ThreatTypeEngageZone[category]);
if ( ! x.CurrentLocation().WithinZone(ThreatTypeEngageZone[category]))
{
writeln_d("aifl ", PLATFORM.Name(),", target ", x.TargetName(), " outside of category ", category," zone ", ThreatTypeEngageZone[category], ". not considering for a job.");
continue;
}
else
{
writeln_d("aifl ", PLATFORM.Name(),", target ", x.TargetName(), " inside category ", category," zone ", ThreatTypeEngageZone[category], ". updating job!!!");
}
}
else
{
writeln_d(PLATFORM.Name(), " no zone to check for category ", category);
}
updatedTracks.Set(x.TargetName(), 1);
if ( ! mTrackJobMap.Exists(x.TargetName()) )
{
double jobPriority = cPursueTargetPriority;
if( escortPlatform.IsValid() )
{
jobPriority = cPursueTargetPriority / (1 + x.SlantRangeTo( escortPlatform ) );
}
WsfRIPRJob temp = WsfRIPRJob.Create( PROCESSOR,
"pursue-target",
"pursue-target-" + x.TargetName(),
jobPriority,
maxJobWinnersForPursueTrack);
writeln_d(" - Setting targetTrack, name: ", x.TargetName());
temp.SetData("targetTrack", x);
temp.SetData("targetTrackName", x.TargetName());
writeln_d(" - Adding job");
AddJob(temp);
mTrackJobMap.Set(x.TargetName(), temp);
//writeln_d(" - Creating job pursue-target-", x.TargetName());
writeln_d("--- ", PLATFORM.Name(), " job change, ADD: ", x.TargetName() );
string NewComment = "AIFL - new job: " + temp.Name() + " - " + temp.GetDescription();
PLATFORM.Comment(NewComment);
}
else
{
if( escortPlatform.IsValid() )
{
double jobPriority = cPursueTargetPriority / (1 + x.SlantRangeTo( escortPlatform ) );
WsfRIPRJob updateJob = mTrackJobMap.Get( x.TargetName() );
updateJob.Priority( jobPriority );
}
}
}
Array<WsfRIPRJob> jobs = GetJobs();
foreach (WsfRIPRJob x in jobs)
{
Map<string, Object>tempData = x.GetData();
string name = (string)tempData["targetTrackName"];
if (updatedTracks[name] == 0)
{
if (mTrackJobMap[name].IsValid())
{
//writeln_d(" - Removing non-updated track: ", name);
string temp = write_str("--- ", PLATFORM.Name(), " job change, REMOVE: ", mTrackJobMap[name].Name());
writeln_d(temp);
PLATFORM.Comment(temp);
RemoveJob(mTrackJobMap[name]);
mTrackJobMap.Erase(name);
}
}
}
writeln_d(" - mTrackJobMap.Size() = ", mTrackJobMap.Size());
end_script
query_bid
if (PLATFORM.Subordinates().Count() <= 0)
{
return -MATH.DOUBLE_MAX();
}
//only bid on jobs that air platforms can perform
if (1 != ((int)JOB.GetData("for_air")))
{
writeln_d("aifl, job NOT for air!");
return -MATH.DOUBLE_MAX();
}
Map<string, Object> jobData = JOB.GetData();
//determine the job type & bid appropriately
if( JOB.Name() == "zone" )
{
double maxBid = -MATH.DOUBLE_MAX();
//iterate over all targets in the zone cluster
//find out what my subordinates would bid on each of these targets
//return the best bid from my subordinate on one target as my own bid on the whole cluster of targets
WsfRIPRJob tempJob = WsfRIPRJob.Create(PROCESSOR,"pursue-target","job description",1.0,1);
Array<string> targetNames = (Array<string>)JOB.GetData("ZoneThreatNameArray");
writeln_d("job ", JOB.GetDescription(), " -> number of target names considering: ", targetNames.Size());
foreach(string targetName in targetNames)
{
tempJob.SetData("targetTrackName", targetName);
if (fastAndDirtyBidding)
{
Array<WsfRIPRProcessor> subs = GetRIPRSubordinateProcessors();
if (subs.Size() > 0)
{
WsfRIPRProcessor sub = subs.Get(0);
maxBid = sub.QueryBid(tempJob);
}
break;
}
else
{
//by default this expands through job-pass-through agents to get all bids
double curBid = QuerySubordinatesMaxBid(tempJob);
#######
WsfPlatform target = WsfSimulation.FindPlatform(targetName);
if (target.IsValid())
{
#extern string DeterminePlatformCategory(WsfPlatform);
string category = DeterminePlatformCategory(target);
if (ThreatTypeEngageZone.Exists(category) && ThreatTypeEngageZone[category].Length()>0)
{
if ( ! target.Location().WithinZone(ThreatTypeEngageZone[category]))
{
curBid = -MATH.DOUBLE_MAX();
writeln_d("aifl ", PLATFORM.Name(),", target ", targetName, " outside of category ", category," zone ", ThreatTypeEngageZone[category], ". bid = -DOUBLE_MAX.");
}
else
{
writeln_d("aifl ", PLATFORM.Name(),", target ", targetName, " inside category ", category," zone ", ThreatTypeEngageZone[category], ". bid as usual!!!");
}
}
foreach ( string aZone in mZoneNames)
{
if ( !target.WithinZoneOf(PLATFORM, aZone) )
{
curBid = -MATH.DOUBLE_MAX();
writeln_d("ai flight lead, target ", targetName, " outside of defined zone ", aZone, " curBid from subordinate set to -DOUBLE_MAX.");
}
else
{
writeln_d("ai flight lead, target ", targetName, " inside of defined zone ", aZone, " curBid unchanged.");
}
}
}
#######
# Escorts only bid on targets within a certain radius of the escorted platform
#WsfPlatform escortPlatform = WsfSimulation.FindPlatform(mEscortName);
#if ( escortPlatform.IsValid() && target.IsValid() )
#{
# if ( escortPlatform.SlantRangeTo(target)>mEscortProtectRange )
# {
# curBid = -MATH.DOUBLE_MAX();
# writeln(" Target outside escort protect range" );
# }
#}
#######
# Escorts only bid on targets within a zone on the escorted platform
if ( mEscortZoneName != "" )
{
WsfPlatform escortPlatform = WsfSimulation.FindPlatform(mEscortName);
if ( escortPlatform.IsValid() && target.IsValid() )
{
#writeln_d("$$$3", " ", target.WithinZoneOf(escortPlatform, mEscortZoneName), " ", escortPlatform.SlantRangeTo(target)*(1/MATH.M_PER_NM()));
writeln_d(" slantrange from protected platform ", escortPlatform.Name(), " and target ", target.Name(), " is ", escortPlatform.SlantRangeTo(target)*(1/MATH.M_PER_NM()), " nmi");
if ( !target.WithinZoneOf(escortPlatform, mEscortZoneName) )
{
curBid = -MATH.DOUBLE_MAX();
writeln_d(" target not within protected platform zone");
}
else
{
writeln_d(" target is within protected platform zone");
}
}
}
writeln_d("ai flight lead, max bid on ", targetName," from subordinates: ", curBid);
if (curBid > maxBid)
{
maxBid = curBid;
}
}
}
return maxBid;
}
else if( JOB.Name() == "flank" )
{
//first determine if this squadron is already in a flank position
#string zoneName = (string)jobData.Get("FlankZoneName");
####string FlankZoneName = JOB.Name();
#string FlankZoneName = zoneName;
#WsfPlatform zoneOwner = JOB.GetAssigner().Platform();
#//writeln_d("@@@ num subs: ", PLATFORM.Subordinates().Count());
#Array<string> zoneNames = zoneOwner.ZoneNames();
#foreach( string zName in zoneNames)
#{
# writeln(zoneOwner.Name(), " has zone: ", zName);
#}
#### put this part in the script that performs the job, not bids on the job
#foreach( WsfPlatform sub in PLATFORM.Subordinates() )
#{
# if( sub.WithinZoneOf( zoneOwner, FlankZoneName ) )
# {
# ### writeln_d( "@@@ aifl subordinate ", sub.Name(), " inside flank zone: ", FlankZoneName );
# ### //mark job as complete (progress == 1.0)
# ### JOB.SetProgress( PROCESSOR, 1.0 );
# return -MATH.DOUBLE_MAX();
# }
#}
WsfGeoPoint zonePoint = (WsfGeoPoint)JOB.GetData("ZonePoint");
double zoneBearing = (double) JOB.GetData("ZoneBearing");
WsfZone flankZone = (WsfZone) JOB.GetData("FlankZone");
if (mDrawFlankLines)
{
//writeln("flank zone point: ", zonePoint.ToString(), ", bearing (rad): ", zoneBearing*MATH.RAD_PER_DEG());
flankZone.DebugDrawZone(zonePoint, zoneBearing*MATH.RAD_PER_DEG());
}
#foreach( WsfPlatform sub in PLATFORM.Subordinates() )
#{
# if (flankZone.PointIsInside(sub.Location(), zonePoint, zoneBearing*MATH.RAD_PER_DEG(), 0.0))
# {
# #mark the job as complete elsewhere, probably where it would be performed
# return -MATH.DOUBLE_MAX();
# }
#}
//determine which side to flank on, based on subordinate that is closest to flank point
//find closest subordinate & then calculate relative geometry
#writeln_d("@@@ aiFL - commander flank job ", JOB.GetId() ," for zone: ", zoneName );
WsfGeoPoint fPoint = (WsfGeoPoint)jobData.Get("ZonePoint");
double flankDistance = (double)jobData.Get( "FlankDistance" );
WsfPlatform ClosestFlanker;
###writeln("cluster: bearing=", clusterBearingTrue, ", distance=", flankDistance);
if( fPoint.IsValid() )
{
if (mDrawFlankLines) //draw flank point of interest (target we are flanking), white dot
{
draw.BeginPoints();
draw.SetColor(1.0, 1.0, 1.0);
draw.Vertex(fPoint);
draw.End();
}
#writeln("cluster ZonePoint is valid!");
double MinRange = MATH.DOUBLE_MAX();
double NumSubordinates = (double)(PLATFORM.Subordinates().Count());
foreach (WsfPlatform sub in PLATFORM.Subordinates())
{
double range = sub.SlantRangeTo( fPoint );
#writeln("sub ", sub.Name(), " slant range to cluster point: ", range);
if( range < MinRange )
{
MinRange = range;
ClosestFlanker = sub;
}
}
bool clusterBearingValid = (bool)jobData.Get( "ZoneBearingValid" );
double tempBearing = (double)jobData.Get( "ZoneBearing" );
###double clusterBearingTrue = MATH.NormalizeAngle0_360( (double)jobData.Get( "ZoneBearing" ) );
double clusterBearingTrue = 0.0;
if (clusterBearingValid)
{
#writeln("cluster bearing valid, bearing: ", tempBearing);
### cluster heading is with reference to east (instead of north), so subtract 90 degrees
#clusterBearingTrue = MATH.NormalizeAngle0_360( tempBearing - 90.0 );
clusterBearingTrue = MATH.NormalizeAngle0_360( tempBearing );
WsfGeoPoint bPoint = WsfGeoPoint(fPoint);
bPoint.Extrapolate( clusterBearingTrue, flankDistance );
if (mDrawFlankLines) //draw red-orange line to represent heading of target's flight
{
draw.BeginLines();
draw.SetColor(1.0, 0.3, 0.1);
draw.Vertex(fPoint);
draw.Vertex(bPoint);
draw.End();
}
}
else
{
writeln("cluster bearing invalid, bearing: ", tempBearing);
//assume cluster is flying straight at me, flank to side I'm already oriented towards
clusterBearingTrue = ClosestFlanker.TrueBearingTo( fPoint ) - 180.0;
}
//don't need to normalize it here, the next line catches it
double angle = ClosestFlanker.TrueBearingTo( fPoint ) - 180.0;
double relativeFlankBearing = MATH.NormalizeAngle0_360( angle - clusterBearingTrue );
double flankAngle = 90.0;
if( relativeFlankBearing > 180.0 )
{
flankAngle = 270.0;
}
if (cPreferredFlank == "left")
{
flankAngle = 90.0;
}
else if(cPreferredFlank == "right")
{
flankAngle = 270.0;
}
double flankBearing = MATH.NormalizeAngle0_360( clusterBearingTrue + flankAngle );
#writeln("angle: ", angle, ", relativeFlankBearing: ", relativeFlankBearing, ", cluster: bearing=", flankBearing, ", minRange=", MinRange);
WsfGeoPoint ePoint = WsfGeoPoint(fPoint);
ePoint.Extrapolate( flankBearing, flankDistance );
if (mDrawFlankLines) //draw green line to the flank point, and to the side we are flying towards
{
draw.BeginLines();
draw.SetColor(0.1, 1.0, 0.4);
draw.Vertex(fPoint);
draw.Vertex(ePoint);
draw.Vertex(fPoint);
draw.Vertex(ClosestFlanker);
draw.End();
}
//save off the flank point, in case we win this job
mFlankJobIdToFlankPointMap.Set( JOB.GetId(), ePoint );
//find the range to the place we will fly so as to flank the target
MinRange = ClosestFlanker.SlantRangeTo( ePoint );
###double JobBidValue = NumSubordinates / MATH.Sqrt(MinRange);
double JobBidValue = NumSubordinates * flankDistance / MinRange;
JobBidValue = JobBidValue + cFlankWeighting;
#writeln_d("!!! Bid for flanking job: ", JOB.Name(), ", bid: ", JobBidValue );
return JobBidValue;
}
else
{
writeln_d("!!! Invalid point in flank job");
}
}
//can't make a bid, return max negative
return -MATH.DOUBLE_MAX();
end_query_bid
script void CreateJobsFromCommander()
//writeln_d("!!! Creating jobs from commanders jobs!" );
Array<WsfRIPRJob> jobs = GetRIPRCommanderProcessor().GetJobs();
writeln_d(PLATFORM.Name(), " jobs.Size() = ", jobs.Size());
foreach (WsfRIPRJob aJob in jobs)
{
if( aJob.IsValid() )
{
double bidValue = QueryBid(aJob);
writeln_d(PLATFORM.Name(), " bid on job ", aJob.GetDescription(), " == ", bidValue, ", priority = ", aJob.GetPriority());
if (bidValue == -MATH.DOUBLE_MAX())
{
if (aJob.GetProgress( PROCESSOR) < 1.0)
{
aJob.UnbidJob( PROCESSOR );
}
}
else
{
aJob.BidJob( PROCESSOR, bidValue );
}
# aJob.SetProgress( PROCESSOR, 1.0 );
# GetRIPRCommanderProcessor().RemoveJob(aJob)
}
}
// now check the board to see what we've won!
mCurrentJob = GetRIPRCommanderProcessor().GetJobFor(TIME_NOW, PROCESSOR);
if( mCurrentJob.IsValid() )
{
if( (!mLastJob.IsValid()) || mCurrentJob.GetId() != mLastJob.GetId() )
{
string NewComment = "AIFL - Won new job: " + mCurrentJob.Name() + " - " + mCurrentJob.GetDescription();
PLATFORM.Comment(NewComment);
}
mLastJob = mCurrentJob;
if( mCurrentJob.Name() == "zone" )
{
Map<string, int> updatedTracks = Map<string, int>();
Array<string> targetNames = (Array<string>)mCurrentJob.GetData("ZoneThreatNameArray");
writeln_d(PLATFORM.Name(), " targetNames.Size() = ", targetNames.Size());
WsfGeoPoint point;
#WsfCluster cluster = WsfCluster.Create();
foreach(string targetName in targetNames)
{
WsfPlatform target = WsfSimulation.FindPlatform(targetName);
if (target.IsValid())
{
#extern string DeterminePlatformCategory(WsfPlatform);
string category = DeterminePlatformCategory(target);
if (ThreatTypeEngageZone.Exists(category) && ThreatTypeEngageZone[category].Length()>0)
{
if ( ! target.Location().WithinZone(ThreatTypeEngageZone[category]))
{
#make sure no job exists for him
continue;
}
}
updatedTracks.Set( targetName, 1 );
#cluster.Add(target.MakeTrack());
#save any target's location, to send along extra subordinates later
point = target.Location();
if (!mTrackJobMap.Exists(targetName))
{
WsfRIPRJob temp = WsfRIPRJob.Create( PROCESSOR,
"pursue-target",
"pursue-target-" + targetName,
cPursueTargetPriority,
maxJobWinnersForPursueTrack);
temp.SetData("targetTrackName", targetName);
AddJob(temp);
mTrackJobMap.Set(targetName, temp);
writeln_d("--- ", PLATFORM.Name(), " job change, ADD: ", targetName);
}
}
}
Array<WsfRIPRProcessor> subs = GetRIPRSubordinateProcessors();
int NumSubordinates = subs.Size();
string zName = (string)mCurrentJob.GetData("ZoneName");
//create a pursue-point job that allows for enough winners to send the whole squadron
//this is useful in case some subordinates don't have a track for some of the threats
//or if there are less threats than there are subordinates, so the whole squadron will be sent
//writeln_d("!!! Not enough tracks inside zone for all subordinates! Using default zone point too!" );
#if (cluster.Count()>0)
if (point.IsValid())
{
updatedTracks.Set( zName, 1 );
#WsfGeoPoint point = (WsfGeoPoint)mCurrentJob.GetData("ZonePoint");
#WsfGeoPoint realPoint = cluster.MeanLocation();
if( ! mTrackJobMap.Exists( zName ) )
{
if (NumSubordinates > cMaxPeersToComeAlong)
{
NumSubordinates = cMaxPeersToComeAlong;
}
if (NumSubordinates > 0)
{
//set max job winners to number of subordinates (so all can proceed into zone)
WsfRIPRJob temp = WsfRIPRJob.Create( PROCESSOR,
"pursue-point",
"pursue-point-" + zName,
cPursuePointPriority,
NumSubordinates);
temp.SetData( "targetTrackName", zName ); //hack for now, so other code here works
temp.SetData( "targetPoint", point );
#temp.SetData( "targetPoint", realPoint );
#writeln(PLATFORM.Name(), " using cluster point: ", realPoint.ToString());
AddJob(temp);
mTrackJobMap.Set( zName, temp );
writeln_d("--- ", PLATFORM.Name(), " job change, ADD: ", zName );
}
}
else
{
//update the job?
mTrackJobMap.Get( zName ).SetData( "targetPoint" , point );
#mTrackJobMap.Get( zName ).SetData( "targetPoint" , realPoint );
}
}
else
{
writeln(PLATFORM.Name(), " has no valid targets, not creating pursue-point job either!");
}
Array<WsfRIPRJob> jobs = GetJobs();
foreach (WsfRIPRJob x in jobs)
{
string name = (string)x.GetData("targetTrackName");
if (updatedTracks.Get(name) != 1)
{
writeln_d("--- ", PLATFORM.Name(), " job change, REMOVE: ", name);
RemoveJob(mTrackJobMap[name]);
mTrackJobMap.Erase(name);
}
}
#writeln(PLATFORM.Name(), " final line in zone job processing!");
}
else if( mCurrentJob.Name() == "flank" )
{
writeln_d(" Flight Lead, Won job for flank ", mCurrentJob.Name() );
#//see if any subordinates are in the flank zone, if they are... flanking is done
####string FlankZoneName = mCurrentJob.Name();
#string FlankZoneName = (string)(mCurrentJob.GetData().Get("FlankZoneName"));
#writeln_d( "@@@ aifl flank zone: ", FlankZoneName );
#WsfPlatform zoneOwner = mCurrentJob.GetAssigner().Platform();
#writeln("@@@ aifl flank zone owner: ", zoneOwner.Name());
WsfGeoPoint zonePoint = (WsfGeoPoint)mCurrentJob.GetData("ZonePoint");
double zoneBearing = (double) mCurrentJob.GetData("ZoneBearing");
WsfZone flankZone = (WsfZone) mCurrentJob.GetData("FlankZone");
foreach( WsfPlatform sub in PLATFORM.Subordinates() )
{
if (flankZone.PointIsInside(sub.Location(), zonePoint, zoneBearing*MATH.RAD_PER_DEG(), 0.0))
{
writeln_d( "@@@ aifl subordinate ", sub.Name(), " inside flank zone!");
mCurrentJob.SetProgress( PROCESSOR, 1.0 ); #mark the job as complete
return;
}
}
WsfGeoPoint point = mFlankJobIdToFlankPointMap.Get( mCurrentJob.GetId() );
int NumSubordinates = PLATFORM.Subordinates().Count();
#foreach( WsfPlatform sub in PLATFORM.Subordinates() )
#{
# if( sub.GroundRangeTo(point) < 1500 )
# {
# writeln_d( "@@@ aifl subordinate ", sub.Name(), " close to flank point!");
# mCurrentJob.SetProgress( PROCESSOR, 1.0 );
# #mCurrentJob.UnbidJob( PROCESSOR );
# return;
# }
# else
# {
# writeln_d( "@@@ aifl subordinate ", sub.Name(), " NOT close to flank point!");
# }
#}
##string zName = (string)mCurrentJob.GetData("ZoneName");
string zName = (string)mCurrentJob.GetData("FlankZoneName");
//if flank job doesn't exist yet, create it
if( ! mTrackJobMap.Exists( zName ) )
{
if (NumSubordinates > cMaxPeersToComeAlong)
{
NumSubordinates = cMaxPeersToComeAlong;
}
if (NumSubordinates > 0)
{
//set max job winners to number of subordinates (so all can proceed into zone)
WsfRIPRJob temp = WsfRIPRJob.Create( PROCESSOR,
"pursue-point",
"pursue-point-" + zName,
cFlankPointPriority,
NumSubordinates);
temp.SetData( "targetTrackName", zName ); //hack for now, so other code here works
temp.SetData( "targetPoint", point );
AddJob(temp);
mTrackJobMap.Set( zName, temp );
writeln_d("--- ", PLATFORM.Name(), " job change, ADD: ", zName );
}
}
else
{
mTrackJobMap.Get( zName ).SetData( "targetPoint" , point );
writeln_d(" aiFL - updated flank pursue-point job ", zName, ", ( ", point.Latitude(), ", ", point.Longitude(), " )" );
}
//remove all jobs that aren't involved with flanking
Array<WsfRIPRJob> jobs = GetJobs();
foreach (WsfRIPRJob x in jobs)
{
Map<string, Object>jobData = x.GetData();
string name = (string)jobData.Get("targetTrackName");
if ( name != zName )
{
//writeln_d(" - Removing job not related to flanking, target: ", name);
writeln_d("--- ", PLATFORM.Name(), " job change, REMOVE: ", name);
RemoveJob(mTrackJobMap[name]);
mTrackJobMap.Erase(name);
}
}
}
else
{
writeln("ERROR: UNRECOGNIZED JOB TYPE: ", mCurrentJob.Name(), " !!!");
}
}
else
{
writeln_d("--- mCurrentJob NOT VALID!!!!! Removing all my aifl jobs.");
Array<WsfRIPRJob> jobs = GetJobs();
foreach (WsfRIPRJob x in jobs)
{
Map<string, Object>jobData = x.GetData();
string name = (string)jobData.Get("targetTrackName");
writeln_d("--- ", PLATFORM.Name(), " job change, REMOVE: ", name);
RemoveJob(mTrackJobMap[name]);
mTrackJobMap.Erase(name);
}
}
#writeln(PLATFORM.Name(), " final line in CreateJobsFromCommander method!");
end_script
on_initialize2
draw.SetPointSize(5);
draw.SetDuration(PROCESSOR.UpdateInterval()); //try it here, after the processor is setup
end_on_initialize2
on_initialize
SetJobAllocationMode(0); #spread (Default -- every subordinate is given the highest priority job that he has the highest bid for. If there are more subordinates than jobs, some subordinates will be left idle. )
#SetJobAllocationMode(1); #greedy (Every subordinate is given the job he bids highest on with the highest priority, without regard for the maximum number of winners that the job allows. Every subordinate will get a job. (Disregards Job Stickiness value) )
#SetJobAllocationMode(2); #coverthengreedy (Like spread, but remaining unassigned subordinates will be given the job they bid highest on with the highest priority, even if that results in the job having more winners that the maximum specified. )
#SetJobAllocationMode(3); #coverthenspread (Like spread, but remaining unassigned subordinates will be spread out over the pool of jobs with no job getting two extra winners before all jobs have one extra winner. )
#SetJobAllocationMode(4); #strictpriority (Like spread, awards the highest priority job to the highest bidder regardless of the bidder's highest overall bid. )
#SetJobStickiness(mJobStickiness);
Array<WsfZone> zoneList = PLATFORM.Zones();
foreach (WsfZone z in zoneList)
{
mZoneNames.PushBack(z.Name());
}
foreach( string x in mZoneNames )
{
writeln_d("~~~ Flight Lead ", PLATFORM.Name(), " now monitoring retrieved zone: ", x );
}
if( mZoneNames.Size() == 0 )
{
writeln_d( "~~~ Flight Lead ", PLATFORM.Name(), " has no zone defined." );
}
end_on_initialize
on_update
/*
if (windowToggle)
{
SetJobWindowOpen(true);
SetBidWindowOpen(false);
windowToggle = false;
}
else
{
SetJobWindowOpen(false);
SetBidWindowOpen(true);
windowToggle = true;
}
*/
#######
mEscortName = "";
if ( !mEscortNames.Empty() )
{
foreach ( string sEscortName in mEscortNames )
{
if ( WsfSimulation.FindPlatform(sEscortName).IsValid() )
{
mEscortName = sEscortName;
#writeln("$$$2", " ", PLATFORM.Name(), " ", mEscortName);
break;
}
#else
#{
# mEscortNames.Erase(mEscortName);
#}
}
}
if ( mEscortName != "" ) writeln_d("~~~ Flight Lead ", PLATFORM.Name(), " is assigned to escort ", mEscortName);
double duration = 0.0;
double lStartTime = GetWallClockTime();
writeln_d("--- aifl_update Platform: ", PLATFORM.Name(), ", Time: ", TIME_NOW);
if (GetRIPRCommanderProcessor().IsValid())
{
writeln_d("...CreateJobsFromCommander()");
CreateJobsFromCommander();
}
else
{
writeln_d("...CreateJobsIndependently()");
CreateJobsIndependently();
}
duration = GetWallClockTime() - lStartTime;
writeln_d("--- on_update Platform: ", PLATFORM.Name(), ", Process Time: ", duration);
end_on_update
end_processor