def testDebugLvl(self): fdm = self.create_fdm() fdm.load_script( self.sandbox.path_to_jsbsim_file('scripts', 'ball_orbit.xml')) fdm.run_ic() ExecuteUntil(fdm, 1000.) ref = pd.read_csv('BallOut.csv', index_col=0) os.environ["JSBSIM_DEBUG"] = str(0) fdm = self.create_fdm() fdm.load_script( self.sandbox.path_to_jsbsim_file('scripts', 'ball_orbit.xml')) fdm.run_ic() ExecuteUntil(fdm, 1000.) current = pd.read_csv('BallOut.csv', index_col=0) # Check the data are matching i.e. the time steps are the same between # the two data sets and that the output data are also the same. self.assertTrue(isDataMatching(ref, current)) # Find all the data that are differing by more than 1E-8 between the # two data sets. diff = FindDifferences(ref, current, 1E-8) self.longMessage = True self.assertEqual(len(diff), 0, msg='\n' + diff.to_string())
def testDebugLvl(self): fdm = CreateFDM(self.sandbox) fdm.load_script( self.sandbox.path_to_jsbsim_file('scripts', 'ball_orbit.xml')) fdm.run_ic() ExecuteUntil(fdm, 1000.) ref, current = Table(), Table() ref.ReadCSV(self.sandbox('BallOut.csv')) del fdm os.environ["JSBSIM_DEBUG"] = str(0) fdm = CreateFDM(self.sandbox) fdm.load_script( self.sandbox.path_to_jsbsim_file('scripts', 'ball_orbit.xml')) fdm.run_ic() ExecuteUntil(fdm, 1000.) current.ReadCSV(self.sandbox('BallOut.csv')) diff = ref.compare(current) self.longMessage = True self.assertTrue(diff.empty(), msg='\n' + repr(diff))
def test_gust_reset(self): fdm = CreateFDM(self.sandbox) fdm.load_script(self.sandbox.path_to_jsbsim_file('scripts', 'c172_cruise_8K.xml')) fdm['simulation/randomseed'] = 0.0 fdm.set_output_directive(self.sandbox.path_to_jsbsim_file('tests', 'output.xml')) fdm.run_ic() ExecuteUntil(fdm, 15.5) ref = pd.read_csv('output.csv', index_col=0) fdm['simulation/randomseed'] = 0.0 fdm.reset_to_initial_conditions(1) ExecuteUntil(fdm, 15.5) current = pd.read_csv('output_0.csv', index_col=0) # Check the data are matching i.e. the time steps are the same between # the two data sets and that the output data are also the same. self.assertTrue(isDataMatching(ref, current)) # Find all the data that are differing by more than 1E-8 between the # two data sets. diff = FindDifferences(ref, current, 1E-8) self.longMessage = True self.assertEqual(len(diff), 0, msg='\n'+diff.to_string())
def test_hold_down_with_gnd_reactions(self): fdm = CreateFDM(self.sandbox) fdm.load_script( self.sandbox.path_to_jsbsim_file('scripts', 'c1721.xml')) fdm.run_ic() ExecuteUntil(fdm, 0.25) fdm['forces/hold-down'] = 1.0 h0 = fdm['position/h-sl-ft'] pitch = fdm['attitude/pitch-rad'] roll = fdm['attitude/roll-rad'] heading = fdm['attitude/heading-true-rad'] while fdm['simulation/sim-time-sec'] < 2.0: fdm.run() self.assertAlmostEqual(fdm['accelerations/pdot-rad_sec2'], 0.0) self.assertAlmostEqual(fdm['accelerations/qdot-rad_sec2'], 0.0) self.assertAlmostEqual(fdm['accelerations/rdot-rad_sec2'], 0.0) self.assertAlmostEqual(fdm['accelerations/udot-ft_sec2'], 0.0) self.assertAlmostEqual(fdm['accelerations/vdot-ft_sec2'], 0.0) self.assertAlmostEqual(fdm['accelerations/wdot-ft_sec2'], 0.0) self.assertAlmostEqual(fdm['position/h-sl-ft'], h0, delta=1E-6) self.assertAlmostEqual(fdm['attitude/pitch-rad'], pitch) self.assertAlmostEqual(fdm['attitude/roll-rad'], roll) self.assertAlmostEqual(fdm['attitude/heading-true-rad'], heading)
def Compare(self, section): # Rerun the script with the modified aircraft definition self.sandbox.delete_csv_files() fdm = CreateFDM(self.sandbox) # We need to tell JSBSim that the aircraft definition is located in the # directory build/.../aircraft fdm.set_aircraft_path('aircraft') fdm.set_output_directive( self.sandbox.path_to_jsbsim_file('tests', 'output.xml')) fdm.load_script(self.script) fdm.set_property_value('simulation/randomseed', 0.0) fdm.run_ic() ExecuteUntil(fdm, 50.0) mod = Table() mod.ReadCSV(self.sandbox('output.csv')) # Whether the data is read from the aircraft definition file or from an # external file, the results shall be exactly identical. Hence the # precision set to 0.0. diff = self.ref.compare(mod, 0.0) self.assertTrue(diff.empty(), msg='\nTesting section "' + section + '"\n' + repr(diff))
def test_output(self): tree = et.parse(self.script_path) output_tag = et.SubElement(tree.getroot(), 'output') output_tag.attrib['name'] = 'test.csv' output_tag.attrib['type'] = 'CSV' output_tag.attrib['rate'] = '10' property_tag = et.SubElement(output_tag, 'property') property_tag.text = 'position/vrp-radius-ft' tree.write('c1722_0.xml') fdm = CreateFDM(self.sandbox) fdm.load_script('c1722_0.xml') fdm.run_ic() ExecuteUntil(fdm, 10.) self.assertTrue(self.sandbox.exists(output_tag.attrib['name']), msg="The file 'output.csv' has not been created") orig = pd.read_csv('JSBout172B.csv', index_col=0) test = pd.read_csv('test.csv', index_col=0) pname = '/fdm/jsbsim/' + property_tag.text ref = orig[pname] mod = test[pname] # Check the data are matching i.e. the time steps are the same between # the two data sets. self.assertTrue(isDataMatching(ref, mod)) # Find all the data that are differing by more than 1E-8 between the # two data sets. delta = pd.concat([np.abs(ref - mod), ref, mod], axis=1) delta.columns = ['delta', 'ref value', 'value'] diff = delta[delta['delta'] > 1E-8] self.longMessage = True self.assertEqual(len(diff), 0, msg='\n' + diff.to_string())
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 Compare(self, section): # Rerun the script with the modified aircraft definition self.sandbox.delete_csv_files() fdm = CreateFDM(self.sandbox) # We need to tell JSBSim that the aircraft definition is located in the # directory build/.../aircraft fdm.set_aircraft_path('aircraft') fdm.set_output_directive( self.sandbox.path_to_jsbsim_file('tests', 'output.xml')) fdm.load_script(self.script) fdm['simulation/randomseed'] = 0.0 fdm.run_ic() ExecuteUntil(fdm, 50.0) mod = pd.read_csv('output.csv', index_col=0) # Check the data are matching i.e. the time steps are the same between # the two data sets and that the output data are also the same. self.assertTrue(isDataMatching(self.ref, mod)) # Whether the data is read from the aircraft definition file or from an # external file, the results shall be exactly identical. Hence the # precision set to 0.0. diff = FindDifferences(self.ref, mod, 0.0) self.assertEqual(len(diff), 0, msg='\nTesting section "' + section + '"\n' + diff.to_string())
def test_no_output(self): fdm = CreateFDM(self.sandbox) fdm.load_script(self.script_path) fdm.run_ic() ExecuteUntil(fdm, 10.) self.assertFalse(self.sandbox.exists('output.csv'), msg="Results have unexpectedly been written to 'output.csv'")
def test_fuel_tanks_inertia(self): script_path = self.sandbox.path_to_jsbsim_file('scripts', 'c1722.xml') # The aircraft c172x does not contain an <inertia_factor> tag so we need # to add one. tree, aircraft_name, b = CopyAircraftDef(script_path, self.sandbox) tank_tag = tree.getroot().find('./propulsion/tank') inertia_factor = et.SubElement(tank_tag, 'inertia_factor') inertia_factor.text = '1.0' tree.write(self.sandbox('aircraft', aircraft_name, aircraft_name+'.xml')) fdm = CreateFDM(self.sandbox) fdm.set_aircraft_path('aircraft') fdm.load_script(script_path) fdm.run_ic() contents0 = fdm.get_property_value('propulsion/tank/contents-lbs') ixx0 = fdm.get_property_value('propulsion/tank/local-ixx-slug_ft2') iyy0 = fdm.get_property_value('propulsion/tank/local-iyy-slug_ft2') izz0 = fdm.get_property_value('propulsion/tank/local-izz-slug_ft2') # Remove half of the tank contents and check that the inertias are # updated accordingly fdm.set_property_value('propulsion/tank/contents-lbs', 0.5*contents0) contents = fdm.get_property_value('propulsion/tank/contents-lbs') ixx = fdm.get_property_value('propulsion/tank/local-ixx-slug_ft2') iyy = fdm.get_property_value('propulsion/tank/local-iyy-slug_ft2') izz = fdm.get_property_value('propulsion/tank/local-izz-slug_ft2') self.assertTrue(abs(contents-0.5*contents0) < 1E-7, msg="The tank content (%f lbs) should be %f lbs" % (contents, 0.5*contents0)) self.assertTrue(abs(ixx-0.5*ixx0) < 1E-7, msg="The tank inertia Ixx (%f slug*ft^2) should be %f slug*ft^2" % (ixx, 0.5*ixx0)) self.assertTrue(abs(iyy-0.5*iyy0) < 1E-7, msg="The tank inertia Iyy (%f slug*ft^2) should be %f slug*ft^2" % (iyy, 0.5*iyy0)) self.assertTrue(abs(izz-0.5*izz0) < 1E-7, msg="The tank inertia Izz (%f slug*ft^2) should be %f slug*ft^2" % (izz, 0.5*izz0)) # Execute the script and check that the fuel inertias have been updated # along with the consumption. ExecuteUntil(fdm, 200.0) contents = fdm.get_property_value('propulsion/tank/contents-lbs') ixx = fdm.get_property_value('propulsion/tank/local-ixx-slug_ft2') iyy = fdm.get_property_value('propulsion/tank/local-iyy-slug_ft2') izz = fdm.get_property_value('propulsion/tank/local-izz-slug_ft2') contents_ratio = contents / contents0 ixx_ratio = ixx / ixx0 iyy_ratio = iyy / iyy0 izz_ratio = izz / izz0 self.assertTrue(abs(contents_ratio - ixx_ratio) < 1E-7, msg="Ixx does not vary as the tank content does\nIxx ratio=%f\nContents ratio=%f" % (ixx_ratio, contents_ratio)) self.assertTrue(abs(contents_ratio - iyy_ratio) < 1E-7, msg="Iyy does not vary as the tank content does\nIyy ratio=%f\nContents ratio=%f" % (iyy_ratio, contents_ratio)) self.assertTrue(abs(contents_ratio - izz_ratio) < 1E-7, msg="Izz does not vary as the tank content does\nIzz ratio=%f\nContents ratio=%f" % (izz_ratio, contents_ratio))
def testSteadyFlight(self): script_name = 'c1722.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_script(script_path) # Switch the accel on fdm['fcs/accelerometer/on'] = 1.0 # Use the standard gravity (i.e. GM/r^2) fdm['simulation/gravity-model'] = 0 # Select an orientation such that frame transformations simplify fdm['ic/psi-true-rad'] = 0.0 fdm.run_ic() ExecuteUntil(fdm, 0.1) fdm['simulation/do_simple_trim'] = 1 r = fdm['position/radius-to-vehicle-ft'] pitch = fdm['attitude/theta-rad'] roll = fdm['attitude/phi-rad'] latitude = fdm['position/lat-gc-rad'] g = fdm['accelerations/gravity-ft_sec2'] omega = 0.00007292115 # Earth rotation rate in rad/sec fc = r * math.cos(latitude) * omega * omega # Centrifugal force uvw = np.array(fdm.get_propagate().get_uvw().T)[0] Omega = omega * np.array([ math.cos(pitch - latitude), math.sin(pitch - latitude) * math.sin(roll), math.sin(pitch - latitude) * math.cos(roll) ]) # Compute the acceleration measured by the accelerometer as the sum of # the gravity and the centrifugal and Coriolis forces. fa_yz = (fc * math.cos(latitude - pitch) - g * math.cos(pitch)) fa = np.array([(fc * math.sin(latitude - pitch) + g * math.sin(pitch)), fa_yz * math.sin(roll), fa_yz * math.cos(roll) ]) + np.cross(2.0 * Omega, uvw) # After the trim we are close to the equilibrium but there remains a # small residual that we have to take the bias into account fax = fa[0] + fdm['accelerations/udot-ft_sec2'] fay = fa[1] + fdm['accelerations/vdot-ft_sec2'] faz = fa[2] + fdm['accelerations/wdot-ft_sec2'] # Deltas are relaxed because the tolerances of the trimming algorithm # are quite relaxed themselves. self.assertAlmostEqual(fdm['fcs/accelerometer/X'], fax, delta=1E-6) self.assertAlmostEqual(fdm['fcs/accelerometer/Y'], fay, delta=1E-4) self.assertAlmostEqual(fdm['fcs/accelerometer/Z'], faz, delta=1E-5) del fdm
def test_moments_update(self): script_path = self.sandbox.path_to_jsbsim_file('scripts', 'weather-balloon.xml') self.fdm = CreateFDM(self.sandbox) self.fdm.load_script(script_path) self.fdm.set_output_directive( self.sandbox.path_to_jsbsim_file('tests', 'output.xml')) self.fdm.run_ic() self.CheckCGPosition() dt = self.fdm.get_property_value('simulation/dt') ExecuteUntil(self.fdm, 1.0 - 2.0 * dt) self.CheckCGPosition() # Moves the radio sonde to modify the CG location self.fdm.set_property_value('inertia/pointmass-location-X-inches', 5.0) # Check that the moment is immediately updated accordingly self.fdm.run() self.CheckCGPosition() Fbx = self.fdm.get_property_value('forces/fbx-buoyancy-lbs') Fbz = self.fdm.get_property_value('forces/fbz-buoyancy-lbs') CGx = self.fdm.get_property_value( 'inertia/cg-x-in') / 12.0 # Converts from in to ft CGz = self.fdm.get_property_value('inertia/cg-z-in') / 12.0 Mby = self.fdm.get_property_value('moments/m-buoyancy-lbsft') self.assertAlmostEqual( Fbx * CGz - Fbz * CGx, Mby, delta=1E-7, msg="Fbx*CGz-Fbz*CGx = %f and Mby = %f do not match" % (Fbx * CGz - Fbz * CGx, Mby)) # One further step to log the same results in the output file self.fdm.run() self.CheckCGPosition() csv = Table() csv.ReadCSV(self.sandbox('output.csv')) Mby = csv.get_column('M_{Buoyant} (ft-lbs)')[-1] Fbx = csv.get_column('F_{Buoyant x} (lbs)')[-1] Fbz = csv.get_column('F_{Buoyant z} (lbs)')[-1] self.assertAlmostEqual( Fbx * CGz - Fbz * CGx, Mby, delta=1E-7, msg="Fbx*CGz-Fbz*CGx = %f and Mby = %f do not match" % (Fbx * CGz - Fbz * CGx, Mby))
def test_script_start_time_0(self): script_name = 'ball_orbit.xml' script_path = self.sandbox.path_to_jsbsim_file('scripts', script_name) fdm = self.create_fdm() fdm.load_script(script_path) fdm.run_ic() self.assertEqual(fdm['simulation/sim-time-sec'], 0.0) ExecuteUntil(fdm, 5.0) fdm.reset_to_initial_conditions(1) self.assertEqual(fdm['simulation/sim-time-sec'], 0.0)
def test_output_from_file(self): tree = et.parse(self.sandbox.elude(self.script_path)) output_tag = et.SubElement(tree.getroot(), 'output') output_tag.attrib['file'] = self.sandbox.elude(self.sandbox.path_to_jsbsim_file('tests', 'output.xml')) tree.write(self.sandbox('c1722_0.xml')) fdm = CreateFDM(self.sandbox) fdm.load_script('c1722_0.xml') fdm.run_ic() ExecuteUntil(fdm, 10.) self.assertTrue(self.sandbox.exists('output.csv'), msg="The file 'output.csv' has not been created")
def test_gust_reset(self): fdm = CreateFDM(self.sandbox) fdm.load_script( self.sandbox.path_to_jsbsim_file('scripts', 'c172_cruise_8K.xml')) fdm.set_property_value('simulation/randomseed', 0.0) fdm.set_output_directive( self.sandbox.path_to_jsbsim_file('tests', 'output.xml')) fdm.run_ic() ExecuteUntil(fdm, 15.5) ref, current = Table(), Table() ref.ReadCSV(self.sandbox('output.csv')) fdm.set_property_value('simulation/randomseed', 0.0) fdm.reset_to_initial_conditions(1) ExecuteUntil(fdm, 15.5) current.ReadCSV(self.sandbox('output_0.csv')) diff = ref.compare(current) self.longMessage = True self.assertTrue(diff.empty(), msg='\n' + repr(diff))
def testScripts(self): fpectl.turnon_sigfpe() for s in self.script_list(['737_cruise_steady_turn_simplex.xml']): fdm = self.create_fdm() try: self.assertTrue(fdm.load_script(s), msg="Failed to load script %s" % (s, )) fdm.run_ic() ExecuteUntil(fdm, 30.) except Exception as e: self.fail("Script %s failed:\n%s" % (s, e.args[0]))
def test_no_script(self): fdm = self.create_fdm() fdm.load_model('c172x') fdm.load_ic('reset01.xml', True) 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)
def test_output_from_file(self): tree = et.parse(self.script_path) output_tag = et.SubElement(tree.getroot(), 'output') # Relative path from the aircraft directory to the output directive # file output_tag.attrib['file'] = os.path.join('..', '..', 'tests', 'output.xml') tree.write('c1722_0.xml') fdm = CreateFDM(self.sandbox) fdm.load_script('c1722_0.xml') fdm.run_ic() ExecuteUntil(fdm, 10.) self.assertTrue(self.sandbox.exists('output.csv'), msg="The file 'output.csv' has not been created")
def test_script_start_time(self): script_name = 'ball_orbit.xml' script_path = self.sandbox.path_to_jsbsim_file('scripts', script_name) tree = et.parse(script_path) run_tag = tree.getroot().find('./run') run_tag.attrib['start'] = '1.2' tree.write(script_name) fdm = self.create_fdm() fdm.load_script(script_name) fdm.run_ic() self.assertEqual(fdm['simulation/sim-time-sec'], 1.2) ExecuteUntil(fdm, 5.0) fdm.reset_to_initial_conditions(1) self.assertEqual(fdm['simulation/sim-time-sec'], 1.2)
def testUnitConversion(self): shutil.copy(self.sandbox.path_to_jsbsim_file('tests', 'output2.xml'),'.') shutil.copy(self.sandbox.path_to_jsbsim_file('tests', 'unitconversion.xml'),'.') script_path = self.sandbox.path_to_jsbsim_file('scripts', 'c1723.xml') fdm = CreateFDM(self.sandbox) fdm.set_output_directive('output2.xml') fdm.load_script(script_path) fdm.run_ic() ExecuteUntil(fdm, 10.) ref = pd.read_csv("output2.csv", index_col=0) self.assertAlmostEqual(np.abs(ref['/fdm/jsbsim/aero/alpha-deg']- ref['template/alpha-deg']).max(), 0.0) self.assertAlmostEqual(np.abs(ref['pre/p-aero-deg_sec']- ref['template/p-aero-deg_sec']).max(), 0.0)
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_no_script(self): fdm = self.create_fdm() 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)
def testHold(self): fdm = self.initFDM() ExecuteUntil(fdm, 1.0) fdm.hold() for i in xrange(5): fdm.run() fdm.resume() while fdm.run(): pass out = pd.read_csv('BallOut.csv', index_col=0) # Find all the data that are differing by more than 1E-8 between the # two data sets. diff = FindDifferences(self.ref, out, 1E-8) self.longMessage = True self.assertEqual(len(diff), 0, msg='\n' + diff.to_string())
def test_script_no_start_time(self): script_name = 'ball_orbit.xml' script_path = self.sandbox.path_to_jsbsim_file('scripts', script_name) tree = et.parse(script_path) run_tag = tree.getroot().find('./run') # Remove the parameter 'start' from the tag <run> del run_tag.attrib['start'] tree.write(script_name) fdm = CreateFDM(self.sandbox) fdm.load_script(script_name) fdm.run_ic() self.assertEqual(fdm['simulation/sim-time-sec'], 0.0) ExecuteUntil(fdm, 5.0) fdm.reset_to_initial_conditions(1) self.assertEqual(fdm['simulation/sim-time-sec'], 0.0) del fdm
def BuildReference(self, script_name): # Run the script self.script = self.sandbox.path_to_jsbsim_file('scripts', script_name) self.sandbox.delete_csv_files() fdm = CreateFDM(self.sandbox) fdm.set_output_directive( self.sandbox.path_to_jsbsim_file('tests', 'output.xml')) fdm.load_script(self.script) fdm['simulation/randomseed'] = 0.0 fdm.run_ic() ExecuteUntil(fdm, 50.0) self.ref = pd.read_csv("output.csv", index_col=0) # Since the script will work with modified versions of the aircraft XML # definition file, we need to make a copy of the directory that # contains all the input data of that aircraft tree, self.aircraft_name, self.path_to_jsbsim_aircrafts = CopyAircraftDef( self.script, self.sandbox) self.aircraft_path = os.path.join('aircraft', self.aircraft_name)
def test_output(self): tree = et.parse(self.sandbox.elude(self.script_path)) output_tag = et.SubElement(tree.getroot(), 'output') output_tag.attrib['name'] = 'test.csv' output_tag.attrib['type'] = 'CSV' output_tag.attrib['rate'] = '10' property_tag = et.SubElement(output_tag, 'property') property_tag.text = 'position/vrp-radius-ft' tree.write(self.sandbox('c1722_0.xml')) fdm = CreateFDM(self.sandbox) fdm.load_script('c1722_0.xml') fdm.run_ic() ExecuteUntil(fdm, 10.) self.assertTrue(self.sandbox.exists(output_tag.attrib['name']), msg="The file 'output.csv' has not been created") orig = pd.read_csv(self.sandbox('JSBout172B.csv')) test = pd.read_csv(self.sandbox('test.csv')) self.assertEqual(np.max(orig['Time']-test['Time']), 0.0) pname = '/fdm/jsbsim/' + property_tag.text self.assertEqual(np.max(orig[pname]-test[pname]), 0.0)
def test_no_script(self): fdm = CreateFDM(self.sandbox) aircraft_path = self.sandbox.path_to_jsbsim_file('aircraft') fdm.set_aircraft_path(aircraft_path) fdm.load_model('c172x') aircraft_path = os.path.join(self.sandbox.elude(aircraft_path), 'c172x') fdm.load_ic(os.path.join(aircraft_path, 'reset01.xml'), False) fdm.run_ic() self.assertEqual(fdm.get_property_value('simulation/sim-time-sec'), 0.0) ExecuteUntil(fdm, 5.0) t = fdm.get_property_value('simulation/sim-time-sec') fdm.set_property_value('simulation/do_simple_trim', 1) self.assertEqual(fdm.get_property_value('simulation/sim-time-sec'), t) fdm.reset_to_initial_conditions(1) self.assertEqual(fdm.get_property_value('simulation/sim-time-sec'), 0.0) del fdm
def test_IC_override(self): # Run the script c1724.xml script_path = self.sandbox.path_to_jsbsim_file('scripts', 'c1724.xml') fdm = self.create_fdm() fdm.load_script(script_path) vt0 = fdm['ic/vt-kts'] fdm.run_ic() self.assertEqual(fdm['simulation/sim-time-sec'], 0.0) self.assertAlmostEqual(fdm['velocities/vt-fps'], vt0 / fpstokts, delta=1E-7) ExecuteUntil(fdm, 1.0) # Check that the total velocity exported in the output file matches the # IC defined in the initialization file ref = pd.read_csv('JSBout172B.csv') self.assertEqual(ref['Time'][0], 0.0) self.assertAlmostEqual(ref['V_{Total} (ft/s)'][0], vt0 / fpstokts, delta=1E-7) # Now, we will re-run the same test but the IC will be overridden in # the script. The initial total velocity is increased by 1 ft/s vt0 += 1.0 # The script c1724.xml is loaded and the following line is added in it: # <property value="..."> ic/vt-kts </property> # The modified script is then saved with the named 'c1724_0.xml' tree = et.parse(script_path) run_tag = tree.getroot().find("run") property = et.SubElement(run_tag, 'property') property.text = 'ic/vt-kts' property.attrib['value'] = str(vt0) tree.write('c1724_0.xml') # Kill the fdm so that Windows do not block further access to # JSBout172B.csv fdm = None self.delete_fdm() # Re-run the same check than above. This time we are making sure than # the total initial velocity is increased by 1 ft/s self.sandbox.delete_csv_files() fdm = self.create_fdm() fdm.load_script('c1724_0.xml') self.assertAlmostEqual(fdm['ic/vt-kts'], vt0, delta=1E-6) fdm.run_ic() self.assertEqual(fdm['simulation/sim-time-sec'], 0.0) self.assertAlmostEqual(fdm['velocities/vt-fps'], vt0 / fpstokts, delta=1E-6) ExecuteUntil(fdm, 1.0) mod = pd.read_csv('JSBout172B.csv') self.assertAlmostEqual(mod['V_{Total} (ft/s)'][0], vt0 / fpstokts, delta=1E-6)
def CheckICValues(self, vars, f, fdm, IC_root): # Extract the IC values from XML for var in vars: var_tag = IC_root.find(var['tag']) var['specified'] = var_tag is not None if var_tag is None: var['value'] = 0.0 continue var['value'] = float(var_tag.text) if 'unit' in var_tag.attrib: conv = var['unit'][var_tag.attrib['unit']] else: conv = var['unit'][var['default_unit']] var['value'] *= conv # Sanity check, we just initialized JSBSim with the ICs, the time must # be set to 0.0 self.assertEqual(fdm['simulation/sim-time-sec'], 0.0) # Check that the properties (including in 'ic/') have been correctly # initialized (i.e. that they contain the value read from the XML # file). for var in vars: if not var['specified']: continue if self.PhiOrPsiAndGimbalLock(var, vars): continue value = var['value'] prop = fdm[var['ic_prop']] if var['tag'] == 'psi': if abs(prop - 360.0) <= 1E-8: prop = 0.0 self.assertAlmostEqual(value, prop, delta=1E-7, msg="In %s: %s should be %f but found %f" % (f, var['tag'], value, prop)) prop = fdm[var['prop']] if var['tag'] == 'psi': if abs(prop - 360.0) <= 1E-8: prop = 0.0 self.assertAlmostEqual(value, prop, delta=1E-7, msg="In %s: %s should be %f but found %f" % (f, var['tag'], value, prop)) # Execute the first second of the script. This is to make sure that the # CSV file is open and the ICs have been written in it. try: ExecuteUntil(fdm, 1.0) except RuntimeError as e: if e.args[0] == 'Trim Failed': self.fail("Trim failed in %s" % (f,)) else: raise # Sanity check: make sure that the time step 0.0 has been copied in the # CSV file. ref = pd.read_csv('check_csv_values.csv') self.assertEqual(ref['Time'][0], 0.0) # Check that the value in the CSV file equals the value read from the # IC file. for var in vars: if not var['specified']: continue if self.PhiOrPsiAndGimbalLock(var, vars): continue value = var['value'] csv_value = float(ref[var['CSV_header']][0]) if var['tag'] == 'psi': if abs(csv_value - 360.0) <= 1E-8: csv_value = 0.0 self.assertAlmostEqual(value, csv_value, delta=1E-7, msg="In {}: {} should be {} but found {}".format(f, var['tag'], value, csv_value))
def test_IC_override(self): # Run the script c1724.xml script_path = self.sandbox.path_to_jsbsim_file('scripts', 'c1724.xml') fdm = CreateFDM(self.sandbox) fdm.load_script(script_path) vt0 = fdm.get_property_value('ic/vt-kts') fdm.run_ic() self.assertEqual(fdm.get_property_value('simulation/sim-time-sec'), 0.0) self.assertAlmostEqual(fdm.get_property_value('velocities/vt-fps'), vt0 / fpstokts, delta=1E-7) ExecuteUntil(fdm, 1.0) # Check that the total velocity exported in the output file matches the # IC defined in the initialization file ref = Table() ref.ReadCSV(self.sandbox('JSBout172B.csv')) self.assertEqual(ref.get_column('Time')[1], 0.0) self.assertAlmostEqual(ref.get_column('V_{Total} (ft/s)')[1], vt0 / fpstokts, delta=1E-7) # Now, we will re-run the same test but the IC will be overridden in the # script. The initial total velocity is increased by 1 ft/s vt0 += 1.0 # The script c1724.xml is loaded and the following line is added in it: # <property value="..."> ic/vt-kts </property> # The modified script is then saved with the named 'c1724_0.xml' tree = et.parse(self.sandbox.elude(script_path)) run_tag = tree.getroot().find("./run") property = et.SubElement(run_tag, 'property') property.text = 'ic/vt-kts' property.attrib['value'] = str(vt0) tree.write(self.sandbox('c1724_0.xml')) # Re-run the same check than above. This time we are making sure than # the total initial velocity is increased by 1 ft/s self.sandbox.delete_csv_files() # Because JSBSim internals use static pointers, we cannot rely on Python # garbage collector to decide when the FDM is destroyed otherwise we can # get dangling pointers. del fdm fdm = CreateFDM(self.sandbox) fdm.load_script('c1724_0.xml') self.assertAlmostEqual(fdm.get_property_value('ic/vt-kts'), vt0, delta=1E-6) fdm.run_ic() self.assertEqual(fdm.get_property_value('simulation/sim-time-sec'), 0.0) self.assertAlmostEqual(fdm.get_property_value('velocities/vt-fps'), vt0 / fpstokts, delta=1E-6) ExecuteUntil(fdm, 1.0) mod = Table() mod.ReadCSV(self.sandbox('JSBout172B.csv')) self.assertAlmostEqual(mod.get_column('V_{Total} (ft/s)')[1], vt0 / fpstokts, delta=1E-6)