From fa8b599234c8eb1e2944f9575e7e5207da5fbb54 Mon Sep 17 00:00:00 2001 From: "Jon S. Berndt" Date: Fri, 15 Sep 2023 12:37:00 -0600 Subject: [PATCH 1/5] Adding capability to aim external forces in inertial frame; added example to do orbital phasing --- aircraft/ball/ball.xml | 69 +++++++++++++++++++++-- aircraft/ball/iss_orbit.xml | 29 ++++++++++ scripts/ball_orbit_phase.xml | 92 +++++++++++++++++++++++++++++++ src/models/FGExternalForce.cpp | 5 ++ src/models/FGExternalForce.h | 1 + src/models/propulsion/FGForce.cpp | 2 + src/models/propulsion/FGForce.h | 2 +- 7 files changed, 194 insertions(+), 6 deletions(-) create mode 100644 aircraft/ball/iss_orbit.xml create mode 100644 scripts/ball_orbit_phase.xml diff --git a/aircraft/ball/ball.xml b/aircraft/ball/ball.xml index f555528b8b..6d761d99bf 100644 --- a/aircraft/ball/ball.xml +++ b/aircraft/ball/ball.xml @@ -55,7 +55,7 @@ -0 -0 -0 - 40 + 20000 0 0 @@ -100,7 +100,8 @@ fcs/parachute_reef_pos_norm - + propulsion/rocket_thrust + @@ -121,19 +122,77 @@ - -1 + -1 + 0 + 0 + + + + + + propulsion/rocket_thrust + + + 0 0 0 + + + + 0 + 0 + 0 + - + + + + + + + + -velocities/eci-x-fps + velocities/eci-velocity-mag-fps + + + external_reactions/rocket/x + + + + + + -velocities/eci-y-fps + velocities/eci-velocity-mag-fps + + + external_reactions/rocket/y + + + + + + -velocities/eci-z-fps + velocities/eci-velocity-mag-fps + + + external_reactions/rocket/z + + + + + diff --git a/aircraft/ball/iss_orbit.xml b/aircraft/ball/iss_orbit.xml new file mode 100644 index 0000000000..d88a549c64 --- /dev/null +++ b/aircraft/ball/iss_orbit.xml @@ -0,0 +1,29 @@ + + + + + + -4084.03 + -5429.69 + -0.5567 + + + + 90.0 + + + + 3.813252 + -2.858118 + 6.003066 + + + + 0.0 + 0.0 + + + diff --git a/scripts/ball_orbit_phase.xml b/scripts/ball_orbit_phase.xml new file mode 100644 index 0000000000..7de04d7de7 --- /dev/null +++ b/scripts/ball_orbit_phase.xml @@ -0,0 +1,92 @@ + + + + + + + Integrators + + 0: No integrator (Freeze) + 1: Rectangular Euler + 2: Trapezoidal + 3: Adams Bashforth 2 + 4: Adams Bashforth 3 + 5: Adams Bashforth 4 + + + simulation/integrator/rate/rotational + simulation/integrator/rate/translational + simulation/integrator/position/rotational + simulation/integrator/position/translational + simulation/gravity-model + simulation/output[0]/log_rate_hz + + simulation/notify-time-trigger + + + Output message at 10 minute intervals + + position/h-agl-ft + position/geod-alt-ft + position/lat-geod-deg + position/radius-to-vehicle-ft + velocities/eci-velocity-mag-fps + velocities/u-fps + simulation/frame + atmosphere/rho-slugs_ft3 + orbital/specific-angular-momentum-ft2_sec + orbital/inclination-deg + orbital/right-ascension-deg + orbital/argument-of-perigee-deg + orbital/period-sec + orbital/eccentricity + orbital/apoapsis-radius-ft + orbital/periapsis-radius-ft + orbital/true-anomaly-deg + + simulation/sim-time-sec >= simulation/notify-time-trigger + + + + + Lower perigee + + simulation/sim-time-sec gt 10 + + + + simulation/sim-time-sec + + + + + Stop lowering perigee + + simulation/sim-time-sec gt 30 + + + + simulation/sim-time-sec + + + + + + + diff --git a/src/models/FGExternalForce.cpp b/src/models/FGExternalForce.cpp index 6c938d5f1c..a259f758b3 100644 --- a/src/models/FGExternalForce.cpp +++ b/src/models/FGExternalForce.cpp @@ -103,6 +103,8 @@ FGParameter* FGExternalForce::bind(Element *el, const string& magName, ttype = tLocalBody; } else if (sFrame == "WIND") { ttype = tWindBody; + } else if (sFrame == "INERTIAL") { + ttype = tInertialBody; } else { cerr << el->ReadFrom() << "Invalid frame specified for external " << el->GetName() << ", \"" @@ -239,6 +241,9 @@ void FGExternalForce::Debug(int from) case tWindBody: cout << "WIND"; break; + case tInertialBody: + cout << "INERTIAL"; + break; default: cout << "ERROR/UNKNOWN"; } diff --git a/src/models/FGExternalForce.h b/src/models/FGExternalForce.h index 5b1252a207..c231b6b7a1 100644 --- a/src/models/FGExternalForce.h +++ b/src/models/FGExternalForce.h @@ -111,6 +111,7 @@ CLASS DOCUMENTATION completes the right handed system. This is modified from a normal wind frame definition, which is rotated about the Y axis 180 degrees from this WIND frame. + - INERTIAL frame refers to the ECI frame. Much of the substance of this class is located in the FGForce base class, from which this class is derived. diff --git a/src/models/propulsion/FGForce.cpp b/src/models/propulsion/FGForce.cpp index 33e2f5e701..f7f82d09cd 100644 --- a/src/models/propulsion/FGForce.cpp +++ b/src/models/propulsion/FGForce.cpp @@ -101,6 +101,8 @@ const FGMatrix33& FGForce::Transform(void) const return fdmex->GetAuxiliary()->GetTw2b(); case tLocalBody: return fdmex->GetPropagate()->GetTl2b(); + case tInertialBody: + return fdmex->GetPropagate()->GetTi2b(); case tCustom: case tNone: return mT; diff --git a/src/models/propulsion/FGForce.h b/src/models/propulsion/FGForce.h index e6458d2e7b..84e3bc7543 100644 --- a/src/models/propulsion/FGForce.h +++ b/src/models/propulsion/FGForce.h @@ -227,7 +227,7 @@ class JSBSIM_API FGForce : public FGJSBBase /// Destructor virtual ~FGForce(); - enum TransformType { tNone, tWindBody, tLocalBody, tCustom }; + enum TransformType { tNone, tWindBody, tLocalBody, tInertialBody, tCustom }; virtual const FGColumnVector3& GetBodyForces(void); From e64f66142f358cd62b00d9e0ba302d283a4de926 Mon Sep 17 00:00:00 2001 From: "Jon S. Berndt" Date: Fri, 22 Sep 2023 08:31:22 -0600 Subject: [PATCH 2/5] Further refinements and corrections; added additional orbital maneuvers --- aircraft/ball/ball.xml | 20 ++++-------- scripts/ball_orbit_phase.xml | 62 ++++++++++++++++++++++++++---------- 2 files changed, 52 insertions(+), 30 deletions(-) diff --git a/aircraft/ball/ball.xml b/aircraft/ball/ball.xml index 6d761d99bf..c265d73b6e 100644 --- a/aircraft/ball/ball.xml +++ b/aircraft/ball/ball.xml @@ -108,7 +108,7 @@ aero/qbar-psf fcs/parachute_reef_pos_norm 1.0 - 20.0 + 10000.0 - - 0 - 0 - 0 - @@ -163,7 +157,7 @@ - -velocities/eci-x-fps + velocities/eci-x-fps velocities/eci-velocity-mag-fps @@ -173,7 +167,7 @@ - -velocities/eci-y-fps + velocities/eci-y-fps velocities/eci-velocity-mag-fps @@ -183,7 +177,7 @@ - -velocities/eci-z-fps + velocities/eci-z-fps velocities/eci-velocity-mag-fps diff --git a/scripts/ball_orbit_phase.xml b/scripts/ball_orbit_phase.xml index 7de04d7de7..3483b043c6 100644 --- a/scripts/ball_orbit_phase.xml +++ b/scripts/ball_orbit_phase.xml @@ -50,21 +50,21 @@ - + Lower perigee simulation/sim-time-sec gt 10 - + simulation/sim-time-sec - + Stop lowering perigee - simulation/sim-time-sec gt 30 + simulation/sim-time-sec gt 12 @@ -72,21 +72,49 @@ - + + + + Circularize orbit below station (Thrust is in negative direction here) + + simulation/sim-time-sec gt 5591 + + + + simulation/sim-time-sec + + + + + Stop circularizing orbit below station + + simulation/sim-time-sec gt 5598 + + + + simulation/sim-time-sec + + From ad47b907152d4f0691c4019399ffc42520eb8e40 Mon Sep 17 00:00:00 2001 From: "Jon S. Berndt" Date: Fri, 22 Sep 2023 14:33:50 -0600 Subject: [PATCH 3/5] Fix parachute area in test --- tests/TestExternalReactions.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/TestExternalReactions.py b/tests/TestExternalReactions.py index 316f004056..f36e087439 100644 --- a/tests/TestExternalReactions.py +++ b/tests/TestExternalReactions.py @@ -54,7 +54,7 @@ def test_wind_frame(self): while fdm.run(): Tw2b = fdm.get_auxiliary().get_Tw2b() - mag = fdm['aero/qbar-psf'] * fdm['fcs/parachute_reef_pos_norm']*20.0 + mag = fdm['aero/qbar-psf'] * fdm['fcs/parachute_reef_pos_norm']*10000.0 f = Tw2b * np.mat([-1.0, 0.0, 0.0]).T * mag self.assertAlmostEqual(fdm['forces/fbx-external-lbs'], f[0, 0]) self.assertAlmostEqual(fdm['forces/fby-external-lbs'], f[1, 0]) From 3055b0134014f40786c6ed19dcdaad1c7d56a32a Mon Sep 17 00:00:00 2001 From: Bertrand Coconnier Date: Sat, 23 Sep 2023 13:43:34 +0200 Subject: [PATCH 4/5] Remove the hardcoded value of the parachute area. --- tests/TestExternalReactions.py | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/tests/TestExternalReactions.py b/tests/TestExternalReactions.py index f36e087439..8bd0299b6c 100644 --- a/tests/TestExternalReactions.py +++ b/tests/TestExternalReactions.py @@ -199,8 +199,7 @@ def test_body_frame(self): def test_moment(self): script_path = self.sandbox.path_to_jsbsim_file('scripts', 'ball_chute.xml') - tree, aircraft_name, _ = CopyAircraftDef(script_path, - self.sandbox) + tree, aircraft_name, _ = CopyAircraftDef(script_path, self.sandbox) extReact_element = tree.getroot().find('external_reactions') moment_element = et.SubElement(extReact_element, 'moment') moment_element.attrib['name'] = 'parachute' @@ -229,9 +228,14 @@ def test_moment(self): fdm['external_reactions/parachute/magnitude-lbsft'] = -3.5 + # Compute the parachute_area + parachute_area = 1.0 + for value in extReact_element.findall('force/function/product/value'): + parachute_area *= float(value.text) + while fdm.run(): Tw2b = fdm.get_auxiliary().get_Tw2b() - mag = fdm['aero/qbar-psf'] * fdm['fcs/parachute_reef_pos_norm']*20.0 + mag = fdm['aero/qbar-psf'] * fdm['fcs/parachute_reef_pos_norm']*parachute_area f = Tw2b * np.mat([-1.0, 0.0, 0.0]).T * mag self.assertAlmostEqual(fdm['forces/fbx-external-lbs'], f[0, 0]) self.assertAlmostEqual(fdm['forces/fby-external-lbs'], f[1, 0]) From 0e5f57904f12f02ae793cb09f8c6bc71125e8755 Mon Sep 17 00:00:00 2001 From: Bertrand Coconnier Date: Sat, 23 Sep 2023 14:02:22 +0200 Subject: [PATCH 5/5] Fix all hardcoded values to the parachute area. --- tests/TestExternalReactions.py | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/tests/TestExternalReactions.py b/tests/TestExternalReactions.py index 8bd0299b6c..8f335c5238 100644 --- a/tests/TestExternalReactions.py +++ b/tests/TestExternalReactions.py @@ -23,6 +23,12 @@ from JSBSim_utils import JSBSimTestCase, CreateFDM, RunTest, CopyAircraftDef +def getParachuteArea(tree): + parachute_area = 1.0 + for value in tree.getroot().findall('external_reactions/force/function/product/value'): + parachute_area *= float(value.text) + return parachute_area + class TestExternalReactions(JSBSimTestCase): def getLeverArm(self, fdm, name): lax = (fdm['external_reactions/'+name+'/location-x-in'] @@ -52,9 +58,12 @@ def test_wind_frame(self): self.assertAlmostEqual(fdm['external_reactions/parachute/y'], 0.0) self.assertAlmostEqual(fdm['external_reactions/parachute/z'], 0.0) + tree, _, _ = CopyAircraftDef(script_path, self.sandbox) + parachute_area = getParachuteArea(tree) + while fdm.run(): Tw2b = fdm.get_auxiliary().get_Tw2b() - mag = fdm['aero/qbar-psf'] * fdm['fcs/parachute_reef_pos_norm']*10000.0 + mag = fdm['aero/qbar-psf'] * fdm['fcs/parachute_reef_pos_norm']*parachute_area f = Tw2b * np.mat([-1.0, 0.0, 0.0]).T * mag self.assertAlmostEqual(fdm['forces/fbx-external-lbs'], f[0, 0]) self.assertAlmostEqual(fdm['forces/fby-external-lbs'], f[1, 0]) @@ -227,11 +236,7 @@ def test_moment(self): self.assertAlmostEqual(fdm['external_reactions/parachute/n'], mDir[2]) fdm['external_reactions/parachute/magnitude-lbsft'] = -3.5 - - # Compute the parachute_area - parachute_area = 1.0 - for value in extReact_element.findall('force/function/product/value'): - parachute_area *= float(value.text) + parachute_area = getParachuteArea(tree) while fdm.run(): Tw2b = fdm.get_auxiliary().get_Tw2b()