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

View File

@@ -0,0 +1,281 @@
# ****************************************************************************
# 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 processors/ripr_agents/common/common_platform_script.txt
include_once processors/ripr_agents/aiai/behavior_bid_on_jobs.txt
include_once processors/ripr_agents/aifl/behavior_interpret_zone_jobs.txt
include_once processors/ripr_agents/aifl/behavior_create_target_jobs_self.txt
include_once processors/ripr_agents/aifl/behavior_interpret_flank_jobs.txt
include_once processors/ripr_agents/aifl/behavior_create_point_job.txt
include_once processors/ripr_agents/aifl/behavior_create_cap-routes.txt
#include_once processors/ripr_agents/aifl/behavior_create_sar_jobs.txt
include_once processors/ripr_agents/aifl/behavior_manage-pincer.txt
include_once processors/ripr_agents/aifl/behavior_manage-uplinks.txt
include_once processors/ripr_agents/aiai/behavior_debug_job_board.txt
include_once processors/ripr_agents/aifl/behavior_toggle_windows.txt
processor AIFL-thinker WSF_RIPR_PROCESSOR
script_debug_writes off
update_interval 3.0 sec
script_variables
bool windowToggle = false;
// We need to keep references to all the jobs we create so they don't get
// garbage collected when they go out of scope
int maxJobWinnersForWeaponUplink = 1;
double cPursuePointPriority = 0.00001;
double cFlankPointPriority = 25000.0;
double cPursueTargetPriority = 10000.0;
double cPincerPriority = 10000.0;
WsfRIPRJob mCurrentJob;
WsfRIPRJob mLastJob;
double mJobStickiness = 1.25;
int mJobAllocationMode = 3;
bool mFastAndDirtyBidding = false;
Map<string, string> ThreatTypeEngageZone = Map<string, string>();
string cPreferredFlank = "auto"; //or "left" or "right"
Map<int, WsfGeoPoint> mFlankJobIdToFlankPointMap = Map<int, WsfGeoPoint>();
end_script_variables
behavior_tree
behavior_node bid_on_jobs
behavior_node toggle_windows
selector
behavior_node interpret_zone_jobs
behavior_node create_target_jobs_self
end_selector
behavior_node create_point_job
behavior_node create_cap-routes
#behavior_node create_sar_jobs
#behavior_node interpret_flank_jobs
behavior_node manage-uplinks
behavior_node manage-pincer
#behavior_node debug_job_board
end_behavior_tree
##deprecated
#query_bid
# return -MATH.DOUBLE_MAX();
#end_query_bid
on_initialize
# job allocation mode enumerations:
# 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. )
# 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) )
# 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. )
# 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. )
# 4 --> strictpriority (Like spread, awards the highest priority job to the highest bidder regardless of the bidder's highest overall bid. )
PROCESSOR.SetJobAllocationMode(mJobAllocationMode);
PROCESSOR.SetJobStickiness(mJobStickiness);
end_on_initialize
query_bid_type zone
if (PLATFORM.Subordinates().Count() <= 0 || PROCESSOR.GetRIPRSubordinateProcessors().Size() <= 0)
{
writeln_d("behavior interpret_zone_jobs: not enough subordinates");
return -MATH.DOUBLE_MAX();
}
########################################################################
## bid on the cluster is based on subordinate bids on their members
########################################################################
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());
double maxBid = -MATH.DOUBLE_MAX();
foreach(string targetName in targetNames)
{
bool inZone = true;
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]))
{
inZone = false;
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 PLATFORM.ZoneNames())
{
if ( !target.WithinZoneOf(PLATFORM, aZone) )
{
inZone = false;
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.");
}
}
}
if (inZone == true)
{
tempJob.SetData("targetTrackName", targetName);
if (mFastAndDirtyBidding)
{
maxBid = PROCESSOR.GetRIPRSubordinateProcessors().Get(0).QueryBid(tempJob);
writeln_d("ai flight lead, fast dirty bid on ", JOB.Description()," = ", maxBid);
break;
}
else
{
//by default this expands through job-pass-through agents to get all bids
double curBid = PROCESSOR.QuerySubordinatesMaxBid(tempJob);
writeln_d("ai flight lead, max bid on ", targetName," from subordinates: ", curBid);
if (curBid > maxBid)
{
maxBid = curBid;
}
}
}
else
{
maxBid = -MATH.DOUBLE_MAX();
}
}
return maxBid;
end_query_bid_type
query_bid_type flank
if (PLATFORM.Subordinates().Count() <= 0)
{
writeln_d("no subordinates to carry out flank job");
return -MATH.DOUBLE_MAX();
}
WsfGeoPoint zonePoint = (WsfGeoPoint)JOB.GetData("ZonePoint");
double zoneBearing = (double) JOB.GetData("ZoneBearing");
WsfZone flankZone = (WsfZone) JOB.GetData("FlankZone");
double flankDist = (double) JOB.GetData("FlankDistance");
bool bearingValid = (bool) JOB.GetData("ZoneBearingValid");
//determine which side to flank on, based on subordinate that is closest to flank point
//find closest subordinate & then calculate relative geometry
WsfPlatform ClosestFlanker;
if( zonePoint.IsValid() )
{
double MinRange = MATH.DOUBLE_MAX();
double NumSubordinates = (double)(PLATFORM.Subordinates().Count());
foreach (WsfPlatform sub in PLATFORM.Subordinates())
{
double range = sub.SlantRangeTo( zonePoint );
if( range < MinRange )
{
MinRange = range;
ClosestFlanker = sub;
}
}
if (!ClosestFlanker.IsValid())
{
writeln_d("!!! no valid subordinates to compare to flank point!");
return -MATH.DOUBLE_MAX();
}
double clusterBearingTrue = 0.0;
if (bearingValid)
{
//cluster heading is with reference to east (instead of north), so subtract 90 degrees
#clusterBearingTrue = MATH.NormalizeAngle0_360( zoneBearing - 90.0 );
clusterBearingTrue = MATH.NormalizeAngle0_360( zoneBearing );
}
else
{
writeln_d("cluster bearing invalid, bearing: ", zoneBearing);
//assume cluster is flying straight at me, flank to side I'm already oriented towards
clusterBearingTrue = ClosestFlanker.TrueBearingTo( zonePoint ) - 180.0;
}
//don't need to normalize it here, the next line catches it
double angle = ClosestFlanker.TrueBearingTo( zonePoint ) - 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 );
WsfGeoPoint ePoint = WsfGeoPoint(zonePoint);
ePoint.Extrapolate( flankBearing, flankDist );
//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 = 100000 + NumSubordinates * flankDist / MinRange;
return JobBidValue;
}
else
{
writeln_d("!!! Invalid point in flank job");
return -MATH.DOUBLE_MAX();
}
end_query_bid_type
on_update
writeln_d("--- aifl_update Platform: ", PLATFORM.Name(), ", Time: ", TIME_NOW);
WsfRIPRProcessor commander = PROCESSOR.GetRIPRCommanderProcessor();
if (commander.IsValid())
{
// print any job changes, so check the board to see what we've won
mCurrentJob = commander.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;
}
}
end_on_update
end_processor

