Files
lab1/processors/ripr_agents/aiai/behavior_pursue_base.txt
2025-09-12 15:20:28 +08:00

233 lines
9.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.
# ****************************************************************************
##
## purse_base, aggregate behavior
## this behavior owns the bidding block for pursue-target jobs and acquires the target
## this behavior owns the [main] precondition block for this set of behaviors
## this behavior owns the variables for heading, alt, speed, but child behaviors calculate them
## last child behavior should actually do the flying
##
include_once behavior_pursue_heading.txt //original ripr intercept logic
#include_once behavior_pursue_heading_smooth.txt //option: smooth turning intercept
include_once behavior_pursue_altitude.txt
include_once behavior_pursue_speed.txt
include_once behavior_pursue_fly_simple.txt //original ripr flight command
#include_once behavior_pursue_fly_route_finder.txt //option: fly around avoidances using WsfRouteFinder
behavior pursue_base
script_debug_writes off
script_variables
//**********************************************************************//
//** aggregate parameters (modifeid by or used by child behaviors) **//
//**********************************************************************//
//these three are modified by child behaviors, not edited here
double mDesiredHeading;
double mDesiredAltitude;
double mDesiredSpeed;
//user can edit these three
double mDesiredLinearAccel = 7.5 * Earth.ACCEL_OF_GRAVITY(); // 7.5 G (m/s^2)
double mDesiredRadialAccel = 6.0 * Earth.ACCEL_OF_GRAVITY(); // 6.0 G (m/s^2) //default max limit for air mover
double mDesiredClimbDiveAngle = 35; //(degrees) //should this be climb/dive rate instead of angle?
//**********************************************************************//
//** bidding parameters (pursue-target jobs) **//
//** slant range and closing speed are the most important **//
//** bids are now in units of distance (meters) **//
//** all other bid contributions are converted with their weight **//
//** range will dominate the bids **//
//**********************************************************************//
double cMIN_JOB_BID = -MATH.DOUBLE_MAX();
double cMAX_SLANT_RANGE = 1000000.0; #over 539 nm away, target ranges beyond this are considered unfavorable
double cWEIGHT_SLANT_RANGE_TO = 1.0;
double cMIN_CLOSING_SPEED = -1050.0; #threats running away (negative closing) faster are considered unfavorable
double cWEIGHT_CLOSING_SPEED = 1.0; #scale for how closing speed translates to distance
double cWEIGHT_FUEL = 0.0; #try a value of 2.0 if you care about fuel
double cWEIGHT_MY_WEAPONS_ACTIVE = 0.0; #changes bid if your own weapons are active on target
double cWEIGHT_PEERS_WEAPONS_ACTIVE = 0.0; #changes bid if your peers weapons are active on target
double cWEIGHT_THREAT_WEAPONS_ENVELOPE = 0.0; #uses the global "mWeaponsEnvelope" array, try value of 10000 if you care about that
//careful with these two parameters, they are stateful
double cWEIGHT_CURRENT_TARGET = 0.0; #changes bid if you are currently targeting the threat
double cWEIGHT_OTHERS_TARGETING = 0.0; #changes bid if peers are currently targeting the threat
//**********************************************************************//
//** control / mode of operation parameters **//
//**********************************************************************//
#bool mFilterJobsOnWeapons = true; # ignore pursue-target jobs that we cant shoot a weapon at
bool mFilterJobsOnWeapons = false; # ignore pursue-target jobs that we cant shoot a weapon at
bool mFilterJobsOnCategory = false; # ignore pursue-target jobs that are for platform of unknown category
bool mFilterJobsOnFuel = false; # ignore pursue-target jobs that we dont have the fuel to reach
bool mFilterJobsOnZone = false; # ignore pursue-target jobs that are for platforms outsize of zone "mZoneName"
string mZoneName = "";
WsfZone mFezZone;
bool mCheckOwnJobBoardToo = false; # can this agent bid on & win a job off his own board
//**********************************************************************//
//** debugging parameters **//
//**********************************************************************//
#bool mDrawSteering = false;
//**********************************************************************//
//********* VARIABLES BELOW THIS LINE ARE NOT FOR USER EDITING *********//
//**********************************************************************//
WsfRIPRJob mCurrentJob;
#WsfDraw mDraw = WsfDraw();
string mOldTargetStr = "no target";
double mLastTime = 0.0;
end_script_variables
script bool HaveWeaponsForThreat(WsfTrack track)
#extern bool IsWeaponDomainCapable(WsfTrack, Map<string, Object>);
extern Array<Map<string, Object>> mWeaponArray;
foreach (Map<string, Object> curWeapon in mWeaponArray)
{
WsfWeapon weapon = (WsfWeapon)curWeapon["weapon"];
if (weapon.QuantityRemaining() > 0 &&
IsWeaponDomainCapable(track,curWeapon))
{
if (curWeapon.Exists("onlyUseInRange") &&
(int)curWeapon["onlyUseInRange"] == 1 &&
PLATFORM.SlantRangeTo(track) > (double)curWeapon["rangeMax"] )
{
continue;
}
return true;
}
}
return false;
end_script
precondition
writeln_d(PLATFORM.Name(), " precondition pursue-target, T=", TIME_NOW);
if (!PROCESSOR.IsA_TypeOf("WSF_RIPR_PROCESSOR"))
{
return Failure("behavior not attached to a RIPR processor!");
} // ((WsfRIPRProcessor)PROCESSOR)
double duration = TIME_NOW - mLastTime;
mLastTime = TIME_NOW;
if (duration > (1.5*PROCESSOR.UpdateInterval()))
{
mOldTargetStr = "no target";
}
string anOldTargetStr = mOldTargetStr;
mOldTargetStr = "no target";
WsfRIPRProcessor commander = ((WsfRIPRProcessor)PROCESSOR).GetRIPRCommanderProcessor();
if (commander.IsValid())
{
if (commander.IsJobWindowOpen())
{
writeln_d("pursue-target: commander.GetJobFor()");
mCurrentJob = commander.GetJobFor(TIME_NOW, ((WsfRIPRProcessor)PROCESSOR));
}
else
{
writeln_d("pursue-target: commander's job window closed, keeping current job!");
}
}
if (mCheckOwnJobBoardToo &&
(mCurrentJob.IsNull() || !mCurrentJob.IsValid()))
{
writeln_d("pursue-target: myself.GetJobFor()");
mCurrentJob = ((WsfRIPRProcessor)PROCESSOR).GetJobFor(TIME_NOW, ((WsfRIPRProcessor)PROCESSOR));
}
if (mCurrentJob.IsNull() || !mCurrentJob.IsValid() )
{
writeln_d("pursue-target ClearTarget -> job not a valid pursue-target job");
((WsfRIPRProcessor)PROCESSOR).ClearTarget();
return Failure("job is not a valid pursue-target job");
}
if (mCurrentJob.Name() != "pursue-target")
{
string msg = write_str("job is a ", mCurrentJob.Name(), " instead of a pursue-target job");
writeln_d(msg);
return Failure("job is not a pursue-target job");
}
#extern WsfTrack GetTrackByName (WsfPlatform, string);
string targetName = (string)mCurrentJob.GetData("targetTrackName");
WsfTrack targetTrack = GetTrackByName(PLATFORM, targetName);
if (!targetTrack.IsValid())
{
writeln_d(" No valid target track found for target named ", targetName);
return Failure("target track not found");
}
########################################################################
### print output / comments for any target change
#######################################################################
mOldTargetStr = "Job: " + mCurrentJob.Name() + ", " + mCurrentJob.GetDescription();
writeln_d(" - ", mOldTargetStr);
if (mOldTargetStr != anOldTargetStr)
{
PLATFORM.Comment(mOldTargetStr);
}
((WsfRIPRProcessor)PROCESSOR).SetTarget(targetTrack);
return true;
end_precondition
execute
writeln_d(PLATFORM.Name(), " executing pursue_base, T=", TIME_NOW);
# if (mDrawSteering == true)
# {
# mDraw.SetLayer("behavior_pursue_target");
# mDraw.SetDuration(PROCESSOR.UpdateInterval());
# mDraw.SetColor(1.0, 0.5, 0.0);
# mDraw.SetLineSize(1);
# mDraw.BeginLines();
# mDraw.Vertex(PLATFORM.Location());
# mDraw.Vertex(mTargetPoint);
# mDraw.End();
# }
end_execute
parallel
precondition
WsfTrack target = ((WsfRIPRProcessor)PROCESSOR).GetTarget();
if (target.IsNull() || !target.IsValid()) {
return Failure("target track not found");
}
if (!target.AirDomain()) {
#writeln("track is not for an air-domain target");
return Failure("track is not for an air-domain target");
}
return true;
end_precondition
behavior_node pursue_heading
behavior_node pursue_altitude
behavior_node pursue_speed
behavior_node pursue_fly_simple
end_parallel
end_behavior