init
This commit is contained in:
@@ -0,0 +1,255 @@
|
||||
# ****************************************************************************
|
||||
# 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_clustering_jobs
|
||||
|
||||
script_debug_writes off
|
||||
|
||||
|
||||
script_variables
|
||||
##########################################################################
|
||||
## user parameters, change these at will
|
||||
##########################################################################
|
||||
bool mDrawClusters = false;
|
||||
int mMaxJobWinners = 1;
|
||||
string mClusterMethod = "H_TREE_MAX"; //valid: K_MEANS, H_TREE_MIN, H_TREE_MAX
|
||||
string mDistanceFunction = "POSITION_VELOCITY"; //valid: POSITION_VELOCITY, POSITION_ONLY, 2D_POSITION
|
||||
double mClusterDistanceLimit = 50*1852; // ~50 nautical miles
|
||||
int mNumClusters = -1; //not used unless positive (over-rides distance limit)
|
||||
double mClusterJobPriority = 1; //if set to zero or less, then number of cluster occupants will be the priority
|
||||
bool mRequireKnownCategory = false; //if set to true, only threats of a known category will be clustered
|
||||
|
||||
##########################################################################
|
||||
## script variables, used by methods below, do not change
|
||||
##########################################################################
|
||||
Array<WsfTrack> trackArray = Array<WsfTrack>();
|
||||
Map<int, int> mJobToWinnerMap = Map<int, int>();
|
||||
WsfDraw draw = WsfDraw();
|
||||
WsfClusterManager cManager;
|
||||
end_script_variables
|
||||
|
||||
|
||||
on_init
|
||||
cManager = WsfClusterManager.Create(); // creates a cluster manager owned by this script
|
||||
cManager.SetClusterMethod(mClusterMethod);
|
||||
cManager.SetDistanceLimit(mClusterDistanceLimit);
|
||||
if (mNumClusters > 0)
|
||||
{
|
||||
cManager.SetNumClustersToCreate(mNumClusters);
|
||||
}
|
||||
else
|
||||
{
|
||||
cManager.SetDistanceFunction(mDistanceFunction);
|
||||
}
|
||||
end_on_init
|
||||
|
||||
|
||||
precondition
|
||||
writeln_d("precondition create_clustering_jobs");
|
||||
draw.SetDuration(PROCESSOR.UpdateInterval());
|
||||
|
||||
##########################################################################
|
||||
## only update cluster jobs during a bid window
|
||||
##########################################################################
|
||||
if ((!(PROCESSOR.IsBidWindowOpen())) || PROCESSOR.IsJobWindowOpen())
|
||||
{
|
||||
writeln_d("GCI agent will not change zone (cluster) jobs unless bid window open & job window closed!");
|
||||
return Failure("bid window closed or job window open");
|
||||
}
|
||||
|
||||
return true;
|
||||
end_precondition
|
||||
|
||||
|
||||
############################################################################
|
||||
## 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);
|
||||
draw.SetColor(1.0,0.5,0.0); //orange?
|
||||
draw.SetLineStyle("solid");
|
||||
draw.SetLineSize(2);
|
||||
draw.BeginPolyline();
|
||||
for (int j = 0; j < pts.Size(); j = j + 1 )
|
||||
{
|
||||
WsfGeoPoint pt = pts.Get(j);
|
||||
draw.Vertex(pt);
|
||||
}
|
||||
draw.Vertex(first);
|
||||
draw.End();
|
||||
end_script
|
||||
|
||||
|
||||
############################################################################
|
||||
## utility method used to add a cluster job
|
||||
############################################################################
|
||||
script void add_cluster_job(WsfCluster cluster)
|
||||
#new cluster, job not created yet, so create one
|
||||
int occupants = cluster.Count();
|
||||
int clusterId = cluster.Id();
|
||||
string jobName = "cluster_" + (string)clusterId;
|
||||
double ClusterPriority = mClusterJobPriority;
|
||||
if (ClusterPriority <= 0)
|
||||
{
|
||||
ClusterPriority = (double)occupants;
|
||||
}
|
||||
WsfRIPRJob temp = WsfRIPRJob.Create( PROCESSOR,
|
||||
"zone",
|
||||
jobName,
|
||||
ClusterPriority,
|
||||
mMaxJobWinners );
|
||||
temp.SetData( "clusterId", clusterId );
|
||||
temp.SetData( "ZoneName", jobName );
|
||||
temp.SetData( "ZonePoint", WsfGeoPoint(cluster.MeanLocation()) );
|
||||
temp.SetData( "ZoneBearing", cluster.Bearing() );
|
||||
temp.SetData( "ZoneBearingValid", cluster.BearingValid() );
|
||||
temp.SetData( "ZoneNumThreats", occupants );
|
||||
temp.SetData( "for_air", 1 );
|
||||
|
||||
Array<string> arr = Array<string>();
|
||||
for (int i = 0; i < occupants; i = i + 1 )
|
||||
{
|
||||
arr.PushBack(cluster.Entry(i).TargetName());
|
||||
writeln_d("job cluster member: ", cluster.Entry(i).TargetName());
|
||||
}
|
||||
temp.SetData( "ZoneThreatNameArray", arr );
|
||||
PROCESSOR.AddJob(temp);
|
||||
writeln_d("+++ ", PLATFORM.Name(), " job change, ADD: ", temp.Name(), ", id: ", clusterId);
|
||||
end_script
|
||||
|
||||
|
||||
############################################################################
|
||||
## utility method used to remove a cluster job
|
||||
############################################################################
|
||||
script void remove_cluster_job(WsfRIPRJob aJob)
|
||||
int clusterId = (int)aJob.GetData("clusterId");
|
||||
writeln_d("--- ", PLATFORM.Name(), " job change, REMOVE: ", aJob.GetDescription(), ", id: ", clusterId);
|
||||
PROCESSOR.RemoveJob( aJob );
|
||||
end_script
|
||||
|
||||
|
||||
############################################################################
|
||||
## utility method used to update a cluster job
|
||||
## returns true if job exists & was updated
|
||||
## returns false if job by that name does not exist
|
||||
############################################################################
|
||||
script bool update_cluster_job(WsfCluster cluster)
|
||||
int clusterId = cluster.Id();
|
||||
WsfRIPRJob aJob = PROCESSOR.GetJobByData("clusterId", clusterId);
|
||||
if (aJob.IsValid())
|
||||
{
|
||||
//if we are here, the cluster job is identified as having same list of threats
|
||||
//so these data are the same: job priority, ZoneNumThreats, ZoneThreatNameArray,
|
||||
aJob.SetData( "ZonePoint", WsfGeoPoint(cluster.MeanLocation()) );
|
||||
aJob.SetData( "ZoneBearing", cluster.Bearing() );
|
||||
aJob.SetData( "ZoneBearingValid", cluster.BearingValid() );
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
end_script
|
||||
|
||||
|
||||
execute
|
||||
writeln_d(PLATFORM.Name(), " executing create_clustering_jobs, T=", TIME_NOW);
|
||||
|
||||
##########################################################################
|
||||
## update the cluster manager with the current master track list
|
||||
##########################################################################
|
||||
extern bool TestTrackCategory( WsfTrack, string );
|
||||
WsfLocalTrackList localTracks = PLATFORM.MasterTrackList();
|
||||
trackArray.Clear();
|
||||
foreach (WsfTrack track in localTracks)
|
||||
{
|
||||
if (!mRequireKnownCategory || !TestTrackCategory(track, "unknown"))
|
||||
{
|
||||
track.SetBearing( track.Heading() ); #useful for the cluster processing
|
||||
trackArray.PushBack(track);
|
||||
}
|
||||
}
|
||||
cManager.UpdateClusters(TIME_NOW,trackArray);
|
||||
|
||||
##########################################################################
|
||||
## update or add jobs for all the clusters
|
||||
##########################################################################
|
||||
Map<int, int> updatedJobs = Map<int, int>();
|
||||
int NumClusters = cManager.Count();
|
||||
for (int i = 0; i < NumClusters; i = i + 1 )
|
||||
{
|
||||
WsfCluster cluster = cManager.Entry(i);
|
||||
int clusterId = cluster.Id();
|
||||
|
||||
if (mDrawClusters == true)
|
||||
{
|
||||
draw_cluster_hull(cluster);
|
||||
}
|
||||
|
||||
if( cluster.Count() > 0 )
|
||||
{
|
||||
if (update_cluster_job(cluster))
|
||||
{
|
||||
//writeln_d("cluster already exists & was updated!");
|
||||
}
|
||||
else
|
||||
{
|
||||
add_cluster_job(cluster);
|
||||
}
|
||||
updatedJobs.Set(clusterId, 1);
|
||||
}
|
||||
}
|
||||
|
||||
##########################################################################
|
||||
## remove any old jobs for clusters that have gone away
|
||||
##########################################################################
|
||||
Array<WsfRIPRJob> jobs = PROCESSOR.GetJobs();
|
||||
foreach( WsfRIPRJob aJob in jobs )
|
||||
{
|
||||
if (aJob.Name() == "zone")
|
||||
{
|
||||
int clusterId = (int)aJob.GetData("clusterId");
|
||||
if (updatedJobs.Get(clusterId) != 1)
|
||||
{
|
||||
remove_cluster_job( aJob );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
##########################################################################
|
||||
## print out a message if there are any new winners of jobs
|
||||
##########################################################################
|
||||
jobs = PROCESSOR.GetJobs();
|
||||
foreach( WsfRIPRJob aJob in jobs )
|
||||
{
|
||||
if( ! mJobToWinnerMap.Exists( aJob.GetId() ) )
|
||||
{
|
||||
mJobToWinnerMap.Set( aJob.GetId(), 0 );
|
||||
}
|
||||
else
|
||||
{
|
||||
int currWinners = aJob.GetNumWinners();
|
||||
int lastWinners = mJobToWinnerMap.Get( aJob.GetId() );
|
||||
if( currWinners != lastWinners )
|
||||
{
|
||||
string NewComment = "AIGCI - Sub took a job: " + aJob.Name() + " - " + aJob.GetDescription();
|
||||
PLATFORM.Comment(NewComment);
|
||||
mJobToWinnerMap.Set( aJob.GetId(), currWinners );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
end_execute
|
||||
|
||||
end_behavior
|
||||
259
processors/quantum_agents/aigci/behavior_create_flank_jobs.txt
Normal file
259
processors/quantum_agents/aigci/behavior_create_flank_jobs.txt
Normal file
@@ -0,0 +1,259 @@
|
||||
# ****************************************************************************
|
||||
# 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_flank_jobs
|
||||
|
||||
script_debug_writes off
|
||||
|
||||
|
||||
script_variables
|
||||
WsfDraw draw = WsfDraw();
|
||||
|
||||
Array<Vec3> mBowTieZonePoints = Array<Vec3>();
|
||||
|
||||
Map<int, int> mFlankToClusterMap = Map<int, int>();
|
||||
Map<int, int> mClusterToFlankMap = Map<int, int>();
|
||||
Array<string> mCompletedFlanks = Array<string>();
|
||||
Map<string, double> mFlankNameToTimeCompleteMap = Map<string, double>();
|
||||
|
||||
int mMaxTotalFlankJobsEverToCreate = 1;
|
||||
int mMaxJobWinnersForFlank = 2;
|
||||
double mFlankJobPriorityScale = 1.5; // make > 1 for more important than clusters
|
||||
double cFLANK_DISTANCE = 60.0; // flank towards a point approximately this many nm to the side of target
|
||||
int mFlankJobsCreated = 0; // utility variable, not a constant to set
|
||||
int mFlankJobsCompleted = 0; // utility variable, not a constant to set
|
||||
|
||||
//after a completed flank on a cluster, don't do another on that same cluster until this time passes
|
||||
double mFlankRepeatDelay = 300.0; //in units of seconds
|
||||
|
||||
end_script_variables
|
||||
|
||||
|
||||
on_init
|
||||
double FlankDistanceMeters = cFLANK_DISTANCE * MATH.M_PER_NM();
|
||||
//create simple bowtie shape, based on specified size parameters
|
||||
double w1 = 2.0 * FlankDistanceMeters; //Bow Tie Width (meters)
|
||||
double h2 = 0.75 * FlankDistanceMeters; //Bow Tie Outter Thickness (meters)
|
||||
double h1 = 0.5 * h2; //Bow Tie Inner Thickness (meters)
|
||||
mBowTieZonePoints.PushBack(Vec3.Construct( h1, 0, 0));
|
||||
mBowTieZonePoints.PushBack(Vec3.Construct( h2, w1, 0));
|
||||
mBowTieZonePoints.PushBack(Vec3.Construct( -h2, w1, 0));
|
||||
mBowTieZonePoints.PushBack(Vec3.Construct( -h1, 0, 0));
|
||||
mBowTieZonePoints.PushBack(Vec3.Construct( -h2, -w1, 0));
|
||||
mBowTieZonePoints.PushBack(Vec3.Construct( h2, -w1, 0));
|
||||
end_on_init
|
||||
|
||||
|
||||
# #
|
||||
# # script callback method for when a flank job is completed
|
||||
# # the job board calls this when a flank job that it owns has been marked as complete
|
||||
# #
|
||||
# script void aigci_flank_complete(int jobID)
|
||||
# //save job in completed array
|
||||
# //remove job from created array
|
||||
# WsfRIPRJob aJob = PROCESSOR.GetJobById( jobID );
|
||||
# writeln_d("~~~ Flank Job Completed: ", aJob.GetDescription());
|
||||
# mCompletedFlanks.PushBack( aJob.Name() );
|
||||
#
|
||||
# mFlankNameToTimeCompleteMap.Set( aJob.Name(), TIME_NOW );
|
||||
#
|
||||
# int clusterId = mFlankToClusterMap.Get( jobID );
|
||||
# mFlankToClusterMap.Erase( jobID );
|
||||
# mClusterToFlankMap.Erase( clusterId );
|
||||
#
|
||||
# mFlankJobsCompleted = mFlankJobsCompleted + 1;
|
||||
# end_script
|
||||
|
||||
|
||||
|
||||
precondition
|
||||
writeln_d("precondition create_flank_jobs");
|
||||
|
||||
//check if this gci is done creating & updating the flank jobs
|
||||
if( mFlankJobsCompleted >= mMaxTotalFlankJobsEverToCreate )
|
||||
{
|
||||
writeln_d( "~~~ aiGCI - Max Flank Jobs Completed, return now!" );
|
||||
return Failure("max number of flank jobs already created and completed");
|
||||
}
|
||||
|
||||
draw.SetDuration(PROCESSOR.UpdateInterval());
|
||||
return true;
|
||||
end_precondition
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
execute
|
||||
writeln_d("executing create_flank_jobs");
|
||||
|
||||
|
||||
########################################################################
|
||||
## check for clusters that went away & we can't flank them anymore
|
||||
## otherwise, update any existing flank jobs
|
||||
########################################################################
|
||||
foreach( int flankJobId : int clusterJobId in mFlankToClusterMap )
|
||||
{
|
||||
WsfRIPRJob flankJob = PROCESSOR.GetJobById( flankJobId );
|
||||
WsfRIPRJob clusterJob = PROCESSOR.GetJobById( clusterJobId );
|
||||
|
||||
if( clusterJob.IsValid() )
|
||||
{
|
||||
if( flankJob.IsValid() )
|
||||
{
|
||||
if (flankJob.GetBestProgress() >= 1.0 )
|
||||
{
|
||||
writeln("GCI removing completed flank job!!!");
|
||||
mCompletedFlanks.PushBack( flankJob.Name() );
|
||||
mFlankNameToTimeCompleteMap.Set( flankJob.Name(), TIME_NOW );
|
||||
int flankId = flankJob.GetId();
|
||||
int clusterId = mFlankToClusterMap.Get( flankId );
|
||||
mFlankToClusterMap.Erase( flankId );
|
||||
mClusterToFlankMap.Erase( clusterId );
|
||||
mFlankJobsCompleted = mFlankJobsCompleted + 1;
|
||||
mFlankToClusterMap.Remove( flankId );
|
||||
mClusterToFlankMap.Remove( clusterId );
|
||||
PROCESSOR.RemoveJob( flankJob );
|
||||
}
|
||||
else
|
||||
{
|
||||
writeln_d( "~~~ aiGCI - updating flank job ", flankJob.Name(), " with cluster ", clusterJob.Name(), "!!!" );
|
||||
writeln_d("best flank progress: ", flankJob.GetBestProgress());
|
||||
WsfGeoPoint point = (WsfGeoPoint)clusterJob.GetData("ZonePoint");
|
||||
double bearing = (double)clusterJob.GetData("ZoneBearing");
|
||||
bool bearingValid = (bool)clusterJob.GetData("ZoneBearingValid");
|
||||
//writeln_d( "~~~ aiGCI - flank job BEARING: ", bearing );
|
||||
string flankZoneName = "flank" + clusterJob.Name();
|
||||
|
||||
//writeln(PLATFORM.Name(), " UpdateFlankZone( ", TIME_NOW, ", ", flankZoneName, ", ", point.ToString(), ", ", bearing, ", ", cFLANK_DISTANCE);
|
||||
|
||||
//now the wsfzone can be treated as a relative zone, and doesn't need updating
|
||||
//UpdateFlankZone( TIME_NOW, flankZoneName, point, bearing, cFLANK_DISTANCE );
|
||||
//update the flank job with relevant cluster information
|
||||
flankJob.Priority( (mFlankJobPriorityScale * clusterJob.GetPriority()) );
|
||||
flankJob.SetData( "FlankZoneName", flankZoneName );
|
||||
flankJob.SetData( "ZonePoint", WsfGeoPoint(point) );
|
||||
flankJob.SetData( "ZoneBearing", bearing );
|
||||
flankJob.SetData( "ZoneBearingValid", bearingValid );
|
||||
flankJob.SetData( "ZoneNumThreats", (int)clusterJob.GetData("ZoneNumThreats") );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
writeln_d( "~~~ aiGCI - cluster valid, but flank not valid!" );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
//remove flank job, cluster went away
|
||||
if (flankJob.IsValid())
|
||||
{
|
||||
writeln_d("--- ", PLATFORM.Name(), " job change, REMOVE: ", flankJob.Name() );
|
||||
|
||||
PROCESSOR.RemoveJob( flankJob );
|
||||
|
||||
if( mFlankJobsCreated > 0 )
|
||||
{
|
||||
mFlankJobsCreated = mFlankJobsCreated - 1;
|
||||
}
|
||||
}
|
||||
mFlankToClusterMap.Remove( flankJobId );
|
||||
mClusterToFlankMap.Remove( clusterJobId );
|
||||
}
|
||||
}
|
||||
|
||||
//check if only the updates were needed, or if we can create more flank jobs
|
||||
if( mFlankJobsCreated >= mMaxTotalFlankJobsEverToCreate )
|
||||
{
|
||||
writeln_d( "~~~ aiGCI - max flank jobs created, no need for more!" );
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
########################################################################
|
||||
## create a new flank job if a cluster exists that never had one
|
||||
## locate the nearest available cluster
|
||||
########################################################################
|
||||
double DistClosestCluster = MATH.DOUBLE_MAX();
|
||||
WsfRIPRJob JobWithClusterToFlank;
|
||||
Array<WsfRIPRJob> jobs = PROCESSOR.GetJobs();
|
||||
foreach (WsfRIPRJob aJob in jobs)
|
||||
{
|
||||
//if job is a cluster job (not a flank job) & is not being flanked already
|
||||
//then consider it as a candidate for flanking, else continue
|
||||
if( mFlankToClusterMap.Exists( aJob.GetId() ) || mClusterToFlankMap.Exists( aJob.GetId() ) )
|
||||
{
|
||||
//writeln_d( "~~~ aiGCI - job ", aJob.Name(), " is either a flank job or a zone thats already being flanked!" );
|
||||
continue;
|
||||
}
|
||||
|
||||
//if enough time hasn't elapsed since the last flank performed on this cluster, then continue
|
||||
//this prevents the agent from re-creating flank jobs that were just completed and removed
|
||||
string newFlankName = "flank" + aJob.Name();
|
||||
if( mFlankNameToTimeCompleteMap.Exists( newFlankName ) )
|
||||
{
|
||||
double lastFlankTime = mFlankNameToTimeCompleteMap.Get( newFlankName );
|
||||
if( TIME_NOW < (lastFlankTime + mFlankRepeatDelay) )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
WsfGeoPoint cPoint = (WsfGeoPoint)aJob.GetData("ZonePoint");
|
||||
double dist = PLATFORM.GroundRangeTo(cPoint);
|
||||
if( dist < DistClosestCluster )
|
||||
{
|
||||
JobWithClusterToFlank = aJob;
|
||||
}
|
||||
}
|
||||
if( JobWithClusterToFlank.IsValid() )
|
||||
{
|
||||
WsfGeoPoint clusterPoint = (WsfGeoPoint)JobWithClusterToFlank.GetData("ZonePoint");
|
||||
double clusterBearing = (double)JobWithClusterToFlank.GetData("ZoneBearing");
|
||||
bool clusterBearingValid = (bool)JobWithClusterToFlank.GetData("ZoneBearingValid");
|
||||
int clusterOccupants = (int)JobWithClusterToFlank.GetData("ZoneNumThreats");
|
||||
string clusterZoneName = (string)JobWithClusterToFlank.GetData("ZoneName");
|
||||
|
||||
string flankZoneName = "flank" + JobWithClusterToFlank.Name();
|
||||
|
||||
|
||||
WsfRIPRJob NewFlankJob = WsfRIPRJob.Create( PROCESSOR,
|
||||
"flank",
|
||||
flankZoneName,
|
||||
(mFlankJobPriorityScale * JobWithClusterToFlank.GetPriority()),
|
||||
mMaxJobWinnersForFlank );
|
||||
NewFlankJob.SetData( "ZoneName", clusterZoneName );
|
||||
NewFlankJob.SetData( "FlankZoneName", flankZoneName );
|
||||
NewFlankJob.SetData( "ZonePoint", WsfGeoPoint(clusterPoint) );
|
||||
NewFlankJob.SetData( "ZoneBearing", clusterBearing );
|
||||
NewFlankJob.SetData( "ZoneBearingValid", clusterBearingValid );
|
||||
NewFlankJob.SetData( "ZoneNumThreats", clusterOccupants );
|
||||
double FlankDistanceMeters = cFLANK_DISTANCE * MATH.M_PER_NM();
|
||||
NewFlankJob.SetData( "FlankDistance", (1.8 * FlankDistanceMeters) ); //pursue a point 10% inside the flank zone, the flank width is 2*FlankDist
|
||||
#NewFlankJob.SetData( "OnJobComplete", "aigci_flank_complete" );
|
||||
NewFlankJob.SetData( "for_air", 1 );
|
||||
|
||||
WsfZone flankZone = WsfZone.CreatePolygonal(PLATFORM, mBowTieZonePoints); //creates a relative zone
|
||||
NewFlankJob.SetData( "FlankZone", flankZone );
|
||||
|
||||
PROCESSOR.AddJob(NewFlankJob);
|
||||
|
||||
writeln_d("+++ ", PLATFORM.Name(), " job change, ADD: ", NewFlankJob.Name() );
|
||||
|
||||
mFlankJobsCreated = mFlankJobsCreated + 1;
|
||||
//save link between the flank & the cluster thats being flanked
|
||||
mFlankToClusterMap.Set( NewFlankJob.GetId(), JobWithClusterToFlank.GetId() );
|
||||
mClusterToFlankMap.Set( JobWithClusterToFlank.GetId(), NewFlankJob.GetId() );
|
||||
}
|
||||
|
||||
end_execute
|
||||
|
||||
end_behavior
|
||||
@@ -0,0 +1,294 @@
|
||||
# ****************************************************************************
|
||||
# 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.
|
||||
# ****************************************************************************
|
||||
|
||||
|
||||
#it is assumed that all weapons on the platform this agent is on... are alert-5 aircraft
|
||||
#when it launches an alert-5 aircraft, it will find the first one available & fire
|
||||
|
||||
behavior launch_alert-5_aircraft
|
||||
|
||||
script_debug_writes off
|
||||
|
||||
script_variables
|
||||
//public
|
||||
string mFlightLeadToSupport = "fighter_flight_lead";
|
||||
int mSalvoCount = 2;
|
||||
//private
|
||||
bool mLaunched = false;
|
||||
end_script_variables
|
||||
|
||||
#on_init
|
||||
#end_on_init
|
||||
|
||||
script WsfWeapon GetNextAlert5()
|
||||
WsfWeapon empty;
|
||||
for(int i=0; i<PLATFORM.WeaponCount(); i=i+1)
|
||||
{
|
||||
WsfWeapon test = PLATFORM.WeaponEntry(i);
|
||||
if (test.QuantityRemaining() >= 1)
|
||||
{
|
||||
return test;
|
||||
}
|
||||
}
|
||||
return empty;
|
||||
end_script
|
||||
|
||||
|
||||
script WsfRIPRProcessor GetRIPR(string platformName)
|
||||
WsfRIPRProcessor empty;
|
||||
WsfPlatform plat = WsfSimulation.FindPlatform(platformName);
|
||||
if (plat.IsValid())
|
||||
{
|
||||
for (int i=0; i<plat.ProcessorCount(); i=i+1)
|
||||
{
|
||||
WsfProcessor proc = plat.ProcessorEntry(i);
|
||||
if (proc.IsA_TypeOf("WSF_RIPR_PROCESSOR"))
|
||||
{
|
||||
WsfRIPRProcessor rProc = (WsfRIPRProcessor)proc;
|
||||
return rProc;
|
||||
}
|
||||
}
|
||||
}
|
||||
return empty;
|
||||
end_script
|
||||
|
||||
|
||||
script bool LaunchAlert_5(WsfWeapon alert5Weapon, int salvo)
|
||||
WsfGeoPoint pt = PLATFORM.Location();
|
||||
pt.Offset(PLATFORM.Heading(), 9260, 0.0, -9260);
|
||||
WsfTrack tgt = WsfTrack();
|
||||
tgt.SetLocation(pt);
|
||||
return alert5Weapon.FireSalvo(tgt, salvo);
|
||||
end_script
|
||||
|
||||
|
||||
precondition
|
||||
writeln_d("precondition launch_alert-5_aircraft");
|
||||
if (mLaunched==true)
|
||||
{
|
||||
writeln_d("already launched alert5 aircraft!");
|
||||
return Failure("already launched alert5 aircraft!");
|
||||
}
|
||||
WsfWeapon test = GetNextAlert5();
|
||||
if (!test.IsValid())
|
||||
{
|
||||
writeln_d("no alert5 aircraft available to launch!");
|
||||
return Failure("no alert5 aircraft available to launch!");
|
||||
}
|
||||
|
||||
WsfRIPRProcessor proc = GetRIPR(mFlightLeadToSupport);
|
||||
if (proc.IsValid())
|
||||
{
|
||||
WsfRIPRJob job = proc.GetRIPRCommanderProcessor().GetJobFor(TIME_NOW, proc);
|
||||
if( job.IsValid())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
writeln_d("flight lead not found: ", mFlightLeadToSupport);
|
||||
return Failure("flight lead not found!");
|
||||
}
|
||||
writeln_d("flight lead does not need support yet!");
|
||||
return Failure("flight lead does not need support yet!");
|
||||
|
||||
end_precondition
|
||||
|
||||
|
||||
execute
|
||||
writeln_d("executing launch_alert-5_aircraft");
|
||||
mLaunched = LaunchAlert_5(GetNextAlert5(), mSalvoCount);
|
||||
end_execute
|
||||
|
||||
end_behavior
|
||||
|
||||
|
||||
|
||||
|
||||
#it is assumed that all weapons on the platform this agent is on... are alert-5 aircraft
|
||||
#when it launches an alert-5 aircraft, it will find the first one available & fire
|
||||
|
||||
behavior launch_alert-5_aircraft2
|
||||
script_debug_writes off
|
||||
|
||||
script_variables //public
|
||||
#string mFlightLeadToSupport = "fighter flightjlead";
|
||||
int mSalvoCount = 2;
|
||||
double mFlightLaunchDelay = 120.0; # 30 sec per a/c, 2 a/c per flight
|
||||
bool mFirstLaunch = true;
|
||||
double mFirstFlightLaunchDelay = 420.0; #account for 5 minute delay of first launch //private
|
||||
double mLastLaunchedTime = -9999.0;
|
||||
int mNumberOfAirThreats = 0;
|
||||
int mNumberOfSubsInAir = 0;
|
||||
bool mCheckPeers = true;
|
||||
string mProtectZoneName = "";
|
||||
double mProtectRange = 1852 * 100; //100nm (in meters)
|
||||
end_script_variables
|
||||
|
||||
# #on init #end on init
|
||||
# script bool ValidType(WsfTrack track)
|
||||
# if (track.Target().IsValid())
|
||||
# {
|
||||
# if (track.Target().Type() == "STRIKER" || track.Target().Type() == "SWEEPER" || track.Target().Type() == "CAPPER" || track.Target().IsATypeOf("E-3C"))
|
||||
# {
|
||||
# return true;
|
||||
# }
|
||||
# }
|
||||
# return false;
|
||||
# end_script
|
||||
|
||||
script WsfWeapon GetNextAlert5()
|
||||
WsfWeapon empty;
|
||||
for(int i=0; i<PLATFORM.WeaponCount(); i=i+l)
|
||||
{
|
||||
WsfWeapon test = PLATFORM.WeaponEntry(i);
|
||||
if (test.QuantityRemaining() >= 1)
|
||||
{
|
||||
return test;
|
||||
}
|
||||
}
|
||||
return empty;
|
||||
end_script
|
||||
|
||||
script bool AnyActiveRequests()
|
||||
for(int i=0; i<PLATFORM.WeaponCount(); i=i+l)
|
||||
{
|
||||
WsfWeapon test = PLATFORM.WeaponEntry(i);
|
||||
if (test.ActiveRequestCount() > 0)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
end_script
|
||||
|
||||
# script WsfRIPRProcessor GetRIPR(string platformName)
|
||||
# WsfRIPRProcessor empty;
|
||||
# WsfPlatform plat = WsfSimulation.FindPlatform(platformName);
|
||||
# if (plat.IsValid())
|
||||
# {
|
||||
# for (int i=0; i<plat.ProcessorCount(); i=i+l)
|
||||
# {
|
||||
# WsfProcessor proc = plat.ProcessorEntry(i);
|
||||
# if (proc.IsA TypeOf("WSFRIPRPROCESSOR"))
|
||||
# {
|
||||
# WsfRIPRProcessor rProc = (WsfRIPRProcessor)proc;
|
||||
# return rProc;
|
||||
# }
|
||||
# }
|
||||
# }
|
||||
# return empty;
|
||||
precondition
|
||||
writelnd("T= ",TIME NOW,", ", PLATFORM.Name()," precondition launch_alert-5 aircraft");
|
||||
WsfWeapon test = GetNextAlert5();
|
||||
if (!test.IsValid())
|
||||
{
|
||||
writelnd("T= ", TIME NOW," no alert5 aircraft available to launch!");
|
||||
return Failure("no alert5 aircraft available to launch!");
|
||||
}
|
||||
if (AnyActiveRequests())
|
||||
{
|
||||
writeln_d("currently launching something");
|
||||
return Failure("currently launching something");
|
||||
}
|
||||
|
||||
mNumberOfAirThreats = 0; //check num threats every time foreach (WsfTrack track in PLATFORM.MasterTrackList())
|
||||
if ((track.TimeSinceUpdated() < 60.0) &&
|
||||
(track.LocationValid() || (track.RangeValid() && track.BearingValid())) &&
|
||||
#(ValidType(track)) &&
|
||||
((mProtectZoneName != "" || track.WithinZoneOf(PLATFORM, mProtectZoneName)) || PLATFORM.GroundRangeTo(track) < mProtectRange))
|
||||
{
|
||||
mNumberOfAirThreats = mNumberOfAirThreats + 1;
|
||||
writeln_d("threat: ", track.TargetName());
|
||||
}
|
||||
|
||||
if (mCheckPeers == true)
|
||||
{
|
||||
mNumberOfSubsInAir = 0; //reset here, & then count
|
||||
WsfPlatform commander = PLATFORM.Commander();
|
||||
if (!commander.IsValid())
|
||||
{
|
||||
writeln_d("no commander!");
|
||||
return Failure("no commander!");
|
||||
}
|
||||
|
||||
foreach (WsfPlatform sub in commander.Subordinates())
|
||||
{
|
||||
if (sub.Type() == "FLIGHT_LEAD_RED") # for each flight lead
|
||||
{
|
||||
foreach (WsfPlatform airInt in sub.Subordinates()) # for each airborne interceptor
|
||||
{
|
||||
if (airInt.AuxDataExists("ENGAGING") && airInt.AuxDataBool("ENGAGING"))
|
||||
{
|
||||
mNumberOfSubsInAir = mNumberOfSubsInAir + 1;
|
||||
writeln_d("subordinate: ", airInt.Name());
|
||||
}
|
||||
else
|
||||
{
|
||||
writeln_d("not engaging: ", airInt.Name());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
mNumberOfSubsInAir = 0; //reset here, & then count
|
||||
foreach (WsfPlatform airInt in PLATFORM.Subordinates()) # for each airborne interceptor
|
||||
{
|
||||
if (airInt.AuxDataExists("ENGAGING") && airInt.AuxDataBool("ENGAGING"))
|
||||
{
|
||||
mNumberOfSubsInAir = mNumberOfSubsInAir + 1;
|
||||
writeln_d("subordinate: ", airInt.Name());
|
||||
}
|
||||
else
|
||||
{
|
||||
writeln_d("not engaging: ", airInt.Name());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (mNumberOfAirThreats <= mNumberOfSubsInAir)
|
||||
{
|
||||
writeln_d("T= ",TIME_N0W," ", PLATFORM.Name(),", enough subordinates in air already for threats!");
|
||||
return Failure("enough subordinates in air already for threats!");
|
||||
}
|
||||
double delay = mFlightLaunchDelay;
|
||||
if (mFirstLaunch == true)
|
||||
{
|
||||
delay = mFirstFlightLaunchDelay;
|
||||
}
|
||||
if ((TIME_NOW-mLastLaunchedTime) < delay)
|
||||
{
|
||||
writeln_d("T= ",TIME NOW," Still launching previous flight!");
|
||||
return Failure("Still launching previous flight!");
|
||||
}
|
||||
return true;
|
||||
end_precondition
|
||||
|
||||
execute
|
||||
writeln_d("T= ", TIME_NOW," executing launch_alert-5_aircraft");
|
||||
WsfGeoPoint pt = PLATFORM.Location();
|
||||
pt.Offset(PLATFORM.Heading(), 9260, 0.0, -9260);
|
||||
WsfTrack tgt = WsfTrack();
|
||||
tgt.SetLocation(pt);
|
||||
WsfWeapon alert5Weapon = GetNextAlert5();
|
||||
if (alert5Weapon.FireSalvo(tgt, mSalvoCount))
|
||||
{
|
||||
if (mLastLaunchedTime > 0)
|
||||
{
|
||||
mFirstLaunch = false;
|
||||
}
|
||||
mLastLaunchedTime = TIME_NOW;
|
||||
PLATFORM.Comment("Launch Alert 5");
|
||||
}
|
||||
end_execute
|
||||
|
||||
end_behavior
|
||||
206
processors/quantum_agents/aigci/gci_quantum_tasker.txt
Normal file
206
processors/quantum_agents/aigci/gci_quantum_tasker.txt
Normal file
@@ -0,0 +1,206 @@
|
||||
# ****************************************************************************
|
||||
# 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.
|
||||
# ****************************************************************************
|
||||
|
||||
|
||||
|
||||
processor GCI_QUANTUM_TASKER WSF_QUANTUM_TASKER_PROCESSOR
|
||||
|
||||
update_interval 10.0 sec
|
||||
|
||||
script_variables
|
||||
##########################################################################
|
||||
## user parameters, change these at will
|
||||
##########################################################################
|
||||
bool mDrawClusters = false;
|
||||
bool mRequireTasking = false;
|
||||
int mMaxTaskPerformers = 1;
|
||||
string mClusterMethod = "H_TREE_MAX"; //valid: K_MEANS, H_TREE_MIN, H_TREE_MAX
|
||||
string mDistanceFunction = "POSITION_VELOCITY"; //valid: POSITION_VELOCITY, POSITION_ONLY, 2D_POSITION
|
||||
double mClusterDistanceLimit = 50*1852; // ~50 nautical miles
|
||||
int mNumClusters = -1; //not used unless positive (over-rides distance limit)
|
||||
double mClusterJobPriority = 1; //if set to zero or less, then number of cluster occupants will be the priority
|
||||
|
||||
##########################################################################
|
||||
## script variables, used by methods below, do not change
|
||||
##########################################################################
|
||||
WsfDraw draw = WsfDraw();
|
||||
WsfClusterManager cManager;
|
||||
end_script_variables
|
||||
|
||||
|
||||
on_initialize
|
||||
cManager = WsfClusterManager.Create(); // creates a cluster manager owned by this script
|
||||
cManager.SetClusterMethod(mClusterMethod);
|
||||
cManager.SetDistanceLimit(mClusterDistanceLimit);
|
||||
if (mNumClusters > 0)
|
||||
{
|
||||
cManager.SetNumClustersToCreate(mNumClusters);
|
||||
}
|
||||
else
|
||||
{
|
||||
cManager.SetDistanceFunction(mDistanceFunction);
|
||||
}
|
||||
end_on_initialize
|
||||
|
||||
############################################################################
|
||||
## 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);
|
||||
draw.SetDuration(PROCESSOR.UpdateInterval());
|
||||
draw.SetColor(1.0,0.5,0.0); //orange?
|
||||
draw.SetLineStyle("solid");
|
||||
draw.SetLineSize(2);
|
||||
draw.BeginPolyline();
|
||||
for (int j = 0; j < pts.Size(); j = j + 1 )
|
||||
{
|
||||
WsfGeoPoint pt = pts.Get(j);
|
||||
draw.Vertex(pt);
|
||||
}
|
||||
draw.Vertex(first);
|
||||
draw.End();
|
||||
end_script
|
||||
|
||||
|
||||
script Array<WsfQuantumTask> GciCommanderTaskGeneration (Array<WsfLocalTrack> TRACKS, Array<WsfAssetPerception> ASSETS )
|
||||
|
||||
//create weapon tasks for enemy track groups (clusters)
|
||||
Array<WsfQuantumTask> tasks = Array<WsfQuantumTask>();
|
||||
writeln_d(PLATFORM.Name(), " executing GciCommanderTaskGeneration(), T=", TIME_NOW);
|
||||
|
||||
##########################################################################
|
||||
## update the cluster manager with the current master track list
|
||||
##########################################################################
|
||||
WsfLocalTrackList localTracks = PLATFORM.MasterTrackList();
|
||||
Array<WsfTrack> trackArray = Array<WsfTrack>();
|
||||
foreach (WsfLocalTrack lt in localTracks)
|
||||
{
|
||||
if (mRequireTasking == true && TasksReceivedForTarget(lt.TrackId()).Count() <= 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (lt.IsValid() && (!lt.SideValid() || lt.Side() != PLATFORM.Side()))
|
||||
{
|
||||
lt.SetBearing( lt.Heading() ); #useful for the cluster processing
|
||||
trackArray.PushBack(lt);
|
||||
}
|
||||
}
|
||||
cManager.UpdateClusters(TIME_NOW,trackArray);
|
||||
|
||||
##########################################################################
|
||||
## generate a task for each clusters
|
||||
##########################################################################
|
||||
int NumClusters = cManager.Count();
|
||||
for (int i = 0; i < NumClusters; i = i + 1 )
|
||||
{
|
||||
WsfCluster cluster = cManager.Entry(i);
|
||||
int clusterId = cluster.Id();
|
||||
|
||||
if (mDrawClusters == true)
|
||||
{
|
||||
draw_cluster_hull(cluster);
|
||||
}
|
||||
|
||||
if( cluster.Count() > 0 )
|
||||
{
|
||||
double ClusterPriority = mClusterJobPriority;
|
||||
if (ClusterPriority <= 0)
|
||||
{
|
||||
ClusterPriority = (double)cluster.Count();
|
||||
}
|
||||
WsfQuantumTask qt = WsfQuantumTask.Construct(ClusterPriority, "CLUSTER", cluster.Entry(0)); //include a track with the task
|
||||
qt.SetTaskType("CLUSTER");
|
||||
qt.UniqueId(cluster.Id());
|
||||
qt.SetAuxData( "clusterIndex", i ); //for evaluation below
|
||||
//TODO local tracks in the quantum task???
|
||||
qt.SetAuxData( "maxPerformers", mMaxTaskPerformers );
|
||||
qt.SetAuxData( "clusterId", cluster.Id() );
|
||||
qt.SetAuxData( "ClusterMeanPoint", WsfGeoPoint(cluster.MeanLocation()) );
|
||||
qt.SetAuxData( "ClusterBearing", cluster.Bearing() );
|
||||
qt.SetAuxData( "ClusterBearingValid", cluster.BearingValid() );
|
||||
qt.SetAuxData( "ClusterNumMembers", cluster.Count() );
|
||||
Array<string> arr = Array<string>();
|
||||
for (int i = 0; i < cluster.Count(); i = i + 1 )
|
||||
{
|
||||
arr.PushBack(cluster.Entry(i).TargetName());
|
||||
writeln_d("job cluster member: ", cluster.Entry(i).TargetName());
|
||||
}
|
||||
qt.SetAuxData( "ClusterMemberNames", arr );
|
||||
tasks.PushBack(qt);
|
||||
writeln_d("cluster task generated for: ", cluster.Id());
|
||||
}
|
||||
}
|
||||
return tasks;
|
||||
end_script
|
||||
|
||||
|
||||
script double GciCommanderEvaluation ( WsfQuantumTask TASK, WsfAssetPerception ASSET)
|
||||
|
||||
//simplistic evaluation for now
|
||||
//TODO : iterate over all perceived assets that are subordinates of this lead and...
|
||||
// evaluate each entry separately & make a composite value
|
||||
writeln_d("evaluating ", ASSET.Name(), " and task type ", TASK.TaskType());
|
||||
if (ASSET.Type() == "FLIGHT_LEAD")
|
||||
{
|
||||
WsfPlatform lead = WsfSimulation.FindPlatform(ASSET.Index());
|
||||
if (lead.IsValid())
|
||||
{
|
||||
writeln_d("calculating value");
|
||||
WsfGeoPoint subCentroid = lead.SubordinatesCentroid(); //cheating, TODO: use asset perception
|
||||
int clusterIndex = TASK.AuxDataInt("clusterIndex");
|
||||
WsfCluster cluster = cManager.Entry(clusterIndex);
|
||||
double dist = cluster.MeanLocation().GroundRangeTo(subCentroid);
|
||||
#double count = (double)lead.Subordinates().Count();
|
||||
|
||||
//count available weapons
|
||||
double weaponCount = 0;
|
||||
Array<WsfAssetPerception> assets = PLATFORM.PerceivedAssets();
|
||||
WsfPlatformList subs = lead.Subordinates();
|
||||
foreach(WsfPlatform sub in subs)
|
||||
{
|
||||
foreach (WsfAssetPerception asset in assets)
|
||||
{
|
||||
if (asset.Index()==sub.Index())
|
||||
{
|
||||
for (int j=0; j<asset.SystemCount(); j+=1)
|
||||
{
|
||||
if (asset.SystemKind(j) == "weapon")
|
||||
{
|
||||
weaponCount += asset.SystemQuantityRemaining(j);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
writeln_d("T=", TIME_NOW, ", ", lead.Name(), " evaluation: ", (weaponCount/dist));
|
||||
#return (count/dist);
|
||||
return (weaponCount/dist);
|
||||
}
|
||||
}
|
||||
return 0.0;
|
||||
end_script
|
||||
|
||||
#show_task_messages
|
||||
script_debug_writes off
|
||||
update_interval 10.0 sec
|
||||
reallocation_strategy dynamic
|
||||
generator custom GciCommanderTaskGeneration
|
||||
evaluator custom GciCommanderEvaluation
|
||||
allocator optimal_profit
|
||||
#allocator_extra_tasks optimal_profit
|
||||
#allocator greedy_isolated
|
||||
#allocator_extra_tasks greedy_isolated
|
||||
end_processor
|
||||
Reference in New Issue
Block a user