View File

@@ -0,0 +1,33 @@
# ****************************************************************************
# 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.
# ****************************************************************************
behavior adjust_priority_for_escort
precondition
return true;
end_precondition
execute
#extern string mEscortName;
WsfPlatform escortPlatform = WsfSimulation.FindPlatform( mEscortName );
if( escortPlatform.IsValid() )
{
#extern double cPursueTargetPriority;
Array<WsfRIPRJob> jobs = PROCESSOR.GetJobs();
foreach (WsfRIPRJob x in jobs)
{
double jobPriority = cPursueTargetPriority / (1 + x.SlantRangeTo( escortPlatform ) );
x.Priority( jobPriority );
}
}
end_execute
end_behavior

View File

@@ -0,0 +1,66 @@
# ****************************************************************************
# 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.
# ****************************************************************************
behavior create_cap-routes
script_debug_writes off
script_variables
Array<Map<string, Object>> mCapRoutes = Array<Map<string, Object>>();
#mCapRoutes[0] = Map<string, Object>();
#mCapRoutes[0].Set("route name", "GOALIE_CAP_CCW_ORBIT");
#mCapRoutes[0].Set("location", WsfGeoPoint.Construct(12.60313, 117.37702, 40000));
#mCapRoutes[0].Set("heading", 140.0);
#mCapRoutes[0].Set("priority", 1000.0);
#mCapRoutes[0].Set("max winners", 1);
#mCapRoutes[0].Set("fez_zone", "lane_2");
end_script_variables
on_init
if (PROCESSOR.IsA_TypeOf("WSF_RIPR_PROCESSOR"))
{
foreach( Map<string, Object> map in mCapRoutes)
{
//create a "cap-route" job
string routeName = (string) map["route name"];
WsfGeoPoint location = (WsfGeoPoint)map["location"];
double heading = (double) map["heading"];
double priority = (double) map["priority"];
int maxWinners = (int) map["max winners"];
string zoneName = (string) map["fez_zone"];
string unique_desc = write_str("cap-route_", routeName, "_", location.Latitude(), "_", location.Longitude());
writeln_d("CREATING CAP ROUTE JOB: ", unique_desc);
WsfRIPRJob temp = WsfRIPRJob.Create( ((WsfRIPRProcessor)PROCESSOR), "cap-route", unique_desc, priority, maxWinners );
temp.SetData( "location", location );
temp.SetData( "heading", heading );
temp.SetData( "route name", routeName );
temp.SetData( "for_air", 1 );
temp.SetData( "fez_zone", zoneName);
((WsfRIPRProcessor)PROCESSOR).AddJob(temp);
}
}
end_on_init
precondition
writeln_d("precondition create_cap-routes");
if (!PROCESSOR.IsA_TypeOf("WSF_RIPR_PROCESSOR"))
{
return Failure("behavior not attached to a RIPR processor!");
} //((WsfRIPRProcessor)PROCESSOR)
return false;
end_precondition
execute
writeln_d("executing create_cap-routes");
end_execute
end_behavior

View File

