207 lines
8.9 KiB
Plaintext
207 lines
8.9 KiB
Plaintext
# ****************************************************************************
|
|
# CUI
|
|
#
|
|
# The Advanced Framework for Simulation, Integration, and Modeling (AFSIM)
|
|
#
|
|
# The use, dissemination or disclosure of data in this file is subject to
|
|
# limitation or restriction. See accompanying README and LICENSE for details.
|
|
# ****************************************************************************
|
|
|
|
|
|
|
|
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
|