# **************************************************************************** # 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