@@ -0,0 +1,125 @@
# ****************************************************************************
# 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.
# ****************************************************************************
behavior create_point_job
script_debug_writes off
script_variables
int maxJobWinnersForPursueTrack = 1;
string pointJobName = "-1";
end_script_variables
on_init
//nothing here yet
end_on_init
precondition
writeln_d("precondition create_point_job");
if (!PROCESSOR.IsA_TypeOf("WSF_RIPR_PROCESSOR"))
{
return Failure("behavior not attached to a RIPR processor!");
}
WsfRIPRProcessor commander = ((WsfRIPRProcessor)PROCESSOR).GetRIPRCommanderProcessor();
if (!commander.IsValid())
{
return Failure("Agent does not have a commander to get jobs from!");
}
int NumSubordinates = ((WsfRIPRProcessor)PROCESSOR).GetRIPRSubordinateProcessors().Size();
if (NumSubordinates <= 0)
{
return Failure("Agent has no subordinates to send to a point!");
}
return true;
end_precondition
execute
writeln_d("executing create_point_job");
// now check the board to see what we've won!
WsfRIPRJob currentJob = ((WsfRIPRProcessor)PROCESSOR).GetRIPRCommanderProcessor().GetJobFor(TIME_NOW, ((WsfRIPRProcessor)PROCESSOR));
if( currentJob.IsValid() && currentJob.Name() == "zone" )
{
//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
string zName = (string)currentJob.GetData("ZoneName");
WsfGeoPoint point = (WsfGeoPoint)currentJob.GetData("ZonePoint");
if (point.IsValid())
{
string newPointJobName = "pursue-point-" + zName;
WsfRIPRJob pointJob = ((WsfRIPRProcessor)PROCESSOR).GetJobByData("pointName", newPointJobName);
if( !pointJob.IsValid() )
{
extern double cPursuePointPriority;
//set max job winners to number of subordinates (so all can proceed into zone)
int NumSubordinates = ((WsfRIPRProcessor)PROCESSOR).GetRIPRSubordinateProcessors().Size();
pointJob = WsfRIPRJob.Create( ((WsfRIPRProcessor)PROCESSOR),
"pursue-point",
newPointJobName,
cPursuePointPriority,
NumSubordinates);
pointJob.SetData( "targetTrackName", zName ); //hack for now, so other code here works
pointJob.SetData( "targetPoint", point );
pointJob.SetData( "pointName", newPointJobName );
((WsfRIPRProcessor)PROCESSOR).AddJob(pointJob);
writeln_d("--- ", PLATFORM.Name(), " job change, ADD: pursue-point-", zName );
}
else
{
//update the job?
pointJob.SetData( "targetPoint" , point );
pointJob.SetData( "targetTrackName" , zName );
}
if (pointJobName != newPointJobName)
{
//remove old point job
WsfRIPRJob prevPointJob = ((WsfRIPRProcessor)PROCESSOR).GetJobByData("pointName", pointJobName);
if (prevPointJob.IsValid())
{
writeln_d("--- ", PLATFORM.Name(), " job change, REMOVE: ", pointJobName);
((WsfRIPRProcessor)PROCESSOR).RemoveJob(prevPointJob);
}
pointJobName = newPointJobName;
}
return; //step out of the behavior at this point, otherwise remove the job
}
else
{
writeln(PLATFORM.Name(), " has no valid zone point, not creating pursue-point job!");
}
}
else
{
writeln_d(PLATFORM.Name(), " does not have a valid zone job for a point!");
//remove old point job
WsfRIPRJob prevPointJob = ((WsfRIPRProcessor)PROCESSOR).GetJobByData("pointName", pointJobName);
writeln_d("--- ", PLATFORM.Name(), " job change, REMOVE: ", pointJobName);
pointJobName = "-1";
if (prevPointJob.IsValid())
{
writeln_d("--- ", PLATFORM.Name(), " job change, REMOVE: ", pointJobName);
((WsfRIPRProcessor)PROCESSOR).RemoveJob(prevPointJob);
}
}
end_execute
end_behavior

View File

