def test_direct_steer(self): fdm = CreateFDM(self.sandbox) fdm.load_model('c172r') aircraft_path = self.sandbox.path_to_jsbsim_file('aircraft') fdm.load_ic(os.path.join(aircraft_path, 'c172r', 'reset00'), False) fdm.run_ic() self.assertAlmostEqual(fdm['fcs/steer-cmd-norm'], 0.0) self.assertAlmostEqual(fdm['fcs/steer-pos-deg'], 0.0) # Should be part of a unit test in C++ ? fpectl.turnon_sigfpe() grndreact = fdm.get_ground_reactions() for i in xrange(grndreact.get_num_gear_units()): gear = grndreact.get_gear_unit(i) self.assertEqual(gear.get_steer_norm(), 0.0) fpectl.turnoff_sigfpe() fdm['fcs/steer-pos-deg'] = 5.0 self.assertAlmostEqual(fdm['fcs/steer-pos-deg'], 5.0) fdm.run() self.assertAlmostEqual(fdm['fcs/steer-cmd-norm'], 0.0) fdm['fcs/steer-cmd-norm'] = 1.0 self.assertAlmostEqual(fdm['fcs/steer-cmd-norm'], 1.0) fdm.run() self.assertAlmostEqual(fdm['fcs/steer-cmd-norm'], 1.0) self.assertAlmostEqual(fdm['fcs/steer-pos-deg'], 10.0)
def test_humidity_parameters(self): # Table: Dew point (deg C), Vapor pressure (Pa), RH humidity_table = [ (-40.0, 19.021201, 0.815452, 1.2040321), (-30.0, 51.168875, 2.193645, 1.2038877), (-20.0, 125.965126, 5.4002118, 1.2035517), (-10.0, 287.031031, 12.3052182, 1.2028282), ( 0.0, 611.2, 26.2025655, 1.2013721), ( 10.0, 1226.030206, 52.5607604, 1.1986102), ( 20.0, 2332.5960221, 100., 1.1936395) ] fdm = CreateFDM(self.sandbox) fdm.load_model('ball') fdm['atmosphere/delta-T'] = 5.0*self.K_to_R fdm.run_ic() Psat = fdm['atmosphere/saturated-vapor-pressure-psf']/self.Pa_to_psf self.assertAlmostEqual(Psat, humidity_table[-1][1]) self.assertAlmostEqual(fdm['atmosphere/vapor-pressure-psf'], 0.0) self.assertAlmostEqual(fdm['atmosphere/RH'], 0.0) self.assertAlmostEqual(fdm['atmosphere/dew-point-R'], 54.054) for Tdp, Pv, RH, rho in humidity_table: fdm['atmosphere/dew-point-R'] = (Tdp+273.15)*self.K_to_R fdm.run_ic() self.assertAlmostEqual(fdm['atmosphere/vapor-pressure-psf'], Pv*self.Pa_to_psf) self.assertAlmostEqual(fdm['atmosphere/RH'], RH) self.assertAlmostEqual(fdm['atmosphere/rho-slugs_ft3']/(self.kg_to_slug*math.pow(0.3048,3)), rho) del fdm
def testKinematicTiming(self): fdm = CreateFDM(self.sandbox) fdm.load_model('c172r') fdm.load_ic(self.sandbox.path_to_jsbsim_file('aircraft', 'c172r', 'reset00'), False) fdm.run_ic() self.assertEqual(fdm['fcs/flap-cmd-norm'], 0.0) self.assertEqual(fdm['fcs/flap-pos-deg'], 0.0) # Test the flap down sequence. The flap command is set to a value # higher than 1.0 to check that JSBSim clamps it to 1.0 fdm['fcs/flap-cmd-norm'] = 1.5 t = fdm['simulation/sim-time-sec'] while t < 2.0: self.assertAlmostEqual(fdm['fcs/flap-pos-deg'], 5.*t) fdm.run() t = fdm['simulation/sim-time-sec'] while t < 4.0: self.assertAlmostEqual(fdm['fcs/flap-pos-deg'], 10.*(t-1.)) fdm.run() t = fdm['simulation/sim-time-sec'] while t < 5.0: self.assertAlmostEqual(fdm['fcs/flap-pos-deg'], 30.) fdm.run() t = fdm['simulation/sim-time-sec'] # Test the flap up sequence with an interruption at 7.5 deg fdm['fcs/flap-cmd-norm'] = 0.25 while t < 7.0: self.assertAlmostEqual(fdm['fcs/flap-pos-deg'], 30.-10.*(t-5.)) fdm.run() t = fdm['simulation/sim-time-sec'] while t < 7.5: self.assertAlmostEqual(fdm['fcs/flap-pos-deg'], 10.-5.*(t-7.)) fdm.run() t = fdm['simulation/sim-time-sec'] while t < 8.0: self.assertAlmostEqual(fdm['fcs/flap-pos-deg'], 7.5) fdm.run() t = fdm['simulation/sim-time-sec'] # Complete the flap up sequence. The flap command is set to a value # lower than 0.0 to check that JSBSim clamps it to 0.0 fdm['fcs/flap-cmd-norm'] = -1. while t < 9.5: self.assertAlmostEqual(fdm['fcs/flap-pos-deg'], 10.-5.*(t-7.5)) fdm.run() t = fdm['simulation/sim-time-sec'] while t < 10.0: self.assertAlmostEqual(fdm['fcs/flap-pos-deg'], 0.0) fdm.run() t = fdm['simulation/sim-time-sec']
def test_trim_on_ground(self): fdm = CreateFDM(self.sandbox) fdm.load_model('c172x') fdm['ic/theta-deg'] = 10.0 fdm.run_ic() fdm['ic/theta-deg'] = 0.0 fdm['simulation/do_simple_trim'] = 2
def test_set_temperature(self): fdm = CreateFDM(self.sandbox) fdm.load_model('ball') fdm.run_ic() atmos = fdm.get_atmosphere() eRankine = 3 # Check that there are no side effects if we call SetTemperature() # twice in a row. atmos.set_temperature(520, 0.0, eRankine) fdm.run_ic() self.assertAlmostEqual(1.0, fdm['atmosphere/T-R'] / 520.0) atmos.set_temperature(500, 0.0, eRankine) fdm.run_ic() self.assertAlmostEqual(1.0, fdm['atmosphere/T-R'] / 500.0) # Check that it works while a temperature gradient is set graded_delta_T_K = -10.0 fdm['atmosphere/SL-graded-delta-T'] = graded_delta_T_K * self.K_to_R atmos.set_temperature(530, 1000.0, eRankine) fdm['ic/h-sl-ft'] = 1000. fdm.run_ic() self.assertAlmostEqual(1.0, fdm['atmosphere/T-R'] / 530.0) del fdm
def test_pitot_angle(self): script_name = 'ball_chute.xml' script_path = self.sandbox.path_to_jsbsim_file('scripts', script_name) # Add a Pitot angle to the Cessna 172 tree, aircraft_name, path_to_jsbsim_aircrafts = CopyAircraftDef( script_path, self.sandbox) root = tree.getroot() pitot_angle_deg = 5.0 self.addPitotTube(root, 5.0) contact_tag = root.find('./ground_reactions/contact') contact_tag.attrib['type'] = 'STRUCTURE' tree.write( self.sandbox('aircraft', aircraft_name, aircraft_name + '.xml')) fdm = CreateFDM(self.sandbox) fdm.set_aircraft_path('aircraft') fdm.load_model('ball') pitot_angle = pitot_angle_deg * math.pi / 180. weight = fdm['inertia/weight-lbs'] spring_tag = contact_tag.find('./spring_coeff') spring_coeff = float(spring_tag.text) print("Weight=%d Spring=%d" % (weight, spring_coeff)) fdm['ic/h-sl-ft'] = weight / spring_coeff fdm['forces/hold-down'] = 1.0 fdm.run_ic() ExecuteUntil(fdm, 10.) for i in range(36): for j in range(-9, 10): angle = math.pi * i / 18.0 angle2 = math.pi * j / 18.0 ca2 = math.cos(angle2) fdm['atmosphere/wind-north-fps'] = 10. * math.cos(angle) * ca2 fdm['atmosphere/wind-east-fps'] = 10. * math.sin(angle) * ca2 fdm['atmosphere/wind-down-fps'] = 10. * math.sin(angle2) fdm.run() vg = fdm['velocities/vg-fps'] self.assertAlmostEqual(vg, 0.0, delta=1E-7) vt = fdm['velocities/vt-fps'] self.assertAlmostEqual(vt, 10., delta=1E-7) mach = vt / fdm['atmosphere/a-fps'] P = fdm['atmosphere/P-psf'] pt = P * math.pow(1 + 0.2 * mach * mach, 3.5) psl = fdm['atmosphere/P-sl-psf'] rhosl = fdm['atmosphere/rho-sl-slugs_ft3'] A = math.pow((pt - P) / psl + 1.0, 1.0 / 3.5) alpha = fdm['aero/alpha-rad'] beta = fdm['aero/beta-rad'] vc = math.sqrt( 7.0 * psl / rhosl * (A - 1.0)) * math.cos(alpha + pitot_angle) * math.cos(beta) self.assertAlmostEqual(fdm['velocities/vc-kts'], max(0.0, vc) / 1.68781, delta=1E-7)
def test_FG_reset(self): # This test reproduces how FlightGear resets. The important thing is # that the property manager is managed by FlightGear. So it is not # deleted when the JSBSim instance is killed. pm = jsbsim.FGPropertyManager(new_instance=True) self.assertFalse(pm.hasNode('fdm/jsbsim/ic/lat-geod-deg')) fdm = CreateFDM(self.sandbox, pm) fdm.load_model('ball') self.assertAlmostEqual(fdm['ic/lat-geod-deg'], 0.0) fdm['ic/lat-geod-deg'] = 45.0 fdm.run_ic() del fdm # Check that the property ic/lat-geod-deg has survived the JSBSim # instance. self.assertTrue(pm.hasNode('fdm/jsbsim/ic/lat-geod-deg')) # Re-use the property manager just as FlightGear does. fdm = CreateFDM(self.sandbox, pm) self.assertAlmostEqual(fdm['ic/lat-geod-deg'], 45.0) del fdm
def test_trim_doesnt_ignite_rockets(self): # Run a longitudinal trim with a rocket equipped with solid propellant # boosters (aka SRBs). The trim algorithm will try to reach a vertical # equilibrium by tweaking the throttle but since the rocket is nose up, # the trim cannot converge. As a result the algorithm will set full # throttle which will result in the SRBs ignition if the integration is # not suspended. This bug has been reported in FlightGear and this test # is checking that there is no regression. fdm = CreateFDM(self.sandbox) fdm.load_model('J246') fdm.load_ic(self.sandbox.path_to_jsbsim_file('aircraft', 'J246', 'LC39'), False) fdm.run_ic() # Check that the SRBs are not ignited self.assertEqual(fdm['propulsion/engine[0]/thrust-lbs'], 0.0) self.assertEqual(fdm['propulsion/engine[1]/thrust-lbs'], 0.0) try: fdm['simulation/do_simple_trim'] = 1 except RuntimeError as e: # The trim cannot succeed. Just make sure that the raised exception # is due to the trim failure otherwise rethrow. if e.args[0] != 'Trim Failed': raise # Check that the trim did not ignite the SRBs self.assertEqual(fdm['propulsion/engine[0]/thrust-lbs'], 0.0) self.assertEqual(fdm['propulsion/engine[1]/thrust-lbs'], 0.0)
def test_waypoint(self): fdm = CreateFDM(self.sandbox) fdm.load_model('c310') aircraft_path = self.sandbox.path_to_jsbsim_file('aircraft') fdm.load_ic(os.path.join(aircraft_path, 'c310', 'reset00'), False) slr = 20925646.32546 # Sea Level Radius TestCases = ((0.25*math.pi, 0.5*math.pi, 0.0, 0.0), (0.0, 0.5*math.pi, math.pi, slr*0.25*math.pi), # North pole (0.5*math.pi, 0.5*math.pi, 0.0, slr*0.25*math.pi), # South pole (-0.5*math.pi, 0.5*math.pi, math.pi, slr*0.75*math.pi), (0.0, 0.0, 1.5*math.pi, slr*0.5*math.pi), (0.0, math.pi, 0.5*math.pi, slr*0.5*math.pi)) fdm['ic/lat-gc-rad'] = TestCases[0][0] fdm['ic/long-gc-rad'] = TestCases[0][1] for case in TestCases: fdm['guidance/target_wp_latitude_rad'] = case[0] fdm['guidance/target_wp_longitude_rad'] = case[1] fdm.run_ic() self.assertAlmostEqual(fdm['guidance/wp-heading-rad'], case[2]) self.assertAlmostEqual(fdm['guidance/wp-distance'], case[3])
def test_trim_doesnt_ignite_rockets(self): # Run a longitudinal trim with a rocket equipped with solid propellant # boosters (aka SRBs). The trim algorithm will try to reach a vertical # equilibrium by tweaking the throttle but since the rocket is nose up, # the trim cannot converge. As a result the algorithm will set full # throttle which will result in the SRBs ignition if the integration is # not suspended. This bug has been reported in FlightGear and this test # is checking that there is no regression. fdm = CreateFDM(self.sandbox) fdm.load_model('J246') fdm.load_ic( self.sandbox.path_to_jsbsim_file('aircraft', 'J246', 'LC39'), False) fdm.run_ic() # Check that the SRBs are not ignited self.assertEqual(fdm['propulsion/engine[0]/thrust-lbs'], 0.0) self.assertEqual(fdm['propulsion/engine[1]/thrust-lbs'], 0.0) try: fdm['simulation/do_simple_trim'] = 1 except RuntimeError as e: # The trim cannot succeed. Just make sure that the raised exception # is due to the trim failure otherwise rethrow. if e.args[0] != 'Trim Failed': raise # Check that the trim did not ignite the SRBs self.assertEqual(fdm['propulsion/engine[0]/thrust-lbs'], 0.0) self.assertEqual(fdm['propulsion/engine[1]/thrust-lbs'], 0.0)
def test_steer_with_fcs(self): fdm = CreateFDM(self.sandbox) fdm.load_model('L410') aircraft_path = self.sandbox.path_to_jsbsim_file('aircraft') fdm.load_ic(os.path.join(aircraft_path, 'L410', 'reset00'), False) fdm.run_ic() self.assertAlmostEqual(fdm['fcs/steer-cmd-norm'], 0.0) self.assertAlmostEqual(fdm['fcs/steer-pos-deg'], 0.0) fdm['fcs/steer-cmd-norm'] = 1.0 self.assertAlmostEqual(fdm['fcs/steer-cmd-norm'], 1.0) fdm.run() self.assertAlmostEqual(fdm['fcs/steer-cmd-norm'], 1.0) self.assertAlmostEqual(fdm['fcs/steer-pos-deg'], 5.0) fdm['/controls/switches/full-steering-sw'] = 1.0 fdm.run() self.assertAlmostEqual(fdm['fcs/steer-cmd-norm'], 1.0) self.assertAlmostEqual(fdm['fcs/steer-pos-deg'], 0.0) fdm['/controls/switches/full-steering-sw'] = 2.0 fdm.run() self.assertAlmostEqual(fdm['fcs/steer-cmd-norm'], 1.0) self.assertAlmostEqual(fdm['fcs/steer-pos-deg'], 45.0) fdm['fcs/steer-cmd-norm'] = -0.5 fdm.run() self.assertAlmostEqual(fdm['fcs/steer-cmd-norm'], -0.5) self.assertAlmostEqual(fdm['fcs/steer-pos-deg'], -22.5)
def test_waypoint(self): fdm = CreateFDM(self.sandbox) fdm.load_model('c310') aircraft_path = self.sandbox.path_to_jsbsim_file('aircraft') fdm.load_ic(os.path.join(aircraft_path, 'c310', 'reset00'), False) slr = 20925646.32546 # Sea Level Radius TestCases = ( (0.25 * math.pi, 0.5 * math.pi, 0.0, 0.0), (0.0, 0.5 * math.pi, math.pi, slr * 0.25 * math.pi), # North pole (0.5 * math.pi, 0.5 * math.pi, 0.0, slr * 0.25 * math.pi), # South pole (-0.5 * math.pi, 0.5 * math.pi, math.pi, slr * 0.75 * math.pi), (0.0, 0.0, 1.5 * math.pi, slr * 0.5 * math.pi), (0.0, math.pi, 0.5 * math.pi, slr * 0.5 * math.pi)) fdm['ic/lat-gc-rad'] = TestCases[0][0] fdm['ic/long-gc-rad'] = TestCases[0][1] for case in TestCases: fdm['guidance/target_wp_latitude_rad'] = case[0] fdm['guidance/target_wp_longitude_rad'] = case[1] fdm.run_ic() self.assertAlmostEqual(fdm['guidance/wp-heading-rad'], case[2]) self.assertAlmostEqual(fdm['guidance/wp-distance'], case[3])
def test_std_atmosphere(self): fdm = CreateFDM(self.sandbox) fdm.load_model('ball') self.check_temperature(fdm, self.T0, 0.0) self.check_pressure(fdm, self.P0, self.T0, 0.0) del fdm
def test_trim_on_ground(self): # Check that the trim is made with up to date initial conditions fdm = CreateFDM(self.sandbox) fdm.load_model('c172x') fdm['ic/theta-deg'] = 10.0 fdm.run_ic() fdm['ic/theta-deg'] = 0.0 # If the trim fails, it will raise an exception fdm['simulation/do_simple_trim'] = 2
def test_asl_override_vs_geod_lat(self): fdm = CreateFDM(self.sandbox) fdm.load_model('c310') fdm.load_ic(self.sandbox.path_to_jsbsim_file('aircraft', 'c310', 'ellington.xml'), False) geod_lat = fdm['ic/lat-geod-deg'] fdm['ic/h-sl-ft'] = 35000. self.assertAlmostEqual(fdm['ic/lat-geod-deg'], geod_lat)
def test_pitot_angle(self): script_name = 'ball_chute.xml' script_path = self.sandbox.path_to_jsbsim_file('scripts', script_name) # Add a Pitot angle to the Cessna 172 tree, aircraft_name, path_to_jsbsim_aircrafts = CopyAircraftDef(script_path, self.sandbox) root = tree.getroot() pitot_angle_deg = 5.0 self.addPitotTube(root, 5.0) contact_tag = root.find('./ground_reactions/contact') contact_tag.attrib['type'] = 'STRUCTURE' tree.write(self.sandbox('aircraft', aircraft_name, aircraft_name+'.xml')) fdm = CreateFDM(self.sandbox) fdm.set_aircraft_path('aircraft') fdm.load_model('ball') pitot_angle = pitot_angle_deg * math.pi / 180. weight = fdm['inertia/weight-lbs'] spring_tag = contact_tag.find('./spring_coeff') spring_coeff = float(spring_tag.text) print "Weight=%d Spring=%d" % (weight, spring_coeff) fdm['ic/h-sl-ft'] = weight / spring_coeff fdm['forces/hold-down'] = 1.0 fdm.run_ic() ExecuteUntil(fdm, 10.) for i in xrange(36): for j in xrange(-9, 10): angle = math.pi * i / 18.0 angle2 = math.pi * j / 18.0 ca2 = math.cos(angle2) fdm['atmosphere/wind-north-fps'] = 10. * math.cos(angle) * ca2 fdm['atmosphere/wind-east-fps'] = 10. * math.sin(angle) * ca2 fdm['atmosphere/wind-down-fps'] = 10. * math.sin(angle2) fdm.run() vg = fdm['velocities/vg-fps'] self.assertAlmostEqual(vg, 0.0, delta=1E-7) vt = fdm['velocities/vt-fps'] self.assertAlmostEqual(vt, 10., delta=1E-7) mach = vt / fdm['atmosphere/a-fps'] P = fdm['atmosphere/P-psf'] pt = P * math.pow(1+0.2*mach*mach, 3.5) psl = fdm['atmosphere/P-sl-psf'] rhosl = fdm['atmosphere/rho-sl-slugs_ft3'] A = math.pow((pt-P)/psl+1.0, 1.0/3.5) alpha = fdm['aero/alpha-rad'] beta = fdm['aero/beta-rad'] vc = math.sqrt(7.0*psl/rhosl*(A-1.0))*math.cos(alpha+pitot_angle)*math.cos(beta) self.assertAlmostEqual(fdm['velocities/vc-kts'], max(0.0, vc) / 1.68781, delta=1E-7)
def test_asl_override_vs_geod_lat(self): fdm = CreateFDM(self.sandbox) fdm.load_model('c310') fdm.load_ic( self.sandbox.path_to_jsbsim_file('aircraft', 'c310', 'ellington.xml'), False) geod_lat = fdm['ic/lat-geod-deg'] fdm['ic/h-sl-ft'] = 35000. self.assertAlmostEqual(fdm['ic/lat-geod-deg'], geod_lat)
def test_sl_pressure_bias(self): fdm = CreateFDM(self.sandbox) fdm.load_model('ball') P_sl = 95000. fdm['atmosphere/P-sl-psf'] = P_sl * self.Pa_to_psf self.check_temperature(fdm, self.T0, 0.0) self.check_pressure(fdm, P_sl, self.T0, 0.0) del fdm
def test_densityaltitude(self): fdm = CreateFDM(self.sandbox) fdm.load_model('ball') # Reference data (Geometric Altitude, Temp Delta (Rankine), Density Altitude) reference_data = [ (0, 0, 0), (0, -27, -1838.3210293), (0, 27, 1724.0715454), (10000, 0, 10000), (10000, -27, 8842.6417730), (10000, 27, 11117.881412), (20000, 0, 20000), (20000, -27, 19524.3027252), (20000, 27, 20511.1447732), (30000, 0, 30000), (30000, -27, 30206.6618955), (30000, 27, 29903.8616766), (40000, 0, 40000), (40000, -27, 40795.49296642545), (40000, 27, 39370.88017359472), (50000, 0, 50000), (50000, -27, 51540.55687445524), (50000, 27, 48722.498495051164), (60000, 0, 60000), (60000, -27, 62286.38628793139), (60000, 27, 58073.53700852329), (100000, 0, 100000), (100000, -27, 105340.83866126923), (100000, 27, 95441.10933931815), (150000, 0, 150000), (150000, -27, 159983.12837740956), (150000, 27, 141847.12260237316), (160000, 0, 160000), (160000, -27, 171305.317547756), (160000, 27, 150762.4482763878), (220000, 0, 220000), (220000, -27, 233395.46205079104), (220000, 27, 207735.4268030979), (260000, 0, 260000), (260000, -27, 274351.9265767301), (260000, 27, 246964.3481013492), (290000, 0, 290000), (290000, -27, 305321.815863847), (290000, 27, 276290.37419984984), (320000, 0, 320000), (320000, -27, 337990.28144264355), (320000, 27, 304417.9280936986) ] # Run through refernce data and compare JSBSim calculated density altitude to expected for geometric_alt, delta_T, density_alt in reference_data: fdm['ic/h-sl-ft'] = geometric_alt fdm['atmosphere/delta-T'] = delta_T fdm.run_ic() jsbSim_density_alt = fdm['atmosphere/density-altitude'] if density_alt < 1E-9: self.assertAlmostEqual(density_alt, jsbSim_density_alt) else: self.assertAlmostEqual(1.0, jsbSim_density_alt / density_alt) density_ref = fdm['atmosphere/rho-slugs_ft3'] fdm['ic/h-sl-ft'] = jsbSim_density_alt fdm['atmosphere/delta-T'] = 0.0 fdm.run_ic() self.assertAlmostEqual(density_ref, fdm['atmosphere/rho-slugs_ft3']) del fdm
def test_temperature_bias(self): fdm = CreateFDM(self.sandbox) fdm.load_model('ball') delta_T_K = 15.0 T_sl = self.T0 + delta_T_K fdm['atmosphere/delta-T'] = delta_T_K * self.K_to_R self.check_temperature(fdm, T_sl, 0.0) self.check_pressure(fdm, self.P0, T_sl, 0.0) del fdm
def testSpinningBodyOnOrbit(self): script_name = 'ball_orbit.xml' script_path = self.sandbox.path_to_jsbsim_file('scripts', script_name) self.AddAccelerometersToAircraft(script_path) fdm = CreateFDM(self.sandbox) fdm.set_aircraft_path('aircraft') fdm.load_model('ball') # Offset the CG along Y (by 30") fdm.set_property_value('inertia/pointmass-weight-lbs[1]', 50.0) aircraft_path = self.sandbox.elude( self.sandbox.path_to_jsbsim_file('aircraft', 'ball')) fdm.load_ic(os.path.join(aircraft_path, 'reset00.xml'), False) # Switch the accel on fdm.set_property_value('fcs/accelerometer/on', 1.0) # Set the orientation such that the spinning axis is Z. fdm.set_property_value('ic/phi-rad', 0.5 * math.pi) # Set the angular velocities to 0.0 in the ECEF frame. The angular # velocity R_{inertial} will therefore be equal to the Earth rotation # rate 7.292115E-5 rad/sec fdm.set_property_value('ic/p-rad_sec', 0.0) fdm.set_property_value('ic/q-rad_sec', 0.0) fdm.set_property_value('ic/r-rad_sec', 0.0) fdm.run_ic() fax = fdm.get_property_value('fcs/accelerometer/X') fay = fdm.get_property_value('fcs/accelerometer/Y') faz = fdm.get_property_value('fcs/accelerometer/Z') cgy_ft = fdm.get_property_value('inertia/cg-y-in') / 12. omega = 0.00007292115 # Earth rotation rate in rad/sec self.assertAlmostEqual( fdm.get_property_value('accelerations/a-pilot-x-ft_sec2'), fax, delta=1E-8) self.assertAlmostEqual( fdm.get_property_value('accelerations/a-pilot-y-ft_sec2'), fay, delta=1E-8) self.assertAlmostEqual( fdm.get_property_value('accelerations/a-pilot-z-ft_sec2'), faz, delta=1E-8) # Acceleration along X should be zero self.assertAlmostEqual(fax, 0.0, delta=1E-8) # Acceleration along Y should be equal to r*omega^2 self.assertAlmostEqual(fay / (cgy_ft * omega * omega), 1.0, delta=1E-7) # Acceleration along Z should be zero self.assertAlmostEqual(faz, 0.0, delta=1E-8)
def testKinematicSetInitialValue(self): fdm = CreateFDM(self.sandbox) fdm.load_model('p51d') fdm.load_ic('reset01', True) fdm.run_ic() fdm['gear/gear-cmd-norm'] = 0.5 fdm['gear/gear-pos-norm'] = 0.5 while fdm['simulation/sim-time-sec'] < 1.0: fdm.run() self.assertAlmostEqual(fdm['gear/gear-cmd-norm'], 0.5) self.assertAlmostEqual(fdm['gear/gear-pos-norm'], 0.5)
def test_pressurealtitude(self): fdm = CreateFDM(self.sandbox) fdm.load_model('ball') # Reference data (Geometric Altitude, Temp Delta (Rankine), Pressure Altitude) reference_data = [ (0, 0, 0), (0, -27, 0), (0, 27, 0), (10000, 0, 10000), (10000, -27, 10549.426597202142), (10000, 27, 9504.969939165301), (20000, 0, 20000), (20000, -27, 21099.40877940678), (20000, 27, 19009.488882465), (30000, 0, 30000), (30000, -27, 31649.946590500946), (30000, 27, 28513.556862000503), (40000, 0, 40000), (40000, -27, 42294.25242340247), (40000, 27, 37972.879013500584), (50000, 0, 50000), (50000, -27, 53040.858132036126), (50000, 27, 47323.24573196882), (60000, 0, 60000), (60000, -27, 63788.23024872676), (60000, 27, 56673.032160129085), (100000, 0, 100000), (100000, -27, 107018.51146890492), (100000, 27, 93910.6118895332), (150000, 0, 150000), (150000, -27, 161956.60354430682), (150000, 27, 139810.93668842476), (160000, 0, 160000), (160000, -27, 172582.32995327076), (160000, 27, 148992.4108097521), (220000, 0, 220000), (220000, -27, 233772.88181515134), (220000, 27, 207274.89794422916), (260000, 0, 260000), (260000, -27, 275000.20893894637), (260000, 27, 246263.63421221747), (290000, 0, 290000), (290000, -27, 306867.8082342206), (290000, 27, 275185.69941262825), (320000, 0, 320000), (320000, -27, 339541.05112835445), (320000, 27, 302991.642663158) ] # Run through refernce data and compare JSBSim calculated pressure altitude to expected for geometric_alt, delta_T, pressure_alt in reference_data: fdm['ic/h-sl-ft'] = geometric_alt fdm['atmosphere/delta-T'] = delta_T fdm.run_ic() jsbSim_pressure_alt = fdm['atmosphere/pressure-altitude'] self.assertAlmostEqual(pressure_alt, jsbSim_pressure_alt, delta=1e-7) pressure_ref = fdm['atmosphere/P-psf'] fdm['ic/h-sl-ft'] = jsbSim_pressure_alt fdm['atmosphere/delta-T'] = 0.0 fdm.run_ic() self.assertAlmostEqual(pressure_ref, fdm['atmosphere/P-psf']) del fdm
def test_static_hold_down(self): fdm = CreateFDM(self.sandbox) fdm.load_model('J246') aircraft_path = self.sandbox.path_to_jsbsim_file('aircraft') fdm.load_ic(os.path.join(aircraft_path, 'J246', 'LC39'), False) fdm['forces/hold-down'] = 1.0 fdm.run_ic() h0 = fdm['position/h-sl-ft'] t = 0.0 while t < 420.0: fdm.run() t = fdm['simulation/sim-time-sec'] self.assertAlmostEqual(fdm['position/h-sl-ft'], h0, delta=1E-5)
def test_initial_latitude(self): Output_file = self.sandbox.path_to_jsbsim_file('tests', 'output.xml') GEODETIC, ELEVATION, ALTITUDE = (1, 2, 4) for v in ('', '_v2'): IC_file = self.sandbox.path_to_jsbsim_file('aircraft', 'ball', 'reset00' + v + '.xml') for i in xrange(8): for latitude_pos in xrange(4): IC_tree = et.parse(IC_file) IC_root = IC_tree.getroot() if v: position_tag = IC_root.find('position') latitude_tag = et.SubElement(position_tag, 'latitude') latitude_tag.attrib['unit'] = 'DEG' else: position_tag = IC_root latitude_tag = IC_root.find('latitude') latitude_tag.text = str(latitude_pos * 30.) if i & GEODETIC: latitude_tag.attrib['type'] = 'geod' if i & ELEVATION: elevation_tag = et.SubElement(IC_root, 'elevation') elevation_tag.text = '1000.' if i & ALTITUDE: if v: altitude_tag = position_tag.find('altitudeMSL') altitude_tag.tag = 'altitudeAGL' else: altitude_tag = position_tag.find('altitude') altitude_tag.tag = 'altitudeMSL' IC_tree.write('IC.xml') fdm = CreateFDM(self.sandbox) fdm.load_model('ball') fdm.set_output_directive(Output_file) fdm.set_output_filename(1, 'check_csv_values.csv') fdm.load_ic('IC.xml', False) fdm.run_ic() self.CheckICValues(self.GetVariables(latitude_tag), 'IC%d' % (i, ), fdm, position_tag) del fdm
def testKinematicSetInitialValue(self): fdm = CreateFDM(self.sandbox) fdm.load_model('p51d') fdm.load_ic(self.sandbox.path_to_jsbsim_file('aircraft', 'p51d', 'reset01'), False) fdm.run_ic() fdm['gear/gear-cmd-norm'] = 0.5 fdm['gear/gear-pos-norm'] = 0.5 while fdm['simulation/sim-time-sec'] < 1.0: fdm.run() self.assertAlmostEqual(fdm['gear/gear-cmd-norm'], 0.5) self.assertAlmostEqual(fdm['gear/gear-pos-norm'], 0.5)
def test_initial_latitude(self): Output_file = self.sandbox.path_to_jsbsim_file('tests', 'output.xml') GEODETIC, ELEVATION, ALTITUDE = (1, 2, 4) for v in ('', '_v2'): IC_file = self.sandbox.path_to_jsbsim_file('aircraft', 'ball', 'reset00'+v+'.xml') for i in xrange(8): for latitude_pos in xrange(4): IC_tree = et.parse(IC_file) IC_root = IC_tree.getroot() if v: position_tag = IC_root.find('position') latitude_tag = et.SubElement(position_tag, 'latitude') latitude_tag.attrib['unit'] = 'DEG' else: position_tag = IC_root latitude_tag = IC_root.find('latitude') latitude_tag.text = str(latitude_pos*30.) if i & GEODETIC: latitude_tag.attrib['type'] = 'geod' if i & ELEVATION: elevation_tag = et.SubElement(IC_root, 'elevation') elevation_tag.text = '1000.' if i & ALTITUDE: if v: altitude_tag = position_tag.find('altitudeMSL') altitude_tag.tag = 'altitudeAGL' else: altitude_tag = position_tag.find('altitude') altitude_tag.tag = 'altitudeMSL' IC_tree.write('IC.xml') fdm = CreateFDM(self.sandbox) fdm.load_model('ball') fdm.set_output_directive(Output_file) fdm.set_output_filename(1, 'check_csv_values.csv') fdm.load_ic('IC.xml', False) fdm.run_ic() self.CheckICValues(self.GetVariables(latitude_tag), 'IC%d' % (i,), fdm, position_tag) del fdm
def test_pressure_and_temperature_bias(self): fdm = CreateFDM(self.sandbox) fdm.load_model('ball') delta_T_K = 15.0 T_sl = self.T0 + delta_T_K fdm['atmosphere/delta-T'] = delta_T_K * self.K_to_R P_sl = 95000. fdm['atmosphere/P-sl-psf'] = P_sl * self.Pa_to_psf self.check_temperature(fdm, T_sl, 0.0) self.check_pressure(fdm, P_sl, T_sl, 0.0) del fdm
def testKinematicSetInitialValue(self): fdm = CreateFDM(self.sandbox) fdm.load_model('p51d') fdm.load_ic( self.sandbox.path_to_jsbsim_file('aircraft', 'p51d', 'reset01'), False) fdm.run_ic() fdm['gear/gear-cmd-norm'] = 0.5 fdm['gear/gear-pos-norm'] = 0.5 while fdm['simulation/sim-time-sec'] < 1.0: fdm.run() self.assertAlmostEqual(fdm['gear/gear-cmd-norm'], 0.5) self.assertAlmostEqual(fdm['gear/gear-pos-norm'], 0.5)
def test_static_hold_down(self): fdm = CreateFDM(self.sandbox) fdm.load_model('J246') fdm.load_ic('LC39', True) fdm['forces/hold-down'] = 1.0 fdm.run_ic() h0 = fdm['position/vrp-radius-ft'] t = 0.0 while t < 420.0: fdm.run() t = fdm['simulation/sim-time-sec'] self.assertAlmostEqual(fdm['position/vrp-radius-ft'] / h0, 1.0, delta=1E-9)
def test_temperature_gradient(self): fdm = CreateFDM(self.sandbox) fdm.load_model('ball') graded_delta_T_K = -10.0 fdm['atmosphere/SL-graded-delta-T'] = graded_delta_T_K*self.K_to_R T_gradient = graded_delta_T_K / self.gradient_fade_out_h self.assertAlmostEqual(T_gradient*self.K_to_R/self.km_to_ft, fdm['atmosphere/SL-graded-delta-T']) self.check_temperature(fdm, self.T0 + graded_delta_T_K, T_gradient) self.check_pressure(fdm, self.P0, self.T0 + graded_delta_T_K, T_gradient) del fdm
def testAircrafts(self): aircraft_path = self.sandbox.path_to_jsbsim_file('aircraft') for d in os.listdir(aircraft_path): fullpath = os.path.join(aircraft_path, d) # Is d a directory ? if not os.path.isdir(fullpath): continue f = os.path.join(aircraft_path, d, d + '.xml') # Is f an aircraft definition file ? if not CheckXMLFile(f, 'fdm_config'): continue if d in ('blank'): continue fdm = CreateFDM(self.sandbox) self.assertTrue(fdm.load_model(d), msg='Failed to load aircraft %s' % (d, )) for f in os.listdir(fullpath): f = os.path.join(aircraft_path, d, f) if CheckXMLFile(f, 'initialize'): self.assertTrue( fdm.load_ic(f, False), msg='Failed to load IC %s for aircraft %s' % (f, d)) try: fdm.run_ic() except RuntimeError: self.fail('Failed to run IC %s for aircraft %s' % (f, d)) del fdm
def testAircrafts(self): aircraft_path = self.sandbox.path_to_jsbsim_file('aircraft') for d in os.listdir(aircraft_path): fullpath = os.path.join(aircraft_path, d) # Is d a directory ? if not os.path.isdir(fullpath): continue f = os.path.join(aircraft_path, d, d+'.xml') # Is f an aircraft definition file ? if not CheckXMLFile(f, 'fdm_config'): continue if d in ('blank'): continue fdm = CreateFDM(self.sandbox) self.assertTrue(fdm.load_model(d), msg='Failed to load aircraft %s' % (d,)) for f in os.listdir(fullpath): f = os.path.join(aircraft_path, d, f) if CheckXMLFile(f, 'initialize'): self.assertTrue(fdm.load_ic(f, False), msg='Failed to load IC %s for aircraft %s' % (f, d)) try: fdm.run_ic() except RuntimeError: self.fail('Failed to run IC %s for aircraft %s' % (f, d)) del fdm
def testSpinningBodyOnOrbit(self): script_name = 'ball_orbit.xml' script_path = self.sandbox.path_to_jsbsim_file('scripts', script_name) self.AddAccelerometersToAircraft(script_path) fdm = CreateFDM(self.sandbox) fdm.set_aircraft_path('aircraft') fdm.load_model('ball') # Offset the CG along Y (by 30") fdm['inertia/pointmass-weight-lbs[1]'] = 50.0 aircraft_path = self.sandbox.path_to_jsbsim_file('aircraft', 'ball') fdm.load_ic(os.path.join(aircraft_path, 'reset00.xml'), False) # Switch the accel on fdm['fcs/accelerometer/on'] = 1.0 # Set the orientation such that the spinning axis is Z. fdm['ic/phi-rad'] = 0.5 * math.pi # Set the angular velocities so that angular velocity R_{inertial} will # be equal to 1.0 rad/sec. omega = 0.00007292115 # Earth rotation rate in rad/sec fdm['ic/p-rad_sec'] = 0.0 fdm['ic/q-rad_sec'] = 0.0 fdm['ic/r-rad_sec'] = 1.0 - omega fdm.run_ic() fax = fdm['fcs/accelerometer/X'] fay = fdm['fcs/accelerometer/Y'] faz = fdm['fcs/accelerometer/Z'] cgy_ft = fdm['inertia/cg-y-in'] / 12. self.assertAlmostEqual(fdm['accelerations/a-pilot-x-ft_sec2'], fax, delta=1E-8) self.assertAlmostEqual(fdm['accelerations/a-pilot-y-ft_sec2'], fay, delta=1E-8) self.assertAlmostEqual(fdm['accelerations/a-pilot-z-ft_sec2'], faz, delta=1E-8) # Acceleration along X should be zero self.assertAlmostEqual(fax, 0.0, delta=1E-8) # Acceleration along Y should be equal to d*r_dot^2 self.assertAlmostEqual(fay / cgy_ft, 1.0, delta=1E-7) # Acceleration along Z should be zero self.assertAlmostEqual(faz, 0.0, delta=1E-8)
def test_property_catalog(self): fdm = CreateFDM(self.sandbox) fdm.load_model('ball') fdm.run_ic() catalog = fdm.query_property_catalog('geod-deg') self.assertEqual(len(catalog), 2) self.assertEqual(catalog[0], 'position/lat-geod-deg (R)') self.assertEqual(catalog[1], 'ic/lat-geod-deg (RW)') values = fdm.get_property_catalog('geod-deg') item = 'position/lat-geod-deg' self.assertEqual(values[item], fdm[item]) item = 'ic/lat-geod-deg' self.assertEqual(values[item], fdm[item]) del fdm
def test_direct_steer(self): fdm = CreateFDM(self.sandbox) fdm.load_model('c172r') aircraft_path = self.sandbox.path_to_jsbsim_file('aircraft') fdm.load_ic(os.path.join(aircraft_path, 'c172r', 'reset00'), False) fdm.run_ic() self.assertAlmostEqual(fdm['fcs/steer-cmd-norm'], 0.0) self.assertAlmostEqual(fdm['fcs/steer-pos-deg'], 0.0) fdm['fcs/steer-pos-deg'] = 5.0 self.assertAlmostEqual(fdm['fcs/steer-pos-deg'], 5.0) fdm.run() self.assertAlmostEqual(fdm['fcs/steer-cmd-norm'], 0.0) fdm['fcs/steer-cmd-norm'] = 1.0 self.assertAlmostEqual(fdm['fcs/steer-cmd-norm'], 1.0) fdm.run() self.assertAlmostEqual(fdm['fcs/steer-cmd-norm'], 1.0) self.assertAlmostEqual(fdm['fcs/steer-pos-deg'], 10.0)
def testSpinningBodyOnOrbit(self): script_name = 'ball_orbit.xml' script_path = self.sandbox.path_to_jsbsim_file('scripts', script_name) self.AddAccelerometersToAircraft(script_path) fdm = CreateFDM(self.sandbox) fdm.set_aircraft_path('aircraft') fdm.load_model('ball') # Offset the CG along Y (by 30") fdm.set_property_value('inertia/pointmass-weight-lbs[1]', 50.0) aircraft_path = self.sandbox.elude(self.sandbox.path_to_jsbsim_file('aircraft', 'ball')) fdm.load_ic(os.path.join(aircraft_path, 'reset00.xml'), False) # Switch the accel on fdm.set_property_value('fcs/accelerometer/on', 1.0) # Set the orientation such that the spinning axis is Z. fdm.set_property_value('ic/phi-rad', 0.5*math.pi) # Set the angular velocities to 0.0 in the ECEF frame. The angular # velocity R_{inertial} will therefore be equal to the Earth rotation # rate 7.292115E-5 rad/sec fdm.set_property_value('ic/p-rad_sec', 0.0) fdm.set_property_value('ic/q-rad_sec', 0.0) fdm.set_property_value('ic/r-rad_sec', 0.0) fdm.run_ic() fax = fdm.get_property_value('fcs/accelerometer/X') fay = fdm.get_property_value('fcs/accelerometer/Y') faz = fdm.get_property_value('fcs/accelerometer/Z') cgy_ft = fdm.get_property_value('inertia/cg-y-in') / 12. omega = 0.00007292115 # Earth rotation rate in rad/sec self.assertAlmostEqual(fdm.get_property_value('accelerations/a-pilot-x-ft_sec2'), fax, delta=1E-8) self.assertAlmostEqual(fdm.get_property_value('accelerations/a-pilot-y-ft_sec2'), fay, delta=1E-8) self.assertAlmostEqual(fdm.get_property_value('accelerations/a-pilot-z-ft_sec2'), faz, delta=1E-8) # Acceleration along X should be zero self.assertAlmostEqual(fax, 0.0, delta=1E-8) # Acceleration along Y should be equal to r*omega^2 self.assertAlmostEqual(fay / (cgy_ft * omega * omega), 1.0, delta=1E-7) # Acceleration along Z should be zero self.assertAlmostEqual(faz, 0.0, delta=1E-8)
def testKinematicNoScale(self): # Test the <nocale/> feature script_path = self.sandbox.path_to_jsbsim_file('scripts', 'c1721.xml') tree, aircraft_name, b = CopyAircraftDef(script_path, self.sandbox) kinematic_tag = tree.getroot().find('flight_control/channel/kinematic') et.SubElement(kinematic_tag, 'noscale') tree.write( self.sandbox('aircraft', aircraft_name, aircraft_name + '.xml')) fdm = CreateFDM(self.sandbox) fdm.set_aircraft_path('aircraft') fdm.load_model(aircraft_name) fdm.load_ic('reset00', True) fdm.run_ic() fdm['fcs/flap-cmd-norm'] = 12. ExecuteUntil(fdm, 2.2) self.assertAlmostEqual(fdm['fcs/flap-pos-deg'], 12.)
def test_dynamic_hold_down(self): fdm = CreateFDM(self.sandbox) fdm.load_model('J246') fdm.load_ic('LC39', True) fdm['forces/hold-down'] = 1.0 fdm.run_ic() h0 = fdm['position/vrp-radius-ft'] # Start solid rocket boosters fdm['fcs/throttle-cmd-norm[0]'] = 1.0 fdm['fcs/throttle-cmd-norm[1]'] = 1.0 t = 0.0 while t < 420.0: fdm.run() t = fdm['simulation/sim-time-sec'] self.assertAlmostEqual(fdm['position/vrp-radius-ft'] / h0, 1.0, delta=1E-9)
def testSpinningBodyOnOrbit(self): script_name = 'ball_orbit.xml' script_path = self.sandbox.path_to_jsbsim_file('scripts', script_name) self.AddAccelerometersToAircraft(script_path) fdm = CreateFDM(self.sandbox) fdm.set_aircraft_path('aircraft') fdm.load_model('ball') # Offset the CG along Y (by 30") fdm['inertia/pointmass-weight-lbs[1]'] = 50.0 aircraft_path = self.sandbox.path_to_jsbsim_file('aircraft', 'ball') fdm.load_ic(os.path.join(aircraft_path, 'reset00.xml'), False) # Switch the accel on fdm['fcs/accelerometer/on'] = 1.0 # Set the orientation such that the spinning axis is Z. fdm['ic/phi-rad'] = 0.5*math.pi # Set the angular velocities so that angular velocity R_{inertial} will # be equal to 1.0 rad/sec. omega = 0.00007292115 # Earth rotation rate in rad/sec fdm['ic/p-rad_sec'] = 0.0 fdm['ic/q-rad_sec'] = 0.0 fdm['ic/r-rad_sec'] = 1.0 - omega fdm.run_ic() fax = fdm['fcs/accelerometer/X'] fay = fdm['fcs/accelerometer/Y'] faz = fdm['fcs/accelerometer/Z'] cgy_ft = fdm['inertia/cg-y-in'] / 12. self.assertAlmostEqual(fdm['accelerations/a-pilot-x-ft_sec2'], fax, delta=1E-8) self.assertAlmostEqual(fdm['accelerations/a-pilot-y-ft_sec2'], fay, delta=1E-8) self.assertAlmostEqual(fdm['accelerations/a-pilot-z-ft_sec2'], faz, delta=1E-8) # Acceleration along X should be zero self.assertAlmostEqual(fax, 0.0, delta=1E-8) # Acceleration along Y should be equal to d*r_dot^2 self.assertAlmostEqual(fay / cgy_ft, 1.0, delta=1E-7) # Acceleration along Z should be zero self.assertAlmostEqual(faz, 0.0, delta=1E-8)
def testKinematicNoScale(self): # Test the <nocale/> feature script_path = self.sandbox.path_to_jsbsim_file('scripts', 'c1721.xml') tree, aircraft_name, b = CopyAircraftDef(script_path, self.sandbox) kinematic_tag = tree.getroot().find('flight_control/channel/kinematic') et.SubElement(kinematic_tag, 'noscale') tree.write(self.sandbox('aircraft', aircraft_name, aircraft_name+'.xml')) fdm = CreateFDM(self.sandbox) fdm.set_aircraft_path('aircraft') fdm.load_model(aircraft_name) fdm.load_ic(self.sandbox.path_to_jsbsim_file('aircraft', aircraft_name, 'reset00'), False) fdm.run_ic() fdm['fcs/flap-cmd-norm'] = 12. ExecuteUntil(fdm, 2.2) self.assertAlmostEqual(fdm['fcs/flap-pos-deg'], 12.)
def test_dynamic_hold_down(self): fdm = CreateFDM(self.sandbox) fdm.load_model('J246') aircraft_path = self.sandbox.path_to_jsbsim_file('aircraft') fdm.load_ic(os.path.join(aircraft_path, 'J246', 'LC39'), False) fdm['forces/hold-down'] = 1.0 fdm.run_ic() h0 = fdm['position/vrp-radius-ft'] # Start solid rocket boosters fdm['fcs/throttle-cmd-norm[0]'] = 1.0 fdm['fcs/throttle-cmd-norm[1]'] = 1.0 t = 0.0 while t < 420.0: fdm.run() t = fdm['simulation/sim-time-sec'] self.assertAlmostEqual(fdm['position/vrp-radius-ft'] / h0, 1.0, delta=1E-9)
def test_alt_mod_vs_CAS(self): script_name = 'Short_S23_3.xml' script_path = self.sandbox.path_to_jsbsim_file('scripts', script_name) # Add a Pitot angle to the Short S23 tree, aircraft_name, b = CopyAircraftDef(script_path, self.sandbox) self.addPitotTube(tree.getroot(), 10.0) tree.write(self.sandbox('aircraft', aircraft_name, aircraft_name+'.xml')) fdm = CreateFDM(self.sandbox) fdm.set_aircraft_path('aircraft') fdm.load_model('Short_S23') fdm['ic/beta-deg'] = 15.0 # Add some sideslip fdm['ic/vc-kts'] = 172.0 fdm['ic/h-sl-ft'] = 15000. self.assertAlmostEqual(fdm['ic/vc-kts'], 172.0, delta=1E-7) self.assertAlmostEqual(fdm['ic/beta-deg'], 15.0, delta=1E-7) fdm.run_ic() self.assertAlmostEqual(fdm['velocities/vc-kts'], 172.0, delta=1E-7) self.assertAlmostEqual(fdm['aero/beta-deg'], 15.0, delta=1E-7)
def test_no_script(self): fdm = CreateFDM(self.sandbox) aircraft_path = self.sandbox.path_to_jsbsim_file('aircraft') fdm.load_model('c172x') aircraft_path = os.path.join(aircraft_path, 'c172x') fdm.load_ic(os.path.join(aircraft_path, 'reset01.xml'), False) fdm.run_ic() self.assertEqual(fdm['simulation/sim-time-sec'], 0.0) ExecuteUntil(fdm, 5.0) t = fdm['simulation/sim-time-sec'] fdm['simulation/do_simple_trim'] = 1 self.assertEqual(fdm['simulation/sim-time-sec'], t) fdm.reset_to_initial_conditions(1) self.assertEqual(fdm['simulation/sim-time-sec'], 0.0) del fdm
def test_trim_on_ground(self): # Check that the trim is made with up to date initial conditions fdm = CreateFDM(self.sandbox) fdm.load_model('c172x') fdm['ic/theta-deg'] = 90.0 fdm.run_ic() fdm['ic/theta-deg'] = 0.0 # If the trim fails, it will raise an exception fdm['simulation/do_simple_trim'] = 2 # Ground trim # Check that the aircraft has been trimmed successfully (velocities # should be zero i.e. the aircraft must be motionless once trimmed). while fdm['simulation/sim-time-sec'] <= 1.0: fdm.run() self.assertAlmostEqual(fdm['velocities/p-rad_sec'], 0., delta=1E-4) self.assertAlmostEqual(fdm['velocities/q-rad_sec'], 0., delta=1E-4) self.assertAlmostEqual(fdm['velocities/r-rad_sec'], 0., delta=1E-4) self.assertAlmostEqual(fdm['velocities/u-fps'], 0.0, delta=1E-4) self.assertAlmostEqual(fdm['velocities/v-fps'], 0.0, delta=1E-4) self.assertAlmostEqual(fdm['velocities/w-fps'], 0.0, delta=1E-4)
def testKinematicAndTrim(self): fdm = CreateFDM(self.sandbox) fdm.load_model('p51d') fdm.load_ic(self.sandbox.path_to_jsbsim_file('aircraft', 'p51d', 'reset01'), False) self.assertEqual(fdm['gear/gear-cmd-norm'], 1.0) # Set the landing gears up. Since the command is equal to 1.0, the # <kinematic> system will trigger the gear down sequence. fdm['gear/gear-pos-norm'] = 0.0 fdm.run_ic() # The test succeeds if the trim does not raise an exception i.e. if the # <kinematic> system does not interfer with the trim on ground # algorithm. fdm['simulation/do_simple_trim'] = 2 # Ground trim # Check that the gear is down after the trim as requested by # gear/gear-cmd-norm self.assertAlmostEqual(fdm['gear/gear-pos-norm'], 1.0) # Check that the gear is not moving to another position after trim. fdm.run() self.assertAlmostEqual(fdm['gear/gear-pos-norm'], 1.0)
def test_property_access(self): fdm = CreateFDM(self.sandbox) fdm.load_model('ball') fdm.run_ic() # Check that the node 'qwerty' does not exist pm = fdm.get_property_manager() self.assertFalse(pm.hasNode('qwerty')) # Check the default behavior of get_property_value. Non existing # properties return 0.0 self.assertEqual(fdm.get_property_value('qwerty'), 0.0) # Verify that __getitem__ checks the existence and raises KeyError if # the property does not exist. with self.assertRaises(KeyError): x = fdm['qwerty'] # Check that we can initialize a non existing property fdm['qwerty'] = 42.0 self.assertAlmostEqual(fdm.get_property_value('qwerty'), 42.0) self.assertAlmostEqual(fdm['qwerty'], 42.0) del fdm
def test_body_frame(self): fdm = CreateFDM(self.sandbox) aircraft_path = self.sandbox.path_to_jsbsim_file('aircraft') fdm.load_model('f16') aircraft_path = os.path.join(aircraft_path, 'f16') fdm.load_ic(os.path.join(aircraft_path, 'reset00.xml'), False) fdm.run_ic() self.assertAlmostEqual(fdm['external_reactions/pushback/location-x-in'], -2.98081) self.assertAlmostEqual(fdm['external_reactions/pushback/location-y-in'], 0.0) self.assertAlmostEqual(fdm['external_reactions/pushback/location-z-in'], -1.9683) self.assertAlmostEqual(fdm['external_reactions/pushback/x'], 1.0) self.assertAlmostEqual(fdm['external_reactions/pushback/y'], 0.0) self.assertAlmostEqual(fdm['external_reactions/pushback/z'], 0.0) self.assertAlmostEqual(fdm['external_reactions/pushback/magnitude'], 0.0) self.assertAlmostEqual(fdm['external_reactions/hook/location-x-in'], 100.669) self.assertAlmostEqual(fdm['external_reactions/hook/location-y-in'], 0.0) self.assertAlmostEqual(fdm['external_reactions/hook/location-z-in'], -28.818) dx = -0.9995 dz = 0.01 fhook = np.array([dx, 0.0, dz]) fhook /= np.linalg.norm(fhook) self.assertAlmostEqual(fdm['external_reactions/hook/x'], fhook[0]) self.assertAlmostEqual(fdm['external_reactions/hook/y'], fhook[1]) self.assertAlmostEqual(fdm['external_reactions/hook/z'], fhook[2]) self.assertAlmostEqual(fdm['external_reactions/hook/magnitude'], 0.0) self.assertAlmostEqual(fdm['forces/fbx-external-lbs'], 0.0) self.assertAlmostEqual(fdm['forces/fby-external-lbs'], 0.0) self.assertAlmostEqual(fdm['forces/fbz-external-lbs'], 0.0) self.assertAlmostEqual(fdm['moments/l-external-lbsft'], 0.0) self.assertAlmostEqual(fdm['moments/m-external-lbsft'], 0.0) self.assertAlmostEqual(fdm['moments/n-external-lbsft'], 0.0) # Check the 'pushback' external force alone fdm['/sim/model/pushback/position-norm'] = 1.0 fdm['/sim/model/pushback/target-speed-fps'] = 1.0 fdm['/sim/model/pushback/kp'] = 0.05 fdm.run() fpb = np.array([1.0, 0.0, 0.0]) * 0.05 self.assertAlmostEqual(fdm['external_reactions/pushback/magnitude'], 0.05) self.assertAlmostEqual(fdm['forces/fbx-external-lbs'], fpb[0]) self.assertAlmostEqual(fdm['forces/fby-external-lbs'], fpb[1]) self.assertAlmostEqual(fdm['forces/fbz-external-lbs'], fpb[2]) m = np.cross(self.getLeverArm(fdm, 'pushback'), fpb) self.assertAlmostEqual(fdm['moments/l-external-lbsft'], m[0]) self.assertAlmostEqual(fdm['moments/m-external-lbsft'], m[1]) self.assertAlmostEqual(fdm['moments/n-external-lbsft'], m[2]) # Reset the 'pushback' external force to zero fdm['/sim/model/pushback/position-norm'] = 0.0 fdm.run() self.assertAlmostEqual(fdm['external_reactions/pushback/magnitude'], 0.0) self.assertAlmostEqual(fdm['forces/fbx-external-lbs'], 0.0) self.assertAlmostEqual(fdm['forces/fby-external-lbs'], 0.0) self.assertAlmostEqual(fdm['forces/fbz-external-lbs'], 0.0) self.assertAlmostEqual(fdm['moments/l-external-lbsft'], 0.0) self.assertAlmostEqual(fdm['moments/m-external-lbsft'], 0.0) self.assertAlmostEqual(fdm['moments/n-external-lbsft'], 0.0) # Check the 'hook' external force alone fdm['external_reactions/hook/magnitude'] = 10.0 fhook *= 10.0 fdm.run() self.assertAlmostEqual(fdm['forces/fbx-external-lbs'], fhook[0]) self.assertAlmostEqual(fdm['forces/fby-external-lbs'], fhook[1]) self.assertAlmostEqual(fdm['forces/fbz-external-lbs'], fhook[2]) m = np.cross(self.getLeverArm(fdm, 'hook'), fhook) self.assertAlmostEqual(fdm['moments/l-external-lbsft'], m[0]) self.assertAlmostEqual(fdm['moments/m-external-lbsft'], m[1]) self.assertAlmostEqual(fdm['moments/n-external-lbsft'], m[2]) # Add the 'pushback' force to the hook force and check that the global # external forces is the sum of the push back force and the hook force. fdm['/sim/model/pushback/position-norm'] = 1.0 fdm.run() fp = fdm['systems/pushback/force'] fpb = np.array([1.0, 0.0, 0.0]) * fp f = fhook + fpb self.assertAlmostEqual(fdm['external_reactions/pushback/magnitude'], fp) self.assertAlmostEqual(fdm['forces/fbx-external-lbs'], f[0]) self.assertAlmostEqual(fdm['forces/fby-external-lbs'], f[1]) self.assertAlmostEqual(fdm['forces/fbz-external-lbs'], f[2]) # Modify the push back force direction and check that the global external # force is modified accordingly. fdm['external_reactions/pushback/x'] = 1.5 fdm['external_reactions/pushback/y'] = 0.1 fdm.run() fp = fdm['systems/pushback/force'] fpb = np.array([1.5, 0.1, 0.0]) * fp f = fhook + fpb self.assertAlmostEqual(fdm['external_reactions/pushback/magnitude'], fp) self.assertAlmostEqual(fdm['forces/fbx-external-lbs'], f[0]) self.assertAlmostEqual(fdm['forces/fby-external-lbs'], f[1]) self.assertAlmostEqual(fdm['forces/fbz-external-lbs'], f[2]) m = (np.cross(self.getLeverArm(fdm, 'pushback'), fpb) + np.cross(self.getLeverArm(fdm, 'hook'), fhook)) self.assertAlmostEqual(fdm['moments/l-external-lbsft'], m[0]) self.assertAlmostEqual(fdm['moments/m-external-lbsft'], m[1]) self.assertAlmostEqual(fdm['moments/n-external-lbsft'], m[2]) fdm['external_reactions/hook/location-y-in'] = 50.0 fdm.run() fp = fdm['systems/pushback/force'] fpb = np.array([1.5, 0.1, 0.0]) * fp f = fhook + fpb self.assertAlmostEqual(fdm['external_reactions/pushback/magnitude'], fp) self.assertAlmostEqual(fdm['forces/fbx-external-lbs'], f[0]) self.assertAlmostEqual(fdm['forces/fby-external-lbs'], f[1]) self.assertAlmostEqual(fdm['forces/fbz-external-lbs'], f[2]) m = (np.cross(self.getLeverArm(fdm, 'pushback'), fpb) + np.cross(self.getLeverArm(fdm, 'hook'), fhook)) self.assertAlmostEqual(fdm['moments/l-external-lbsft'], m[0]) self.assertAlmostEqual(fdm['moments/m-external-lbsft'], m[1]) self.assertAlmostEqual(fdm['moments/n-external-lbsft'], m[2])