This commit is contained in:
2025-09-12 15:20:28 +08:00
commit 3257a14c32
449 changed files with 388780 additions and 0 deletions

View File

@@ -0,0 +1,242 @@
# ****************************************************************************
# 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.
# ****************************************************************************
// functions to fly in formation
script_variables
// the proximity in which I think I've achieved the waypoint (nm)
double cWAYPOINT_PROXIMITY = 0.2 * MATH.M_PER_NM();
// the range that I think I'm far from my waypoint and need to fly a "max" speed to catch up
double cFAR_FROM_WAYPOINT = 5.0 * MATH.M_PER_NM();
// the slowest I will fly to get back into formation
double cMIN_MACH = 0.6;
// the fastest I will fly to get back into formation
double cMAX_MACH = 1.5;
// once I'm in formation, the range that I think I'm out again
double cOUT_OF_FORMATION = 2.0 * MATH.M_PER_NM();
bool mInFormation = false;
end_script_variables
script void formation_initialize(double aWaypointProximity,
double aFarFromWaypoint,
double aMinMach,
double aMaxMach,
double aOutOfFormation)
// set the constants base on the inputs
// allows users to parameterize their own formation
cWAYPOINT_PROXIMITY = aWaypointProximity;
cFAR_FROM_WAYPOINT = aFarFromWaypoint;
cMIN_MACH = aMinMach;
cMAX_MACH = aMaxMach;
cOUT_OF_FORMATION = aOutOfFormation;
end_script
script void waypoint_behind_logic(WsfWaypoint aWaypoint,
WsfPlatform aLeadPlatform,
WsfPlatform aExternalPlatform)
// what's the minimum I want to fly to let the waypoint "catch up"?
// a fraction of my lead's mach
double machToFly = aExternalPlatform.MachNumber();
double rangeToWaypoint = PLATFORM.SlantRangeTo(aWaypoint);
double relBearing = PLATFORM.RelativeBearingTo(aWaypoint.Latitude(), aWaypoint.Longitude(), aWaypoint.Altitude());
double absBearing = PLATFORM.TrueBearingTo(aWaypoint.Latitude(), aWaypoint.Longitude(), aWaypoint.Altitude());
writeln_d(" wbl, mach: ", machToFly, ", range: ", rangeToWaypoint, ", relBearing: ", relBearing);
// if I've reached my waypoint, just fly my lead's heading
if (rangeToWaypoint <= cWAYPOINT_PROXIMITY)
{
writeln_d(" in formation!");
mInFormation = true;
}
// if I'm far from my waypoint, fly a scale of my lead's speed
else if (rangeToWaypoint > cFAR_FROM_WAYPOINT)
{
writeln_d(" far from formation!");
// fly a fraction of my lead's speed and let the waypoint catch up
// machToFly = cMIN_MACH;
machToFly = cMAX_MACH;
PLATFORM.GoToMachNumber(machToFly);
// PLATFORM.GoToLocation(aWaypoint);
PLATFORM.TurnToHeading(absBearing);
PLATFORM.GoToAltitude(aExternalPlatform.Altitude());
}
// if I haven't reached my waypoint yet
else if (rangeToWaypoint > cWAYPOINT_PROXIMITY)
{
writeln_d(" close, but not in formation!");
// some speed in the middle representative of the range
// "slow down as the waypoint approaches me"
double multiplier = MATH.Sqrt(
(rangeToWaypoint - cWAYPOINT_PROXIMITY) /
(cFAR_FROM_WAYPOINT - cWAYPOINT_PROXIMITY));
multiplier = MATH.Sqrt(multiplier);
machToFly = machToFly - ((machToFly - cMIN_MACH) * multiplier);
// fly in front of the waypoint so when it reaches me, i'm flying on the same line with it
double angle = 0.0;
if (relBearing <= 0.0)
{
angle = 90.0;
}
else
{
angle = -90.0;
}
writeln_d(" angle == ", angle);
double newAngle = angle * (relBearing + 180.0) / 360.0;
writeln_d(" newAngle == ", newAngle);
if (newAngle > 45.0)
{
newAngle = 45.0;
}
if (newAngle < -45.0)
{
newAngle = -45.0;
}
writeln_d(" newAngle == ", newAngle);
double heading = aExternalPlatform.Heading() + newAngle;
writeln_d(" new heading == ", heading);
PLATFORM.TurnToHeading(heading);
PLATFORM.GoToMachNumber(machToFly);
PLATFORM.GoToAltitude(aExternalPlatform.Altitude());
}
end_script
script void waypoint_in_front_logic(WsfWaypoint aWaypoint,
WsfPlatform aLeadPlatform,
WsfPlatform aExternalPlatform)
// what's the maximum I want to fly to catch up to the waypont?
// a scale of my lead's mach
double machToFly = aExternalPlatform.MachNumber();
double rangeToWaypoint = PLATFORM.SlantRangeTo(aWaypoint);
double absBearing = PLATFORM.TrueBearingTo(aWaypoint.Latitude(), aWaypoint.Longitude(), aWaypoint.Altitude());
writeln_d(" wifl, mach: ", machToFly, ", range: ", rangeToWaypoint);
// if I've reached my waypoint, just fly my lead's heading
if (rangeToWaypoint <= cWAYPOINT_PROXIMITY)
{
writeln_d(" in formation!");
mInFormation = true;
PLATFORM.TurnToHeading(aExternalPlatform.Heading());
PLATFORM.GoToMachNumber(machToFly);
PLATFORM.GoToAltitude(aExternalPlatform.Altitude());
}
// if I'm really far from my waypoint, fly a scale of my lead's speed
else if (rangeToWaypoint > cFAR_FROM_WAYPOINT)
{
writeln_d(" far from formation!");
// fly a multiple of my lead's speed and catch up to the waypoint
// using lead pursuit
machToFly = cMAX_MACH;
PLATFORM.GoToMachNumber(machToFly);
// double lat = aWaypoint.Latitude();
// double lon = aWaypoint.Longitude();
// XXX ???? mSoarAirAgent.PushWaypointToLead(aWaypoint, aExternalPlatform.TruthId());
// PLATFORM.GoToLocation(aWaypoint);
PLATFORM.TurnToHeading(absBearing);
PLATFORM.GoToAltitude(aExternalPlatform.Altitude());
}
// if i haven't reached my waypoint yet
else if (rangeToWaypoint > cWAYPOINT_PROXIMITY)
{
writeln_d(" close but not in formation!");
// some speed in the middle representative of the range
// "slow down as I approach the waypoint"
double multiplier = MATH.Sqrt(
(rangeToWaypoint - (cWAYPOINT_PROXIMITY)) /
(cFAR_FROM_WAYPOINT - (cWAYPOINT_PROXIMITY)));
multiplier = MATH.Sqrt(multiplier);
machToFly = machToFly + ((cMAX_MACH - machToFly) * multiplier);
PLATFORM.GoToMachNumber(machToFly);
// double lat = aWaypoint.Latitude();
// double lon = aWaypoint.Longitude();
// XXX ???? mSoarAirAgent.PushWaypointToLead(aWaypoint, aExternalPlatform.TruthId());
PLATFORM.TurnToHeading(absBearing);
// PLATFORM.GoToLocation(aWaypoint);
}
end_script
script void formation_logic(WsfWaypoint aWaypoint,
WsfPlatform aLeadPlatform,
WsfPlatform aExternalPlatform,
bool aTightFormation)
// is waypoint behind or in front of me?
double relBearing = PLATFORM.RelativeBearingTo(aWaypoint.Latitude(), aWaypoint.Longitude(), aWaypoint.Altitude());
double waypointRange = PLATFORM.SlantRangeTo(aWaypoint);
writeln_d(" relBearing: ", relBearing, ", waypointRange: ", waypointRange);
// if waypoint is behind me and I'm somewhat close to it, just let it catch up to me
if (MATH.Fabs(relBearing) > 90 && waypointRange < 20.0 * MATH.M_PER_NM())
{
writeln_d(" waypoint behind, relBearing:", relBearing);
waypoint_behind_logic(aWaypoint, aLeadPlatform, aExternalPlatform);
}
else // waypoint is in front of me
{
writeln_d(" waypoint in front, relBearing: ", relBearing);
// if I'm in formation, don't get out of it easily
if ((aTightFormation == false) && (mInFormation == true))
{
// check if I'm still in formation
if (waypointRange >= cOUT_OF_FORMATION)
{
mInFormation = false;
}
else
{
// fly my lead's heading
PLATFORM.TurnToHeading(aExternalPlatform.Heading());
PLATFORM.GoToMachNumber(aExternalPlatform.MachNumber());
PLATFORM.GoToAltitude(aExternalPlatform.Altitude());
return;
}
}
waypoint_in_front_logic(aWaypoint, aLeadPlatform, aExternalPlatform);
}
end_script
script void formation_update(WsfPlatform aLeadPlatform)
WsfWaypoint formationPoint = WsfWaypoint();
WsfWaypoint leadPoint = WsfWaypoint();
int followingIndex = GetFollowingFormationIndex();
WsfPlatform following = mFlightLeadAgent.GetPlatformInFormation(followingIndex);
int flightLeadIndex = mFlightLeadAgent.GetFormationIndex(mFlightLeadAgent.GetPlatformInFormation(-1));
if (followingIndex == flightLeadIndex)
{
// get the formation point for my position
if ((mFlightLeadAgent.GetFormationPosition(PLATFORM, formationPoint)) == false)
{
return;
}
}
else
{
PROCESSOR.FollowPlatform(following, 110.0, 1.5 * MATH.M_PER_NM(), formationPoint);
}
writeln_d(" following: ", followingIndex, ", flightLeadIndex: ", flightLeadIndex);
writeln_d(" me: (", PLATFORM.Latitude(), ", ", PLATFORM.Longitude(), ", ", PLATFORM.Altitude(), ")");
writeln_d(" to: (", formationPoint.Latitude(), ", ", formationPoint.Longitude(), ", ", formationPoint.Altitude(), ")");
// fly formation logic
formation_logic(formationPoint, aLeadPlatform, following, false);
end_script