@@ -0,0 +1,127 @@
# ****************************************************************************
# 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.
# ****************************************************************************
behavior create_target_jobs_self
script_debug_writes off
script_variables
WsfRIPRJob mMyJob;
int maxJobWinnersForPursueTrack = 1;
end_script_variables
on_init
end_on_init
precondition
writeln_d("precondition create_target_jobs_self");
writeln_d("precondition radar-control");
if (!PROCESSOR.IsA_TypeOf("WSF_RIPR_PROCESSOR"))
{
return Failure("behavior not attached to a RIPR processor!");
}
//this behavior should probably always run, because it
//removes stale jobs from old tracks that have gone away
return true;
end_precondition
execute
writeln_d("executing create_target_jobs_self");
WsfLocalTrackList localTracks = PLATFORM.MasterTrackList();
Map<string, int> updatedTracks = Map<string, int>();
writeln_d(" Flight Lead, Considering Num Tracks: ", localTracks.Count() );
foreach (WsfTrack x in localTracks)
{
// if the track is not a foe or is damaged, we'll ignore it
if (!(x.IsValid()))
{
writeln_d("!!! Need to remove track: not valid!");
continue;
}
WsfTrackId tid = x.TrackId();
writeln_d(" Considering: ", tid.Name(), ".", tid.Number(), " -> ", x.TargetName());
updatedTracks.Set(x.TargetName(), 0);
if (x.IFF_Friend())
{
writeln_d("!!! Need to remove track: IFF FRIEND!");
continue;
}
if (x.SideValid() && x.Side() == PLATFORM.Side())
{
writeln_d("!!! Need to remove track: SAME SIDE!");
continue;
}
#extern string DetermineTrackCategory(WsfTrack);
string category = DetermineTrackCategory(x);
if (category == "unknown")
{
writeln_d(" - Unknown type: ", x.TargetName(), " - ", x.TargetType() );
continue;
}
updatedTracks.Set(x.TargetName(), 1);
WsfRIPRJob job = ((WsfRIPRProcessor)PROCESSOR).GetJobByData("targetTrackName", x.TargetName());
if (job.IsValid())
{
//update the already existing job
job.SetData("targetLocation", x.CurrentLocation());
}
else
{
//create a job for this track
extern double cPursueTargetPriority;
WsfRIPRJob temp = WsfRIPRJob.Create( ((WsfRIPRProcessor)PROCESSOR),
"pursue-target",
"pursue-target-" + x.TargetName(),
cPursueTargetPriority,
maxJobWinnersForPursueTrack);
temp.SetData("targetTrack", x);
temp.SetData("targetTrackName", x.TargetName());
temp.SetData("targetLocation", x.CurrentLocation());
writeln_d(" - Adding job");
((WsfRIPRProcessor)PROCESSOR).AddJob(temp);
writeln_d("--- ", PLATFORM.Name(), " job change, ADD: ", temp.GetDescription() );
PLATFORM.Comment(write_str("AIFL - new job: ", temp.GetDescription()));
}
}
Array<WsfRIPRJob> jobs = ((WsfRIPRProcessor)PROCESSOR).GetJobs();
foreach (WsfRIPRJob x in jobs)
{
string name = (string)x.GetData("targetTrackName");
if (updatedTracks[name] == 0 && x.Name() == "pursue-target")
{
string temp = write_str("--- ", PLATFORM.Name(), " job change, REMOVE: ", x.GetDescription());
writeln_d(temp);
PLATFORM.Comment(temp);
((WsfRIPRProcessor)PROCESSOR).RemoveJob(x);
}
}
end_execute
end_behavior

View File

@@ -0,0 +1,173 @@
# ****************************************************************************
# 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.
# ****************************************************************************
behavior interpret_flank_jobs
script_debug_writes off
script_variables
WsfDraw draw = WsfDraw();
bool mDrawFlankLines = false;
WsfRIPRJob mMyJob;
end_script_variables
on_init
draw.SetLineSize(2);
draw.SetColor(1.0, 0.0, 1.0); //purple
end_on_init
precondition
if (!PROCESSOR.IsA_TypeOf("WSF_RIPR_PROCESSOR"))
{
return Failure("behavior not attached to a RIPR processor!");
}
writeln_d("precondition interpret_flank_jobs");
draw.SetDuration(PROCESSOR.UpdateInterval());
WsfRIPRProcessor commander = ((WsfRIPRProcessor)PROCESSOR).GetRIPRCommanderProcessor();
if (commander.IsValid())
{
mMyJob = commander.GetJobFor(TIME_NOW, ((WsfRIPRProcessor)PROCESSOR));
if (mMyJob.IsValid() && mMyJob.Name() == "flank")
{
return true;
}
else
{
//remove any jobs this behavior created
Array<WsfRIPRJob> jobs = ((WsfRIPRProcessor)PROCESSOR).GetJobs();
foreach (WsfRIPRJob job in jobs)
{
if (job.IsValid() && job.Data().Exists("flankPointName"))
{
//its a valid flank point job created by this behavior, remove it
((WsfRIPRProcessor)PROCESSOR).RemoveJob(job);
}
}
extern Map<int, WsfGeoPoint> mFlankJobIdToFlankPointMap;
mFlankJobIdToFlankPointMap.Clear();
return Failure("Agent does not have a flank job!");
}
}
else
{
return Failure("Agent does not have a commander!");
}
end_precondition
execute
writeln_d("executing interpret_flank_jobs");
WsfGeoPoint zonePoint = (WsfGeoPoint)mMyJob.GetData("ZonePoint");
double zoneBearing = (double) mMyJob.GetData("ZoneBearing");
bool bearingValid = (bool) mMyJob.GetData("ZoneBearingValid");
WsfZone flankZone = (WsfZone) mMyJob.GetData("FlankZone");
double flankDist = (double) mMyJob.GetData("FlankDistance");
string zoneName = (string) mMyJob.GetData("ZoneName");
#extern Map<int, WsfGeoPoint> mFlankJobIdToFlankPointMap;
WsfGeoPoint flankPoint = mFlankJobIdToFlankPointMap.Get( mMyJob.GetId() );
if (mDrawFlankLines)
{
//draw the outline of the flank zone
flankZone.DebugDrawZone(zonePoint, zoneBearing*MATH.RAD_PER_DEG());
//draw flank point of interest (target we are flanking), white dot
draw.BeginPoints();
draw.SetColor(1.0, 1.0, 1.0);
draw.Vertex(zonePoint);
draw.End();
if (bearingValid)
{
//cluster heading is with reference to east (instead of north), so subtract 90 degrees
#doulbe clusterBearingTrue = MATH.NormalizeAngle0_360( zoneBearing - 90.0 );
double clusterBearingTrue = MATH.NormalizeAngle0_360( zoneBearing );
WsfGeoPoint bPoint = WsfGeoPoint(zonePoint);
bPoint.Extrapolate( clusterBearingTrue, flankDist );
//draw red-orange line to represent heading of target's flight
draw.BeginLines();
draw.SetColor(1.0, 0.3, 0.1);
draw.Vertex(zonePoint);
draw.Vertex(bPoint);
draw.End();
}
//draw green line to the flank point (the side we are flying towards)
draw.BeginLines();
draw.SetColor(0.1, 1.0, 0.4);
draw.Vertex(zonePoint);
draw.Vertex(flankPoint);
draw.End();
}
//see if any subordinates are in the flank zone, if they are... flanking is done
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!");
mMyJob.SetProgress( ((WsfRIPRProcessor)PROCESSOR), 1.0 ); #mark the job as complete
}
}
int NumSubordinates = PLATFORM.Subordinates().Count();
//if flank job doesn't exist yet, create it
WsfRIPRJob job = ((WsfRIPRProcessor)PROCESSOR).GetJobByData("flankPointName", zoneName);
if( ! job.IsValid() )
{
if (NumSubordinates > 0)
{
extern double cFlankPointPriority;
//set max job winners to number of subordinates (so all can proceed into zone)
WsfRIPRJob temp = WsfRIPRJob.Create( ((WsfRIPRProcessor)PROCESSOR),
"pursue-point",
"pursue-point-" + zoneName,
cFlankPointPriority,
NumSubordinates);
temp.SetData( "targetTrackName", zoneName ); //hack for now, so other code here works
temp.SetData( "targetPoint", flankPoint );
temp.SetData( "flankPointName", zoneName );
((WsfRIPRProcessor)PROCESSOR).AddJob(temp);
writeln_d("--- ", PLATFORM.Name(), " job change, ADD: ", zoneName );
}
}
else
{
job.SetData( "targetPoint" , flankPoint );
writeln_d(" aiFL - updated flank pursue-point job ", zoneName, ", ( ", flankPoint.Latitude(), ", ", flankPoint.Longitude(), " )" );
}
//remove all jobs that aren't involved with flanking
Array<WsfRIPRJob> jobs = ((WsfRIPRProcessor)PROCESSOR).GetJobs();
foreach (WsfRIPRJob x in jobs)
{
string name = (string)x.GetData("targetTrackName");
if ( name != zoneName )
{
writeln_d("--- ", PLATFORM.Name(), " job change, REMOVE: ", name);
((WsfRIPRProcessor)PROCESSOR).RemoveJob(x);
}
}
end_execute
end_behavior

