# **************************************************************************** # 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 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 GciCommanderTaskGeneration (Array TRACKS, Array ASSETS ) //create weapon tasks for enemy track groups (clusters) Array tasks = Array(); writeln_d(PLATFORM.Name(), " executing GciCommanderTaskGeneration(), T=", TIME_NOW); ########################################################################## ## update the cluster manager with the current master track list ########################################################################## WsfLocalTrackList localTracks = PLATFORM.MasterTrackList(); Array trackArray = Array(); 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 arr = Array(); 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 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