# **************************************************************************** # 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. # **************************************************************************** #always requires a commander #bids on & performs "pursue-target" jobs #does not create any jobs include_once processors/ripr_agents/common/common_platform_script.txt include_once weapons/sam/sam_launch_computer.txt processor AISS-thinker WSF_RIPR_PROCESSOR #debug #script_debug_writes on script_debug_writes off update_interval 1.0 sec script_variables int mMaxJobChannels = 1; int mSalvoSize = 2; string mTargetTrackingSensor = "ttr"; string mTTSensorMode = "TRACK"; string mAcqSensorMode = "ACQUIRE"; string mAcquisitionSensorType = "ACQ_RADAR"; string mAcquisitionCategory = "ACQUISITION"; string mTaskManagerName = "task_mgr"; string mWeaponNameOnSubordinates = "sam"; string mEnvelopeName_Outer = "full_kinematic"; string mEnvelopeName_Inner = "quarter_kinematic"; double mAcquireTimeout = 15.0; //seconds double mTrackingTimeout = 15.0; //seconds double mRelativeOffsetLimit = 90.0; //degrees double mRelativeHeadingLimit = 90.0; //degrees double mTrackerAngleAdjustLimit = 0.0; //degrees (more if target radar can rotate) double mDeadZoneRange = 1852; //arbitrary: in meters (1852 meters == 1 nautical mile) //go silent when threats are in the "dead zone" inner circle double mNeededAcquisitionTrackQuality = 0.75; double mNeededTargetingTrackQuality = 0.95; string mAcqTrkTaskStr = "AcqTrk"; string mCueTaskStr = "Cue"; Map mStateDurations = Map(); //the minimum time of evaluation for each state mStateDurations.Set( "DETECTED", 1.0 ); //arbitrary: seconds mStateDurations.Set( "TRY_ACQUIRE", 1.0 ); //arbitrary: seconds mStateDurations.Set( "ACQUIRE", 1.0 ); //arbitrary: seconds mStateDurations.Set( "TRY_TRACK", 1.0 ); //arbitrary: seconds mStateDurations.Set( "TRACK", 1.0 ); //arbitrary: seconds mStateDurations.Set( "TRY_FIRE", 1.0 ); //arbitrary: seconds mStateDurations.Set( "FIRE", 1.0 ); //arbitrary: seconds mStateDurations.Set( "WEAPONS_ACTIVE", 1.0 ); //arbitrary: seconds Map mJobCurrentState = Map(); //keeps each jobs current engagement state Map mJobStateTimes = Map(); //records when each job entered its current state WsfTrack mLastCuedTrack; // stores the last cued track Map mLastCueStartTime = Map(); // records the last time a pedestal cue was envoked Array mChannelJobs = Array(); //array index is job channel, array value is job id Array mChannelTracks = Array(); //array index is job channel, array value is trackId int mCurrentBiddingChannel = -1; WsfDraw draw = WsfDraw(); end_script_variables on_initialize SetNumJobChannels( mMaxJobChannels ); writeln_d("AISS on_init - Starting multi channel guy ", PLATFORM.Name(), " with ", GetNumJobChannels(), " total job channels" ); for (int i = 0; i < GetNumJobChannels(); i = i + 1) { mChannelJobs.PushBack( -1 ); WsfTrackId tempTrackId = WsfTrackId(); mChannelTracks.PushBack( tempTrackId ); } end_on_initialize // ---------------------------------------- // return the task manager object script WsfTaskManager GetTaskManager() static WsfTaskManager taskMgr; if( !taskMgr.IsValid() ) { taskMgr = (WsfTaskManager)PLATFORM.Processor(mTaskManagerName); } return taskMgr; end_script // ------------------------------------------------------------------------- // Get the track object to from the corresponding job script WsfTrack GetJobsTrack(WsfRIPRJob aJob) string name = (string)aJob.GetData("targetTrackName"); #extern WsfTrack GetTrackByName(WsfPlatform, string); WsfTrack track = GetTrackByName(PLATFORM, name); return track; end_script // ------------------------------------------------------------------------- // Change the current state script bool TransitionEngagementState(int aJobId, string aDesiredState) string currentState = mJobCurrentState.Get(aJobId); double duration = TIME_NOW - mJobStateTimes.Get(aJobId); double required = mStateDurations.Get(currentState); if (duration < required) { return false; } mJobCurrentState.Set(aJobId, aDesiredState); mJobStateTimes.Set(aJobId, TIME_NOW); string comment = "Job " + (string)aJobId + ", " + PLATFORM.Name() + " transition -> " + aDesiredState; PLATFORM.Comment(comment); writeln_d(comment, ", TIME = ", TIME_NOW); return true; end_script // ---------------------------------------- // Return the track quality from sensor tracks associated with the given track script double SensorTrackQuality(WsfTrack track) if( !track.IsValid() ) { return 0.0; } WsfLocalTrack finalTrack; WsfLocalTrackList localTrackList = PLATFORM.MasterTrackList(); if( localTrackList.Count() > 0 ) { finalTrack = localTrackList.FindTrack( track.TrackId() ); } if( finalTrack.IsValid() ) { double quality = 0.0; for (int trackIndex = 0; trackIndex < finalTrack.RawTrackCount(); trackIndex = trackIndex + 1) { WsfTrack rawTrack = finalTrack.RawTrack(trackIndex); double rtQuality = rawTrack.TrackQuality(); // Indirect reports will be assigned a maximum quality of 0.5 if (rawTrack.SensorType() == "") { rtQuality = MATH.Min(0.5, rtQuality); } quality = MATH.Max(quality, rtQuality); } return quality; } return track.TrackQuality(); end_script // ---------------------------------------- // Returns true if altitude data is known. script bool AltitudeKnown(WsfTrack target) // height data is available return (target.LocationValid() || target.ElevationValid()); end_script // ---------------------------------------- // Returns true if intercept results are known // (i.e. weapons have terminated for this TRACK) script bool InterceptResultsKnown(WsfTrack target) return (GetTaskManager().TimeSinceWeaponLastTerminatedFor(target.TrackId()) > 0.0); end_script // ---------------------------------------- // Return 'true' if the target is in the 'dead-zone' script bool InDeadZone( WsfTrack track ) return ( PLATFORM.SlantRangeTo(track) < mDeadZoneRange ); end_script // ---------------------------------------- // Returns true if the given track is inside the given intercept envelope using the launch computer. script bool InInterceptEnvelopeOf( WsfTrack track, string aEnvelopeName ) #extern bool SAM_LaunchComputer(WsfTrack, WsfPlatform, string, double); return SAM_LaunchComputer(track, PLATFORM, aEnvelopeName, 0.0); end_script // ---------------------------------------- // returns true if the given track has a bearing in the direction of the platform script bool TrackIsBearingTowardPlatform( WsfTrack target ) // writeln_d( "AISS TrackIsBearingTowardPlatform() - track=", target.TargetName(), " | bearing=", target.RelativeBearingTo(PLATFORM) ); return ( target.RelativeBearingTo(PLATFORM) < 90.0 && target.RelativeBearingTo(PLATFORM) > -90.0 ); end_script // ---------------------------------------- // returns true if the given track is inside an appropriate envelope script bool IsInEnvelope( WsfTrack target ) if( GetTaskManager().HaveFiredAt( target.TrackId() ) ) { writeln_d( "AISS IsInEnvelope() - target=", target.TargetName(), " | InnerEnvelope=", mEnvelopeName_Inner ); return ( GetTaskManager().TimeSinceWeaponLastTerminatedFor( target.TrackId() ) > 0.0 && InInterceptEnvelopeOf( target, mEnvelopeName_Inner ) ); } writeln_d( "AISS IsInEnvelope() - target=", target.TargetName(), " | OuterEnvelope=", mEnvelopeName_Outer, " | Range=", PLATFORM.SlantRangeTo(target) ); return InInterceptEnvelopeOf( target, mEnvelopeName_Outer ); end_script // ---------------------------------------- // returns true if the given platform is within the multiple target zone specified on the sensor script bool WithinMultipleTargetZone(WsfPlatform aPlatform, WsfTrack target) if (! aPlatform.IsValid()) { writeln_d("***** WARNING: Null platform in WithinMultipleTargetZone"); return false; } bool result = target.WithinZoneOf(aPlatform, "multiple_target_zone", mTargetTrackingSensor); writeln_d("AISS WithinMultipleTargetZone() - aPlatform=", aPlatform.Name(), " | target=", target.TargetName(), " | result=", result ); return result; end_script // ---------------------------------------- // Platform type specific WithinZoneOf logic script bool WithinZoneOf(string aZone, WsfTrack target) bool result = false; WsfPlatform subPlatform; foreach( WsfPlatform sub in PLATFORM.Subordinates() ) { WsfSensor sensor = sub.Sensor(mTargetTrackingSensor); if ( sensor.IsValid() ) { subPlatform = sub; break; } } if ( subPlatform.IsValid() && GetNumJobChannels() > 1 ) // can engage multiple targets { result = WithinMultipleTargetZone(subPlatform, target); } else { // Multiple targets not supported - just check to see if within the supplied zone. result = InInterceptEnvelopeOf(target, aZone); } writeln_d("AISS WithinZoneOf() - subPlatform=", subPlatform.Name(), " | aZone=", aZone, " | target=", target.TargetName(), " | jobchannels=", GetNumJobChannels(), " | result=", result ); return result; end_script // ---------------------------------------- // Determine the number of available weapons. script int WeaponsAvailable() int quantity = 0; foreach (WsfPlatform sub in PLATFORM.Subordinates()) { WsfWeapon weapon = sub.Weapon(mWeaponNameOnSubordinates); if (weapon.IsTurnedOn()) { quantity = quantity + weapon.QuantityRemaining(); } } return quantity; end_script // ------------------------------------------------------------------------- // Determine the number of active weapons script int NumWeaponsActive(WsfTrack aTrack) return GetTaskManager().WeaponsActiveFor(aTrack.TrackId()); end_script // ------------------------------------------------------------------------- // turn on all subordinate sensors script void ActivateSensors() { for (int entry = 0; entry < PLATFORM.SensorCount(); entry = entry + 1) { //writeln_d( "AISS ActivateSensors() - attempting to activate ", PLATFORM.SensorEntry(entry).Name() ); if( !PLATFORM.SensorEntry(entry).IsTurnedOn() ) { if( PLATFORM.SensorEntry(entry).TurnOn() ) { writeln_d( "AISS ActivateSensors() - ", PLATFORM.SensorEntry(entry).Name(), " activated." ); } } } // now activate subordinate subordinate sensors foreach( WsfPlatform sub in PLATFORM.Subordinates() ) { for (int entry = 0; entry < sub.SensorCount(); entry = entry + 1) { //writeln_d( "AISS ActivateSensors() - attempting to activate ", sub.SensorEntry(entry).Name() ); if( !sub.SensorEntry(entry).IsTurnedOn() ) { if( sub.SensorEntry(entry).TurnOn() ) { writeln_d( "AISS ActivateSensors() - ", sub.SensorEntry(entry).Name(), " activated." ); } } } } } end_script // ------------------------------------------------------------------------- // turn off all subordinate sensors script void DeactivateSensors() { for (int entry = 0; entry < PLATFORM.SensorCount(); entry = entry + 1) { writeln_d( "AISS DeactivateSensors() - attempting to deactivate ", PLATFORM.SensorEntry(entry).Name() ); if( PLATFORM.SensorEntry(entry).IsTurnedOn() ) { if( PLATFORM.SensorEntry(entry).TurnOff() ) { writeln_d( "AISS DeactivateSensors() - ", PLATFORM.SensorEntry(entry).Name(), " deactivated." ); } } } // now deactivate subordinate subordinate sensors foreach( WsfPlatform sub in PLATFORM.Subordinates() ) { for (int entry = 0; entry < sub.SensorCount(); entry = entry + 1) { writeln_d( "AISS DeactivateSensors() - attempting to deactivate ", sub.SensorEntry(entry).Name() ); if( sub.SensorEntry(entry).IsTurnedOn() ) { if( sub.SensorEntry(entry).TurnOff() ) { writeln_d( "AISS DeactivateSensors() - ", sub.SensorEntry(entry).Name(), " deactivated." ); } } } } } end_script // ------------------------------------------------------------------------- // cancel tasks and stop tracking on the given track script void CancelTaskOnTrack( WsfTrackId trackId, string taskStr ) if( !trackId.IsValid() ) { writeln_d( "AISS CancelTaskOnTrack() - invalid TrackId" ); return; } foreach( WsfPlatform sub in PLATFORM.Subordinates() ) { // cancel tasks if( ( GetTaskManager().TasksAssignedTo(sub, trackId, taskStr) ) > 0 ) { if( GetTaskManager().CancelTask(trackId, taskStr) ) { writeln_d( "AISS CancelTaskOnTrack() - cancel task ", taskStr, " on ", sub.Name() ); } } } end_script // ------------------------------------------------------------------------- // Update the pedestal cue (if possible). script void UpdatePedestalCue(WsfSensor aSensor, WsfTrack target) // Don't allow the pedestal to be re-cued if it is actively being used. if ( aSensor.IsValid() && target.IsValid() ) { writeln_d( "AISS UpdatePedestalCue() - TasksAssigned=", GetTaskManager().TasksAssignedTo(aSensor.Platform(), mCueTaskStr), " | RequestCount=", aSensor.ActiveRequestCount() ); if( GetTaskManager().TasksAssignedTo(aSensor.Platform(), mCueTaskStr) == 0 && (aSensor.ActiveRequestCount() == 0) ) { writeln_d( "AISS UpdatePedestalCue() - Bearing=", target.RelativeBearingTo(PLATFORM), " | !InDeadZone?=", !InDeadZone(target), " | InEnvelope?=", InInterceptEnvelopeOf(target, "engagement_zone") ); WsfPlatform sub = aSensor.Platform(); if ( TrackIsBearingTowardPlatform(target) && !InDeadZone(target) && InInterceptEnvelopeOf(target, "engagement_zone") ) { // Indicate this task has this pedestal GetTaskManager().AssignTask( target, mCueTaskStr, aSensor.Platform() ); //aSensor.CueToTrack( target ); aSensor.SetYaw( PLATFORM.RelativeBearingTo(target) ); mLastCuedTrack = target; mLastCueStartTime[target.TrackId()] = TIME_NOW; PLATFORM.SetAuxData("ENGAGED", true); // For RED_SAM_MOVEMENT writeln_d("***** T=", TIME_NOW, " Cue pedestal ", sub.Name(), " to ", target.TargetName(), " R=", sub.SlantRangeTo(target), ", RelBrg=", aSensor.Yaw(), " deg", ", AbsBrg=", sub.TrueBearingTo(target), " deg"); /* // draw a line in the new facing direction WsfGeoPoint look = PLATFORM.Location(); look.Offset( sub.TrueBearingTo(target), 120000, 0, 0 ); writeln_d("AISS UpdatePedestalCue() - PLATFORM.Location()=", PLATFORM.Location().X(), "::", PLATFORM.Location().Y(), "::", PLATFORM.Location().Z(), " | ", PLATFORM.Location().ToString() ); writeln_d("AISS UpdatePedestalCue() - target.CurrentLocation()=", target.CurrentLocation().X(), "::", target.CurrentLocation().Y(), "::", target.CurrentLocation().Z(), " | ", target.CurrentLocation().ToString() ); writeln_d("AISS UpdatePedestalCue() - look=", look.X(), "::", look.Y(), "::", look.Z(), " | ", look.ToString() ); draw.Reset(); draw.BeginLines(); draw.SetLineStyle("dash_dot2"); draw.SetLineSize(20); draw.SetColor(0.0,1.0,0.0); draw.Vertex(PLATFORM.Location()); draw.Vertex(look); draw.End(); */ } } } end_script // ------------------------------------------------------------------------- // Release the pedestal if appropriate. script void ReleasePedestal() if( !mLastCuedTrack.IsValid() ) { return; } writeln_d( "AISS ReleasePedestal() - TasksAssigned=", GetTaskManager().TasksAssignedFor( mLastCuedTrack.TrackId(), mCueTaskStr), " | mLastCuedTrack=", mLastCuedTrack.TargetName() ); if ( GetTaskManager().TasksAssignedFor( mLastCuedTrack.TrackId(), mCueTaskStr) != 0 ) { // This track has the pedestal. Determine if it should be released. WsfPlatform sub = GetTaskManager().AssigneeForTask(mLastCuedTrack.TrackId(), mCueTaskStr); if (sub.IsValid()) { double timeSinceLastCueStart = TIME_NOW - mLastCueStartTime[mLastCuedTrack.TrackId()]; WsfSensor sensor = sub.Sensor(mTargetTrackingSensor); writeln_d( "AISS ReleasePedestal() - sensor=", sensor.Name(), " | RequestCount=", sensor.ActiveRequestCount(), " | timeSinceLastCueStart=", timeSinceLastCueStart ); if ( sensor.IsValid() && (sensor.ActiveRequestCount() == 0) && // No active search, acq or trk requests (timeSinceLastCueStart > 30.0)) { writeln_d( "AISS ReleasePedestal() - BelievedDead?=", mLastCuedTrack.BelievedDead(), " | !WMTZ=", !WithinMultipleTargetZone(sub, mLastCuedTrack) ); if ( mLastCuedTrack.BelievedDead() || (!WithinMultipleTargetZone(sub, mLastCuedTrack)) ) { GetTaskManager().CancelTask(mLastCuedTrack.TrackId(), mCueTaskStr); //sensor.ClearCueing(); writeln_d("***** T=", TIME_NOW, " Release pedestal ", sub.Name(), " from ", mLastCuedTrack.TargetName()); writeln_d(" TSE=", timeSinceLastCueStart, " InMTZ=", WithinMultipleTargetZone(sub, mLastCuedTrack)); } } } } end_script // ------------------------------------------------------------------------- // Release resources (sensor, pedestal) that have been assigned to the target. script void ReleaseResources(WsfTrack track) writeln_d( "AISS ReleaseResources() - track=", track.TargetName() ); CancelTaskOnTrack( track.TrackId(), mAcqTrkTaskStr ); ReleasePedestal(); end_script // ------------------------------------------------------------------------- // try to Acquire the given target script bool TryAcquire( WsfTrack target ) writeln_d("AISS TryAcquire() - target=", target.TargetName() ); foreach (WsfPlatform sub in PLATFORM.Subordinates()) { WsfSensor sensor = sub.Sensor(mTargetTrackingSensor); if (! sensor.IsValid()) continue; UpdatePedestalCue(sensor, target); writeln_d( " - sensor=", sensor.Name(), " | RequestCount(Acquire)=", sensor.ActiveRequestCount(mAcqSensorMode), " | MaxRequestCount(Acquire)=", sensor.MaximumRequestCount(mAcqSensorMode) ); writeln_d( " - sensor=", sensor.Name(), " | RequestCount(Track)=", sensor.ActiveRequestCount(mTTSensorMode), " | MaxRequestCount(Track)=", sensor.MaximumRequestCount(mTTSensorMode) ); // Check number of requests for acquisition. if ( sensor.ActiveRequestCount(mAcqSensorMode) >= sensor.MaximumRequestCount(mAcqSensorMode) ) { writeln_d(" - sensor has too many requests in ", mAcqSensorMode, " mode" ); continue; } // Check number of requests for track. if ( sensor.ActiveRequestCount(mTTSensorMode) >= sensor.MaximumRequestCount(mTTSensorMode) ) { writeln_d(" - sensor has too many requests in ", mTTSensorMode, " mode" ); continue; } if ( WithinZoneOf("engagement_zone", target) && IsInEnvelope(target) ) { // Acquire the target if ( GetTaskManager().StartTracking(target, mAcqTrkTaskStr, sensor.Name(), mAcqSensorMode, sub) ) { writeln_d(" - Start Acquiring Target" ); return true; } else { writeln_d( " - sensor tried but FAILED to start Acquiring" ); } } else { writeln_d( " - target is NOT in envelope" ); } } writeln_d( " - unable to Acquire target" ); return false; end_script // ------------------------------------------------------------------------- // Try to track the given target script bool TryTrack(WsfTrack target) writeln_d("AISS TryTrack() - target=", target.TargetName() ); if ( WeaponsAvailable() == 0 ) { writeln_d("AISS TryTrack() - Bingo on Ammo" ); return false; // no weapons available } foreach (WsfPlatform sub in PLATFORM.Subordinates()) { WsfSensor sensor = sub.Sensor(mTargetTrackingSensor); if (! sensor.IsValid()) { continue; } writeln_d( " - sensor=", sensor.Name(), " | RequestCount(Track)=", sensor.ActiveRequestCount(mTTSensorMode), " | MaxRequestCount(Track)=", sensor.MaximumRequestCount(mTTSensorMode) ); if (sensor.ActiveRequestCount(mTTSensorMode) >= sensor.MaximumRequestCount(mTTSensorMode)) { writeln_d(" - sensor has too many requests in ", mTTSensorMode, " mode" ); continue; } if ( WithinZoneOf("engagement_zone", target) && !InDeadZone(target) ) { if( IsInEnvelope(target) && TrackIsBearingTowardPlatform(target) ) { // Track the target if ( GetTaskManager().StartTracking(target, mAcqTrkTaskStr, sensor.Name(), mTTSensorMode, sub) ) { writeln_d(" - Start Tracking Target" ); writeln_d( " - sensor=", sensor.Name(), " | RequestCount(Acquire)=", sensor.ActiveRequestCount(mAcqSensorMode), " | MaxRequestCount(Acquire)=", sensor.MaximumRequestCount(mAcqSensorMode) ); writeln_d( " - sensor=", sensor.Name(), " | RequestCount(Track)=", sensor.ActiveRequestCount(mTTSensorMode), " | MaxRequestCount(Track)=", sensor.MaximumRequestCount(mTTSensorMode) ); return true; } else { writeln_d( " - sensor tried but FAILED to start tracking" ); } } else { writeln_d( " - target is NOT in envelope" ); } } else { writeln_d( " - target is in Dead Zone" ); } } writeln_d( " - unable to Track target" ); return false; end_script // ------------------------------------------------------------------------- // launch a weapon at the target, the weapon must be: // - available and turned on // - have sufficient rounds // - have a target not already being fired on script bool LaunchWeaponAt(WsfTrack target) writeln_d("AISS LaunchWeaponAt() - attempting to launch weapon at ", target.TargetName()); foreach (WsfPlatform sub in PLATFORM.Subordinates()) { WsfWeapon weapon = sub.Weapon(mWeaponNameOnSubordinates); if (weapon.IsValid()) { writeln_d( "AISS LaunchWeaponAt() - ", PLATFORM.Name(), ".LaunchWeaponAt() - weapon=", weapon.Name(), " | WeaponOn=", weapon.IsTurnedOn(), " | TimeSinceFired=", weapon.TimeSinceLastFired(), " | QuantityRemaining=", weapon.QuantityRemaining() ); if ( weapon.IsTurnedOn() && weapon.QuantityRemaining() >= mSalvoSize && (GetTaskManager().TasksAssignedTo( sub, "", weapon.Name() )) == 0 ) { if ( GetTaskManager().Fire(target, "Shoot", weapon.Name(), mSalvoSize, sub) ) { writeln_d("*** T=", TIME_NOW, " ",PLATFORM.Name()," -> ", sub.Name(), " FIRING ON ", target.TargetName(), "!!!"); return true; } } } } return false; end_script // ------------------------------------------------------------------------- // Can the target be self-engaged script void ProcessEngagement(WsfRIPRJob aJob, int currChannel) if (!aJob.IsValid()) { return; } WsfTrack jobTrack = GetJobsTrack(aJob); if (!jobTrack.IsValid() ) { return; } int jobID = aJob.GetId(); string jobState = mJobCurrentState.Get(jobID); writeln_d( "AISS ProcessEngagement() - platform=", PLATFORM.Name(), " | jobState=", jobState, " | jobTrack=", jobTrack.TargetName() ); if( jobTrack.BelievedDead() ) { writeln_d( "AISS ProcessEngagement() - track, ", jobTrack.TargetName(), " is believed dead." ); aJob.SetProgress( PROCESSOR, currChannel, 1.0 ); ReleaseResources(jobTrack); PLATFORM.SetAuxData("FIRING", false); return; } if( !AltitudeKnown(jobTrack) ) { writeln_d( "AISS ProcessEngagement() - track, ", jobTrack.TargetName(), " unknown altitude." ); ReleaseResources(jobTrack); PLATFORM.SetAuxData("FIRING", false); return; } /* if( !WithinZoneOf("engagement_zone", jobTrack) ) { writeln_d( "AISS ProcessEngagement() - track, ", jobTrack.TargetName(), " is out of engagement zone." ); ReleaseResources(jobTrack); PLATFORM.SetAuxData("FIRING", false); return; } */ if (jobState == "DETECTED") { PLATFORM.SetAuxData("FIRING", false); ReleasePedestal(); //if threat is one to be tracked & fired on, try to acquire it if ( jobTrack.IFF_Foe() ) { TransitionEngagementState(jobID, "TRY_ACQUIRE"); } } else if (jobState == "TRY_ACQUIRE") { ReleasePedestal(); if( TryAcquire(jobTrack) ) { //turned on an acquisition radar, make transition TransitionEngagementState(jobID, "ACQUIRE"); } } else if (jobState == "ACQUIRE") { // look for an acquisition track of sufficient quality writeln_d( "AISS ProcessEngagement() - SensorTrackQuality()=", SensorTrackQuality(jobTrack), " | mNeededAcquisitionTrackQuality=", mNeededAcquisitionTrackQuality ); if ( SensorTrackQuality(jobTrack) >= mNeededAcquisitionTrackQuality ) { TransitionEngagementState(jobID, "TRY_TRACK"); ReleaseResources(jobTrack); return; } double timeInAcquireState = TIME_NOW - mJobStateTimes[jobID]; if( timeInAcquireState > mAcquireTimeout ) { writeln_d( "AISS ProcessEngagement() - ACQUIRE TIMEOUT: timeInAcquireState=", timeInAcquireState ); TransitionEngagementState(jobID, "TRY_ACQUIRE"); ReleaseResources(jobTrack); } } else if (jobState == "TRY_TRACK") { if( TryTrack( jobTrack ) ) { TransitionEngagementState(jobID, "TRACK"); } } else if (jobState == "TRACK") { //look for this target track of sufficient quality writeln_d( "AISS ProcessEngagement() - SensorTrackQuality()=", SensorTrackQuality(jobTrack), " | mNeededTargetingTrackQuality=", mNeededTargetingTrackQuality ); if ( SensorTrackQuality(jobTrack) >= mNeededTargetingTrackQuality ) { //found it & its good for firing on (target quality) TransitionEngagementState(jobID, "TRY_FIRE"); return; } double timeInTrackState = TIME_NOW - mJobStateTimes[jobID]; if( timeInTrackState > mTrackingTimeout ) { writeln_d( "AISS ProcessEngagement() - TRACK TIMEOUT: timeInTrackState=", timeInTrackState ); TransitionEngagementState(jobID, "TRY_ACQUIRE"); ReleaseResources(jobTrack); } } else if (jobState == "TRY_FIRE") { if( TrackIsBearingTowardPlatform(jobTrack) && !InDeadZone(jobTrack) && WithinZoneOf("full_kinematic", jobTrack) ) { TransitionEngagementState(jobID, "FIRE"); } // break off if we are no longer tracking if( SensorTrackQuality(jobTrack) < mNeededTargetingTrackQuality ) { TransitionEngagementState(jobID, "TRY_ACQUIRE"); ReleaseResources(jobTrack); } } else if (jobState == "FIRE") { writeln_d( "AISS ProcessEngagement() - IsInEnvelope()=", IsInEnvelope(jobTrack), " | NumWeaponsActive()=", NumWeaponsActive(jobTrack) ); if ( IsInEnvelope( jobTrack ) && NumWeaponsActive( jobTrack ) < 1 ) { if( LaunchWeaponAt(jobTrack) ) { PLATFORM.SetAuxData("HAVE_FIRED", true); PLATFORM.SetAuxData("FIRING", true); TransitionEngagementState(jobID, "WEAPONS_ACTIVE"); } } } else if (jobState == "WEAPONS_ACTIVE") { // check if we should fire again if( NumWeaponsActive( jobTrack ) < 1 ) { PLATFORM.SetAuxData("FIRING", false); TransitionEngagementState(jobID, "TRY_FIRE"); } } end_script // ------------------------------------------------------------------------- // Perform the given job script void DoJob(WsfRIPRJob aJob, int aChannel) writeln_d( "AISS DoJob() - platform=", PLATFORM.Name(), " | job=", aJob.GetDescription(), " | aChannel=", aChannel ); if (aJob.IsValid()) { WsfTrack track = GetJobsTrack(aJob); if (!track.IsValid()) { writeln_d( " track invalid" ); return; } draw.BeginLines(); draw.SetLineStyle("dashed"); draw.SetLineSize(30); draw.SetDuration(1.0); draw.SetColor(1.0,0.0,0.0); draw.Vertex(track.CurrentLocation()); draw.Vertex(PLATFORM.Location()); draw.End(); if (mChannelJobs.Get(aChannel) != aJob.GetId()) //write a line to output if the job changed { writeln_d( " Job Change: ", PLATFORM.Name(), " channel ", aChannel, " new job(", aJob.GetId(), "): ", aJob.GetDescription(), " new track: ", track.TrackId().ToString()); writeln_d( " aChannel=", aChannel, " | mChannelJobs.Size()=", mChannelJobs.Size(), " | mChannelTracks.Size()=", mChannelTracks.Size() ); #extern WsfTrack GetTrackById(WsfPlatform, WsfTrackId); WsfTrack oldTrack = GetTrackById( PLATFORM, mChannelTracks.Get(aChannel) ); if( oldTrack.IsValid() ) { ReleaseResources(oldTrack); } // store the new job data mChannelJobs.Set(aChannel, aJob.GetId()); mChannelTracks.Set(aChannel, track.TrackId()); //transition job to DETECTED TransitionEngagementState( aJob.GetId(), "DETECTED"); } } else { writeln_d( " job invalid" ); } end_script on_update writeln_d( "AISS on_update - ", PLATFORM.Name(), " GetNumJobChannels()=", GetNumJobChannels() ); WsfRIPRProcessor cmdr = GetRIPRCommanderProcessor(); if (!cmdr.IsValid()) { writeln_d("AISS on_update - Invalid commander for platform, ", PLATFORM.Name() ); return; } Array jobs = cmdr.GetJobs(); // if there are no jobs, turn off all sensors if( jobs.Size() < 1 ) { DeactivateSensors(); } else { writeln_d( "AISS on_update - Bid and Do jobs" ); ActivateSensors(); writeln_d( " - Jobs up for bid" ); foreach (WsfRIPRJob debugJob in jobs) { writeln_d(" ~ ", debugJob.GetDescription() ); } for (int jobChannel = 0; jobChannel < GetNumJobChannels(); jobChannel = jobChannel + 1) { // bid on each job from our commander foreach (WsfRIPRJob aJob in jobs) { mCurrentBiddingChannel = jobChannel; double bidVal = QueryBid(aJob); if( bidVal > 0 ) { // scale down bid value as channels increase //bidVal = bidVal * MATH.Pow(0.97,(double)jobChannel); aJob.BidJob(PROCESSOR, jobChannel, bidVal); } } writeln_d( "AISS on_update - ", cmdr.Name(), ".GetJobFor(", TIME_NOW, ", ", PLATFORM.Name(), ".", PROCESSOR.Name(), ", ", jobChannel, ")" ); WsfRIPRJob jobWon = cmdr.GetJobFor(TIME_NOW, PROCESSOR, jobChannel); if( jobWon.IsValid() ) { DoJob(jobWon, jobChannel); ProcessEngagement(jobWon, jobChannel); } else { writeln_d( "AISS on_update - no job assigned for channel, ", jobChannel ); } } } mCurrentBiddingChannel = -1; //extra debug stuff // draw the current facing direction of the platform WsfLocalTrackList localTracks = PLATFORM.MasterTrackList(); writeln_d( "AISS on_update - multi channel guy ",PLATFORM.Name()," track count: ",localTracks.Count()); writeln_d( "AISS on_update - multi channel guy ",PLATFORM.Name()," job count: ",jobs.Size()); writeln_d( "AISS on_update - ", PLATFORM.Name(), " GetNumJobChannels()=", GetNumJobChannels() ); end_on_update query_bid_type pursue-target if (!JOB.IsValid()) { writeln_d("AISS query_bid - job not valid for platform", PLATFORM.Name() ); return -MATH.DOUBLE_MAX(); } WsfTrack track = GetJobsTrack(JOB); if (!track.IsValid()) { writeln_d("AISS query_bid - track not valid for job: ", JOB.Name(), " - ", JOB.GetDescription(), " on platform: ", PLATFORM.Name() ); return -MATH.DOUBLE_MAX(); } if( track.BelievedDead() ) { writeln_d("AISS query_bid - track is believed dead: ", JOB.Name(), " - ", JOB.GetDescription(), " on platform: ", PLATFORM.Name() ); return -MATH.DOUBLE_MAX(); } if( !TrackIsBearingTowardPlatform(track) ) { writeln_d("AISS query_bid - track bearing is away from platform: ", JOB.Name(), " - ", JOB.GetDescription(), " on platform: ", PLATFORM.Name() ); return -MATH.DOUBLE_MAX(); } writeln_d( "AISS query_bid - JOB=", JOB.GetDescription(), " | PLATFORM=", PLATFORM.Name(), " | TRACK=", track.TargetName(), " | mCurrentBiddingChannel=", mCurrentBiddingChannel ); // don't bid on the job if the other channel already won it if( mCurrentBiddingChannel > -1 ) { for( int currChannel=0; currChannel 0 ) { writeln_d( " - platform: ", PLATFORM.Name(), " has no active weapons." ); return MATH.DOUBLE_MAX(); } //bids based on range to the job's track double JobBidValue = 1.0 / PLATFORM.SlantRangeTo(track); writeln_d(" - platform: ", PLATFORM.Name(), " bidding: ", JobBidValue, " on job: ", JOB.Name(), " - ", JOB.GetDescription() ); return JobBidValue; } writeln_d(" - platform: ", PLATFORM.Name(), " out of range of track ", track.TargetName() ); return -MATH.DOUBLE_MAX(); end_query_bid_type end_processor