View File

@@ -0,0 +1,119 @@
# ****************************************************************************
# 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.
# ****************************************************************************
//this behavior will be the only one in an agents tree that bids on "zone" jobs (compiler error otherwise)
//this behavior should be the only one in an agents tree that creates "pursue-target" jobs when it runs (unexplained behavior otherwise)
//in other words... if other behaviors also create "pursue-target" jobs, they should all be under a selector node, so only 1 runs on any update
behavior interpret_zone_jobs
script_debug_writes off
script_variables
int maxJobWinnersForPursueTrack = 1;
WsfRIPRJob mCurrentJob;
end_script_variables
on_init
//nothing here yet
end_on_init
precondition
writeln_d("precondition interpret_zone_jobs");
if (!PROCESSOR.IsA_TypeOf("WSF_RIPR_PROCESSOR"))
{
return Failure("behavior not attached to a RIPR processor!");
}
if (((WsfRIPRProcessor)PROCESSOR).GetRIPRCommanderProcessor().IsValid())
{
return true;
}
else
{
return Failure("Agent does not have a commander to get jobs from!");
}
end_precondition
execute
writeln_d(PLATFORM.Name(), " executing interpret_zone_jobs, T=", TIME_NOW);
// now check the board to see what we've won!
Map<string, int> updatedTracks = Map<string, int>();
WsfRIPRProcessor commander = ((WsfRIPRProcessor)PROCESSOR).GetRIPRCommanderProcessor();
if (commander.IsJobWindowOpen())
{
//we can get a new job for ourselves here
mCurrentJob = commander.GetJobFor(TIME_NOW, ((WsfRIPRProcessor)PROCESSOR));
}
else if (commander.IsBidWindowOpen())
{
//we dont update our own job board until here
if( mCurrentJob.IsValid() && mCurrentJob.Name() == "zone" )
{
Array<string> targetNames = (Array<string>)mCurrentJob.GetData("ZoneThreatNameArray");
writeln_d(PLATFORM.Name(), " targetNames.Size() = ", targetNames.Size());
foreach(string targetName in targetNames)
{
WsfPlatform target = WsfSimulation.FindPlatform(targetName);
if (target.IsValid())
{
updatedTracks.Set( targetName, 1 );
WsfRIPRJob job = ((WsfRIPRProcessor)PROCESSOR).GetJobByData("targetTrackName", targetName);
if (job.IsValid())
{
//just update it, it already exists
}
else
{
extern double cPursueTargetPriority;
WsfRIPRJob temp = WsfRIPRJob.Create(((WsfRIPRProcessor)PROCESSOR),
"pursue-target",
"pursue-target-" + targetName,
cPursueTargetPriority,
maxJobWinnersForPursueTrack);
temp.SetData("targetTrackName", targetName);
((WsfRIPRProcessor)PROCESSOR).AddJob(temp);
writeln_d("--- ", PLATFORM.Name(), " job change, ADD: ", targetName);
}
}
}
}
else
{
writeln_d("--- currentJob not a valid zone job!!!!! Removing all my aifl jobs.");
}
Array<WsfRIPRJob> jobs = ((WsfRIPRProcessor)PROCESSOR).GetJobs();
foreach (WsfRIPRJob x in jobs)
{
string name = (string)x.GetData("targetTrackName");
if (updatedTracks.Get(name) != 1 && x.Name() == "pursue-target")
{
writeln_d("--- ", PLATFORM.Name(), " job change, REMOVE: ", name);
((WsfRIPRProcessor)PROCESSOR).RemoveJob(x);
}
}
}
end_execute
end_behavior