View File

@@ -0,0 +1,201 @@
# ****************************************************************************
# 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.
# ****************************************************************************
//compile_debug true
script_variables
// TEMPORARY eventually get this from a waypoint or a battle manager
string mManeuverName = "la";
string mFlightName = "four";
int mFlightIndex = -1;
bool mFirstPass = true;
WsfAIFLProcessor mFlightLeadAgent;
end_script_variables
include_once aiai_scripts.txt
include_once formation.script
include_once la_methods.script
on_initialize
// check in to the FlightLead agent
mFlightLeadAgent = (WsfAIFLProcessor)(PROCESSOR.GetCommander());
writeln_d(" mFlightLeadAgent.IsValid() == ", mFlightLeadAgent.IsValid());
// mFlightLeadAgent.CheckIn(PLATFORM, false);
// tweak the formation flying for fueling
formation_initialize(0.2 * MATH.M_PER_NM(), // waypoint proximity
5.0 * MATH.M_PER_NM(), // far from waypoint
0.4, // min mach
1.5, // max mach
2.0 * MATH.M_PER_NM()); // out of formation
aiai_initialize();
end_on_initialize
script void lead_wait_logic()
// get the tracks from my flight
WsfLocalTrackList flightTracks = mFlightLeadAgent.FlightTrackList();
// assume targets are in-bound to my flight and find the smallest range
// target selection should be done A LOT better
double minRange = 9999999.9;
WsfTrack closestTrack = NULL;
foreach (WsfTrack track in flightTracks)
{
if (DetermineTargetType(track) == "unknown")
{
continue;
}
double thisRange = PLATFORM.SlantRangeTo(track);
writeln_d(" considering: ", track.TargetName(), " at ", thisRange);
if (thisRange < minRange)
{
minRange = thisRange;
closestTrack = track;
}
}
// if I'm within range of to start the formation tactic, do it
if (minRange < cSTART_MANEUVER_RANGE && closestTrack.IsValid())
{
writeln_d("Maneuver started at range: ", minRange);
mFlightLeadAgent.TargetSet(closestTrack);
PLATFORM.Comment("Maneuver started...");
mFlightLeadAgent.SetTopState("FLIGHT_MANEUVER");
}
if (closestTrack.IsValid())
{
mFlightLeadAgent.TargetSet(closestTrack);
PLATFORM.Comment("Range to target: " + (string)minRange);
// turn towards the track
double heading = PLATFORM.TrueBearingTo(closestTrack);
PLATFORM.TurnToHeading(heading);
PLATFORM.GoToAltitude(closestTrack.Altitude());
PLATFORM.GoToSpeed(cINTERCEPT_SPEED);
}
else
{
// PLATFORM.GoToAltitude(cDEFAULT_ALTITUDE);
// PLATFORM.GoToSpeed(cWAIT_SPEED);
}
end_script
on_update
string flightTopState = "*NO*FLIGHT*LEAD*";
writeln_d("--- four on_update Platform: ", PLATFORM.Name(), ", Time: ", TIME_NOW);
// string myTopState = PLATFORM.GetTopState();
if (!mFlightLeadAgent.IsValid())
{
mFlightLeadAgent = (WsfAIFLProcessor)(PROCESSOR.GetCommander());
if (mFlightLeadAgent.IsValid())
{
writeln_d(" acquired mFlightLeadAgent ", mFlightLeadAgent.Name());
}
else
{
// aiai_update();
// can't do anything without a FL
return;
}
}
flightTopState = mFlightLeadAgent.GetTopState();
writeln_d(" flightTopState: ", flightTopState);
// one time transition to FLIGHT_WAIT state
// if ((myTopState == "STRAIGHT") && (mFirstPass == true))
if (mFirstPass == true)
{
mFlightLeadAgent.AssignNewLead(0);
// PLATFORM.SetTopState("FLIGHT_WAIT");
mFirstPass = false;
}
// if my flight has been disrupted, just go to ai logic
if (!mFlightLeadAgent.FlightIntact())
{
aiai_update();
return;
}
// the flight is waiting for something to act on
// - lead flies straight and level
// - flight follows the lead in formation
writeln_d(" mFlightIndex: ", mFlightIndex);
// if (myTopState == "FLIGHT_WAIT")
// extern string mFlightName;
if (mFlightName == "four")
{
writeln_d(" four...");
// if lead has commanded to do the maneuver, do it
if (flightTopState == "FLIGHT_SOLO")
{
aiai_update();
return;
}
else if (flightTopState == "FLIGHT_MANEUVER")
{
writeln_d(" FLIGHT_MANEUVER...");
// get my position in the flight if not done already
// if (mFlightIndex < 0)
// {
mFlightIndex = mFlightLeadAgent.GetFormationIndex(PLATFORM) + 1;
writeln_d(" mFlightIndex acquired == ", mFlightIndex);
// }
perform_maneuver(mFlightIndex);
}
else if (flightTopState == "FLIGHT_RELEASE")
{
if (mFlightLeadAgent.GetLeadStatus(PLATFORM) == true && !mFlightLeadAgent.TargetPlatformGet().IsValid())
{
writeln_d(" target dead, FLIGHT_WAIT");
mFlightLeadAgent.SetTopState("FLIGHT_WAIT");
// PLATFORM.FollowRoute("DEFAULT_ROUTE", "CLOSEST_POINT");
PLATFORM.FollowRoute("DEFAULT_ROUTE");
return;
}
writeln_d(" FLIGHT_RELEASE...");
aiai_update();
return;
}
else
{
writeln_d(" other (", flightTopState, ")...");
if (mFlightLeadAgent.GetLeadStatus(PLATFORM) == true)
{
writeln_d(" I am lead, so wait");
SetUpdateInterval(cFAST_UPDATE_RATE);
// PLATFORM.GoToLocation(0, 0, 0); // trying to trick mover so next FollowRoute works right
// PLATFORM.FollowRoute("DEFAULT_ROUTE", "CLOSEST_POINT");
// PLATFORM.FollowRoute("line", "CLOSEST_POINT");
lead_wait_logic();
}
else
{
writeln_d(" follow the leader");
// follow the lead
WsfPlatform leadPlatform = mFlightLeadAgent.GetPlatformInFormation(-1);
SetFollowingFormationIndex(-1);
mManeuverState = 0;
SetUpdateInterval(cFAST_UPDATE_RATE);
formation_update(leadPlatform);
}
}
}
end_on_update