View File

@@ -0,0 +1,342 @@
# ****************************************************************************
# 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.
# ****************************************************************************
behavior manage-pincer
script_debug_writes off
script_variables
//for debugging
bool mDrawClusters = false;
//parameters used to determine if a pincer is appropriate
bool mRequireActiveWeapons = false; //if true, weapons must be in flight before pincer performed
double mMaxSeparationAngle = 120.0; //degrees (pincer done if we've flanked by this much)
int mNumSubsInvolved = 2; //not necessary to be an even number
double mThresholdDistance = 160 * 1852; //160nm
//clustering is performed to make sure the group of threats we are pincering against are grouped tightly together
//if more than one group exist, the 2nd, 3rd, etc... groups have to be far enough away so that they aren't a
//concern for the pincer maneuver (i.e. we wont head into them by separating around the target group)
string mClusterMethod = "HTREEMAX"; //also valid: K_MEANS, H_TREE_MIN
double mClusterDistanceLimit = 20*1852; //20nm - how close the group members have to be together
double mMinDistanceRatio = 1.15; //other groups have to be 15% farther away than target group
// parameters useful for those performing the pincer
bool mCross = false;
string mCapZoneName = ""; //useful to specify the name of zone in which we ignore the threat's
//orientation, because they are capping while in the zone
// script variables, used by methods below, do not change, not for user edit
Array<WsfTrack> mTrackArray = Array<WsfTrack>();
Array<string> mTargetNames = Array<string>();
WsfDraw mDraw = WsfDraw();
double mMeanBearing = 0;
bool mMeanBearingValid = false;
WsfClusterManager mClusterManager;
WsfRIPRJob mPincerJob;
WsfGeoPoint mMeanPoint;
WsfGeoPoint mSubPoint;
end_script_variables
on_init
mClusterManager = WsfClusterManager.Create(); // creates a cluster manager owned by this script
mClusterManager.SetClusterMethod(mClusterMethod); // default is: "K_MEANS"
mClusterManager.SetDistanceFunction("POSITION_VELOCITY"); // default is: "POSITION_ONLY"
mClusterManager.SetDistanceLimit(mClusterDistanceLimit) ;
end_on_init
## utility method used to draw lines around tracks in a cluster ## lines are drawn according to the convex hull of the cluster members
script void draw_cluster_hull(WsfCluster cluster)
Array<WsfGeoPoint> pts = cluster.ConvexHull();
if (pts.Size() <= 0)
{
return;
}
WsfGeoPoint first = pts.Get(0);
mDraw.SetColor(1.0,0.5,0.0); //orange?
mDraw.SetLineStyle("solid");
mDraw.SetLineSize(2);
mDraw.BeginPolyline();
for (int j = 0; j < pts.Size(); j = j + 1 )
{
WsfGeoPoint pt = pts.Get(j);
mDraw.Vertex(pt);
}
mDraw.Vertex(first);
mDraw.End();
if (cluster.BearingValid())
{
double bearing = cluster.Bearing();
WsfGeoPoint pt = cluster.MeanLocation();
mDraw.SetColor(1.0,1.0,1.0); //white?
mDraw.BeginLines();
mDraw.Vertex(pt); pt.Extrapolate(cluster.Bearing(), 92600); //50 nautical miles
mDraw.Vertex(pt);
mDraw.End();
}
end_script
script WsfGeoPoint MeanLocation(Array<WsfPlatform> plats)
Vec3 mean = Vec3.Construct(0, 0, 0);
if (plats.Size() > 0)
{
double scale = 1.0/((double)plats.Size());
foreach(WsfPlatform plat in plats)
{
Vec3 temp = plat.LocationWCS();
temp.Scale(scale);
mean = Vec3.Add(mean, temp);
}
}
return WsfGeoPoint.ConstructWCS(mean);
end_script
script WsfGeoPoint SubordinatesMeanLocation()
return MeanLocation(((WsfRIPRProcessor)PROCESSOR).SubordinatePlatforms());
end_script
script void RemovePincerJob()
if(mPincerJob.IsValid())
{
//remove job from board
WsfRIPRJob fake;
writeln_d(PLATFORM.Name(), " job change, REMOVE: ", mPincerJob.GetDescription());
PLATFORM.Comment(write_str("REMOVE job: ", mPincerJob.GetDescription()));
((WsfRIPRProcessor)PROCESSOR).RemoveJob(mPincerJob);
mPincerJob = fake;
}
end_script
precondition
#writeln_d("precondition manage-pincer");
if (!PROCESSOR.IsA_TypeOf("WSF_RIPR_PROCESSOR"))
{
return Failure("behavior not attached to a RIPR processor!");
} //((WsfRIPRProcessor)PROCESSOR)
if (((WsfRIPRProcessor)PROCESSOR).SubordinateProcessors().Size() < mNumSubsInvolved)
{
RemovePincerJob();
writeln_d("not enough subordinates");
return Failure("not enough subordinates");
}
if (mRequireActiveWeapons)
{
int weaponCount = 0;
Array<WsfRIPRProcessor> subs = ((WsfRIPRProcessor)PROCESSOR).SubordinateProcessors();
foreach(WsfRIPRProcessor proc in subs)
{
weaponCount = weaponCount + proc.WeaponsActive();
}
if (weaponCount <= 0)
{
RemovePincerJob();
writeln_d("no active weapons, no pincer yet");
return Failure("no active weapons, no pincer yet");
}
}
mSubPoint = SubordinatesMeanLocation();
#extern bool TestTrackCategory(WsfTrack, string);
mTrackArray.Clear();
mTargetNames.Clear();
foreach (WsfLocalTrack track in PLATFORM.MasterTrackList())
{
if ( (track.IFF_Friend()) ||
(track.SideValid() && track.Side() == PLATFORM.Side()) ||
(! track. LocationValid() ) ||
(track.SlantRangeTo(mSubPoint) > mThresholdDistance) ||
(TestTrackCategory(track, "unknown")) )
{
continue;
}
track.SetBearing( track.Heading() ); #useful for the cluster processing
mTrackArray.PushBack(track);
mTargetNames.PushBack(track.TargetName());
}
if (mTrackArray.Size() > 0)
{
mClusterManager.UpdateClusters(TIME_NOW,mTrackArray);
if (mDrawClusters == true)
{
for (int i = 0; i < mClusterManager.Count(); i = i + 1 )
{
draw_cluster_hull(mClusterManager.Entry(i));
}
}
if (mClusterManager.Count() > 1)
{
//check distances
double near = MATH.DOUBLE_MAX();
double near2 = MATH.DOUBLE_MAX();
for (int i = 0; i < mClusterManager.Count(); i = i + 1 )
{
double dist = mClusterManager.Entry(i).MeanLocation().SlantRangeTo(mSubPoint);
if (dist < near)
{
if (near < near2)
{
near2 = near;
}
near = dist;
}
else if (dist < near2)
{
near2 = dist;
}
}
double ratio = near2/near;
if (ratio < mMinDistanceRatio)
{
RemovePincerJob();
writeln_d("threats too spread out!");
return Failure("threats too spread out!");
}
}
WsfCluster cluster = mClusterManager.Entry(0);
mMeanPoint = cluster.MeanLocation();
mMeanBearingValid = cluster.BearingValid();
mMeanBearing = cluster.Bearing();
}
else //no threats to pincer against, exit out
{
RemovePincerJob();
writeln_d("no threats to pincer against yet!");
return Failure("no threats to pincer against yet!");
}
//check separation of all subordinates
//only relavent if not currently in phase 2 (dragging & chasing)
int dragging = 0;
if(mPincerJob.IsValid())
{
dragging = (int)mPincerJob.GetData("left_drag") + (int)mPincerJob.GetData("right_drag");
}
if (dragging == 0)
{
Array<WsfPlatform> subs = ((WsfRIPRProcessor)PROCESSOR).SubordinatePlatforms();
WsfGeoPoint subMean = MeanLocation(subs);
double standard = mMeanPoint.TrueBearingTo(subMean);
double min = 361;
double max = -361;
foreach(WsfPlatform p in subs)
{
double b = MATH.NormalizeAngleMinus180_180(mMeanPoint.TrueBearingTo(p.Location()) - standard);
min = MATH.Min(min, b);
max = MATH.Max(max, b);
}
double diff = max - min;
if (diff >= mMaxSeparationAngle)
{
RemovePincerJob();
writeln_d("pincer complete, targets flanked!");
return Failure("pincer complete, targets flanked!");
}
}
mDraw.SetDuration(PROCESSOR.UpdateInterval());
return true;
end_precondition
execute
writeln_d("executing manage-pincer, T=", TIME_NOW);
//first find the group of target(s) we are going to perform the pincer against
//generate a list of their names and get their mean location
Array<WsfRIPRProcessor> subs = ((WsfRIPRProcessor)PROCESSOR).SubordinateProcessors();
int N = subs.Size();
if (mPincerJob.IsValid())
{
//pincer job already created! just update it
mPincerJob.SetData("ZoneThreatNameArray", mTargetNames);
mPincerJob.SetData("ZonePoint", mMeanPoint);
mPincerJob.SetData("ZoneBearingValid", mMeanBearingValid);
mPincerJob.SetData("ZoneBearing", mMeanBearing);
mPincerJob.SetData("all_on_cap", 0);
if (mCapZoneName != "" && mPincerJob.IsValid())
{
bool allOnCap = true;
foreach(WsfTrack t in mTrackArray)
{
if ( ! t.ReportedLocation().WithinZone(mCapZoneName))
{
allOnCap = false;
break;
}
}
if (allOnCap)
{
mPincerJob.SetData("all_on_cap", 1);
}
}
}
else
{
//create a pincer job for this flight group
string desc = write_str("pincer-", mNumSubsInvolved);
extern double cPincerPriority;
mPincerJob = WsfRIPRJob.Create( ((WsfRIPRProcessor)PROCESSOR), //creator
"pincer", //name
desc, //description
cPincerPriority * mNumSubsInvolved, //priority (must be enough to break even with "mNumSubsInvolved" jobs of another type
mNumSubsInvolved); //max winnners
mPincerJob.SetData("ZoneThreatNameArray", mTargetNames);
mPincerJob.SetData("ZonePoint", mMeanPoint);
mPincerJob.SetData("ZoneBearingValid", mMeanBearingValid);
mPincerJob.SetData("ZoneBearing", mMeanBearing);
mPincerJob.SetData("left_drag", 0);
mPincerJob.SetData("rightdrag", 0);
mPincerJob.SetData("all_on_cap", 0);
mPincerJob.SetWinnersMin(mNumSubsInvolved);
//setup the left & right flyers
double avgBearing = mMeanPoint.TrueBearingTo(mSubPoint);
foreach(WsfRIPRProcessor proc in subs)
{
//Vec3 temp = proc.Platform().LocationWCS();
double bearing = mMeanPoint.TrueBearingTo(proc.Platform().Location());
double relAngle = MATH.NormalizeAngleMinus180_180(bearing-avgBearing);
if (mCross)
{
relAngle = -1 * relAngle;
}
if (relAngle < 0)
{
mPincerJob.SetData(proc.Platform().Name(), "right");
}
else
{
mPincerJob.SetData(proc.Platform().Name(), "left");
}
}
((WsfRIPRProcessor)PROCESSOR).AddJob(mPincerJob);
writeln_d("--- ", PLATFORM.Name(), " job change, ADD: ", mPincerJob.GetDescription() );
PLATFORM.Comment(write_str("ADD job: ", mPincerJob.GetDescription()));
# foreach(string tgt in mTargetNames)
# {
# PLATFORM.Comment(tgt);
# }
}
end_execute
end_behavior

View File

@@ -0,0 +1,58 @@
# ****************************************************************************
# 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.
# ****************************************************************************
##############################################################################
### assumes exists: #extern WsfTrack GetTrackByName(WsfPlatform, string);
##############################################################################
behavior manage-uplinks
script_debug_writes off
script_variables
//agent constants
end_script_variables
precondition
writeln_d("precondition manage-uplinks");
if (!PROCESSOR.IsA_TypeOf("WSF_RIPR_PROCESSOR"))
{
return Failure("behavior not attached to a RIPR processor!");
} //((WsfRIPRProcessor)PROCESSOR)
return true;
end_precondition
#on_init
#end_on_init
execute
writeln_d("executing manage-uplinks");
Array<WsfRIPRJob> jobs = ((WsfRIPRProcessor)PROCESSOR).GetJobs();
foreach (WsfRIPRJob job in jobs)
{
if (job.Name() == "weapon_uplink")
{
int weaponPlatformIndex = (int)job.GetData("weaponPlatformIndex");
int targetPlatformIndex = (int)job.GetData("targetPlatformIndex");
WsfPlatform weaponPlatform = WsfSimulation.FindPlatform(weaponPlatformIndex);
WsfPlatform targetPlatform = WsfSimulation.FindPlatform(targetPlatformIndex);
if (!weaponPlatform.IsValid() || !targetPlatform.IsValid())
{
//either the weapon is gone or the target is gone, so the uplink is no longer needed, remove the job
string msg = write_str("weapon or target for ", job.GetDescription(), " is gone, remove job");
writeln_d(msg);
PLATFORM.Comment(msg);
((WsfRIPRProcessor)PROCESSOR).RemoveJob(job);
}
}
}
end_execute
end_behavior

View File

@@ -0,0 +1,66 @@
# ****************************************************************************
# 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.
# ****************************************************************************
behavior toggle_windows
script_debug_writes off
script_variables
int mToggleAfterThisManyUpdates = 1;
int mToggleCounter;
end_script_variables
on_init
mToggleCounter = mToggleAfterThisManyUpdates;
end_on_init
precondition
writeln_d("precondition toggle_windows");
if (!PROCESSOR.IsA_TypeOf("WSF_RIPR_PROCESSOR"))
{
return Failure("behavior not attached to a RIPR processor!");
} //((WsfRIPRProcessor)PROCESSOR)
//this behavior should probably always run, windows can always be toggled
return true;
end_precondition
execute
writeln_d("executing toggle_windows");
if (mToggleCounter <=0)
{
mToggleCounter = mToggleAfterThisManyUpdates;
if (((WsfRIPRProcessor)PROCESSOR).IsJobWindowOpen())
{
((WsfRIPRProcessor)PROCESSOR).SetJobWindowOpen(false);
((WsfRIPRProcessor)PROCESSOR).SetBidWindowOpen(true);
writeln_d(PLATFORM.Name(), " job window closed / bid window opened, time=", TIME_NOW);
}
else
{
((WsfRIPRProcessor)PROCESSOR).SetJobWindowOpen(true);
((WsfRIPRProcessor)PROCESSOR).SetBidWindowOpen(false);
writeln_d(PLATFORM.Name(), " job window opened / bid window closed, time=", TIME_NOW);
}
}
else
{
mToggleCounter = mToggleCounter - 1;
}
end_execute
end_behavior