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_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 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 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_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_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 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 testDragFunctions(self): fdm = CreateFDM(self.sandbox) self.script_path = self.sandbox.path_to_jsbsim_file('scripts', 'x153.xml') fdm.load_script(self.script_path) fdm.set_output_directive(self.sandbox.path_to_jsbsim_file('tests', 'output.xml')) fdm.run_ic() while fdm.run(): pass results = pd.read_csv('output.csv', index_col=0) Fdrag = results['F_{Drag} (lbs)'] CDmin = results['aero/coefficient/CDmin'] CDi = results['aero/coefficient/CDi'] self.assertAlmostEqual(abs(Fdrag/(CDmin+CDi)).max(), 1.0, delta=1E-5)
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 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 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_set_initial_geodetic_latitude(self): script_path = self.sandbox.path_to_jsbsim_file('scripts', '737_cruise.xml') output_file = self.sandbox.path_to_jsbsim_file('tests', 'output.xml') fdm = CreateFDM(self.sandbox) fdm.load_script(script_path) fdm.set_output_directive(output_file) alt = fdm['ic/h-sl-ft'] glat = fdm['ic/lat-geod-deg'] - 30. fdm['ic/lat-geod-deg'] = glat fdm.run_ic() self.assertAlmostEqual(fdm['ic/h-sl-ft'], alt) self.assertAlmostEqual(fdm['ic/lat-geod-deg'], glat) self.assertAlmostEqual(fdm['ic/lat-geod-rad'], glat*math.pi/180.) self.assertAlmostEqual(fdm['position/lat-geod-deg'], glat) # Sanity check: make sure that the time step 0.0 has been copied in the # CSV file. ref = pd.read_csv('output.csv') self.assertEqual(ref['Time'][0], 0.0) self.assertAlmostEqual(ref['Latitude Geodetic (deg)'][0], glat)
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 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_set_initial_geodetic_latitude(self): script_path = self.sandbox.path_to_jsbsim_file('scripts', '737_cruise.xml') output_file = self.sandbox.path_to_jsbsim_file('tests', 'output.xml') fdm = CreateFDM(self.sandbox) fdm.load_script(script_path) fdm.set_output_directive(output_file) alt = fdm['ic/h-sl-ft'] glat = fdm['ic/lat-geod-deg'] - 30. fdm['ic/lat-geod-deg'] = glat fdm.run_ic() self.assertAlmostEqual(fdm['ic/h-sl-ft'], alt) self.assertAlmostEqual(fdm['ic/lat-geod-deg'], glat) self.assertAlmostEqual(fdm['ic/lat-geod-rad'], glat * math.pi / 180.) self.assertAlmostEqual(fdm['position/lat-geod-deg'], glat) # Sanity check: make sure that the time step 0.0 has been copied in the # CSV file. ref = pd.read_csv('output.csv') self.assertEqual(ref['Time'][0], 0.0) self.assertAlmostEqual(ref['Latitude Geodetic (deg)'][0], glat)
def test_point_mass_inertia(self): script_path = self.sandbox.path_to_jsbsim_file('scripts', 'J2460.xml') fdm = CreateFDM(self.sandbox) fdm.set_output_directive( self.sandbox.path_to_jsbsim_file('tests', 'output.xml')) fdm.load_script(script_path) fdm.run_ic() ExecuteUntil(fdm, 50.0) ref = pd.read_csv("output.csv", index_col=0) tree, aircraft_name, path_to_jsbsim_aircrafts = CopyAircraftDef( script_path, self.sandbox) pointmass_element = tree.getroot().find( 'mass_balance/pointmass//form/..') weight_element = pointmass_element.find('weight') weight = float(weight_element.text) form_element = pointmass_element.find('form') radius_element = form_element.find('radius') radius, length = (0.0, 0.0) if radius_element is not None: radius = float(radius_element.text) length_element = form_element.find('length') if length_element is not None: length = float(length_element.text) shape = form_element.attrib['shape'] pointmass_element.remove(form_element) inertia = np.zeros((3, 3)) if string.strip(shape) == 'tube': inertia[0, 0] = radius * radius inertia[1, 1] = (6.0 * inertia[0, 0] + length * length) / 12.0 inertia[2, 2] = inertia[1, 1] inertia = inertia * weight / 32.174049 # converting slugs to lbs ixx_element = et.SubElement(pointmass_element, 'ixx') ixx_element.text = str(inertia[0, 0]) iyy_element = et.SubElement(pointmass_element, 'iyy') iyy_element.text = str(inertia[1, 1]) izz_element = et.SubElement(pointmass_element, 'izz') izz_element.text = str(inertia[2, 2]) tree.write( self.sandbox('aircraft', aircraft_name, aircraft_name + '.xml')) # 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.set_aircraft_path('aircraft') fdm.set_output_directive( self.sandbox.path_to_jsbsim_file('tests', 'output.xml')) fdm.load_script(script_path) 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(ref, mod)) # Find all the data that are differing by more than 1E-8 between the # two data sets. diff = FindDifferences(ref, mod, 1E-8) self.longMessage = True self.assertEqual(len(diff), 0, msg='\n' + diff.to_string())
def test_point_mass_inertia(self): script_path = self.sandbox.path_to_jsbsim_file('scripts', 'J2460.xml') fdm = CreateFDM(self.sandbox) fdm.set_output_directive(self.sandbox.path_to_jsbsim_file('tests', 'output.xml')) fdm.load_script(script_path) fdm.run_ic() ExecuteUntil(fdm, 50.0) ref = pd.read_csv("output.csv", index_col=0) tree, aircraft_name, path_to_jsbsim_aircrafts = CopyAircraftDef(script_path, self.sandbox) pointmass_element = tree.getroot().find('mass_balance/pointmass//form/..') weight_element = pointmass_element.find('weight') weight = float(weight_element.text) form_element = pointmass_element.find('form') radius_element = form_element.find('radius') radius, length = (0.0, 0.0) if radius_element is not None: radius = float(radius_element.text) length_element = form_element.find('length') if length_element is not None: length = float(length_element.text) shape = form_element.attrib['shape'] pointmass_element.remove(form_element) inertia = np.zeros((3, 3)) if string.strip(shape) == 'tube': inertia[0, 0] = radius * radius inertia[1, 1] = (6.0 * inertia[0, 0] + length * length) / 12.0 inertia[2, 2] = inertia[1, 1] inertia = inertia * weight / 32.174049 # converting slugs to lbs ixx_element = et.SubElement(pointmass_element, 'ixx') ixx_element.text = str(inertia[0, 0]) iyy_element = et.SubElement(pointmass_element, 'iyy') iyy_element.text = str(inertia[1, 1]) izz_element = et.SubElement(pointmass_element, 'izz') izz_element.text = str(inertia[2, 2]) tree.write(self.sandbox('aircraft', aircraft_name, aircraft_name+'.xml')) # 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.set_aircraft_path('aircraft') fdm.set_output_directive(self.sandbox.path_to_jsbsim_file('tests', 'output.xml')) fdm.load_script(script_path) 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(ref, mod)) # Find all the data that are differing by more than 1E-8 between the # two data sets. diff = FindDifferences(ref, mod, 1E-8) self.longMessage = True self.assertEqual(len(diff), 0, msg='\n'+diff.to_string())
class CheckMomentsUpdate(JSBSimTestCase): def CheckCGPosition(self): weight = self.fdm['inertia/weight-lbs'] empty_weight = self.fdm['inertia/empty-weight-lbs'] contents = self.fdm['buoyant_forces/gas-cell/contents-mol'] radiosonde_weight = weight - empty_weight - contents * mol2lbs CGx = self.fdm['inertia/cg-x-in'] CGy = self.fdm['inertia/cg-y-in'] CGz = self.fdm['inertia/cg-z-in'] X = self.fdm['inertia/pointmass-location-X-inches'] Y = self.fdm['inertia/pointmass-location-Y-inches'] Z = self.fdm['inertia/pointmass-location-Z-inches'] self.assertAlmostEqual(CGx, X * radiosonde_weight / weight, delta=1E-7) self.assertAlmostEqual(CGy, Y * radiosonde_weight / weight, delta=1E-7) self.assertAlmostEqual(CGz, Z * radiosonde_weight / weight, delta=1E-7) 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['simulation/dt'] ExecuteUntil(self.fdm, 1.0-2.0*dt) self.CheckCGPosition() # Moves the radio sonde to modify the CG location self.fdm['inertia/pointmass-location-X-inches'] = 5.0 # Check that the moment is immediately updated accordingly self.fdm.run() self.CheckCGPosition() Fbx = self.fdm['forces/fbx-buoyancy-lbs'] Fbz = self.fdm['forces/fbz-buoyancy-lbs'] CGx = self.fdm['inertia/cg-x-in'] / 12.0 # Converts from in to ft CGz = self.fdm['inertia/cg-z-in'] / 12.0 Mby = self.fdm['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 = pd.read_csv('output.csv') Mby = csv['M_{Buoyant} (ft-lbs)'].iget(-1) Fbx = csv['F_{Buoyant x} (lbs)'].iget(-1) Fbz = csv['F_{Buoyant z} (lbs)'].iget(-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))
class CheckMomentsUpdate(unittest.TestCase): def setUp(self): self.sandbox = SandBox() def tearDown(self): self.sandbox.erase() def CheckCGPosition(self): weight = self.fdm.get_property_value('inertia/weight-lbs') empty_weight = self.fdm.get_property_value('inertia/empty-weight-lbs') contents = self.fdm.get_property_value('buoyant_forces/gas-cell/contents-mol') radiosonde_weight = weight - empty_weight - contents * mol2lbs CGx = self.fdm.get_property_value('inertia/cg-x-in') CGy = self.fdm.get_property_value('inertia/cg-y-in') CGz = self.fdm.get_property_value('inertia/cg-z-in') X = self.fdm.get_property_value('inertia/pointmass-location-X-inches') Y = self.fdm.get_property_value('inertia/pointmass-location-Y-inches') Z = self.fdm.get_property_value('inertia/pointmass-location-Z-inches') self.assertAlmostEqual(CGx, X * radiosonde_weight / weight, delta = 1E-7) self.assertAlmostEqual(CGy, Y * radiosonde_weight / weight, delta = 1E-7) self.assertAlmostEqual(CGz, Z * radiosonde_weight / weight, delta = 1E-7) 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))
class CheckMomentsUpdate(JSBSimTestCase): def CheckCGPosition(self): weight = self.fdm['inertia/weight-lbs'] empty_weight = self.fdm['inertia/empty-weight-lbs'] contents = self.fdm['buoyant_forces/gas-cell/contents-mol'] radiosonde_weight = weight - empty_weight - contents * mol2lbs CGx = self.fdm['inertia/cg-x-in'] CGy = self.fdm['inertia/cg-y-in'] CGz = self.fdm['inertia/cg-z-in'] X = self.fdm['inertia/pointmass-location-X-inches'] Y = self.fdm['inertia/pointmass-location-Y-inches'] Z = self.fdm['inertia/pointmass-location-Z-inches'] self.assertAlmostEqual(CGx, X * radiosonde_weight / weight, delta=1E-7) self.assertAlmostEqual(CGy, Y * radiosonde_weight / weight, delta=1E-7) self.assertAlmostEqual(CGz, Z * radiosonde_weight / weight, delta=1E-7) 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['simulation/dt'] ExecuteUntil(self.fdm, 1.0 - 2.0 * dt) self.CheckCGPosition() # Moves the radio sonde to modify the CG location self.fdm['inertia/pointmass-location-X-inches'] = 5.0 # Check that the moment is immediately updated accordingly self.fdm.run() self.CheckCGPosition() Fbx = self.fdm['forces/fbx-buoyancy-lbs'] Fbz = self.fdm['forces/fbz-buoyancy-lbs'] CGx = self.fdm['inertia/cg-x-in'] / 12.0 # Converts from in to ft CGz = self.fdm['inertia/cg-z-in'] / 12.0 Mby = self.fdm['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 = pd.read_csv('output.csv') Mby = csv['M_{Buoyant} (ft-lbs)'].iget(-1) Fbx = csv['F_{Buoyant x} (lbs)'].iget(-1) Fbz = csv['F_{Buoyant z} (lbs)'].iget(-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_point_mass_inertia(self): script_path = self.sandbox.path_to_jsbsim_file('scripts', 'J2460.xml') fdm = CreateFDM(self.sandbox) fdm.set_output_directive(self.sandbox.path_to_jsbsim_file('tests', 'output.xml')) fdm.load_script(script_path) fdm.run_ic() ExecuteUntil(fdm, 50.0) ref = Table() ref.ReadCSV(self.sandbox("output.csv")) tree, aircraft_name, path_to_jsbsim_aircrafts = CopyAircraftDef(script_path, self.sandbox) pointmass_element = tree.getroot().find('mass_balance/pointmass//form/..') weight_element = pointmass_element.find('weight') weight = float(weight_element.text) form_element = pointmass_element.find('form') radius_element = form_element.find('radius') radius, length = (0.0, 0.0) if radius_element is not None: radius = float(radius_element.text) length_element = form_element.find('length') if length_element is not None: length = float(length_element.text) shape = form_element.attrib['shape'] pointmass_element.remove(form_element) inertia = numpy.zeros((3,3)) if string.strip(shape) == 'tube': inertia[0,0] = radius * radius inertia[1,1] = (6.0 * inertia[0,0] + length * length) / 12.0 inertia[2,2] = inertia[1,1] inertia = inertia * weight / 32.174049 # conversion between slug and lb ixx_element = et.SubElement(pointmass_element, 'ixx') ixx_element.text = str(inertia[0,0]) iyy_element = et.SubElement(pointmass_element, 'iyy') iyy_element.text = str(inertia[1,1]) izz_element = et.SubElement(pointmass_element, 'izz') izz_element.text = str(inertia[2,2]) tree.write(self.sandbox('aircraft', aircraft_name, aircraft_name+'.xml')) fdm = CreateFDM(self.sandbox) fdm.set_aircraft_path('aircraft') fdm.set_output_directive(self.sandbox.path_to_jsbsim_file('tests', 'output.xml')) fdm.load_script(script_path) fdm.run_ic() ExecuteUntil(fdm, 50.0) mod = Table() mod.ReadCSV(self.sandbox("output.csv")) diff = ref.compare(mod) self.assertTrue(diff.empty(), msg='\n'+repr(diff))
class CheckMomentsUpdate(unittest.TestCase): def setUp(self): self.sandbox = SandBox() def tearDown(self): self.sandbox.erase() def CheckCGPosition(self): weight = self.fdm.get_property_value('inertia/weight-lbs') empty_weight = self.fdm.get_property_value('inertia/empty-weight-lbs') contents = self.fdm.get_property_value( 'buoyant_forces/gas-cell/contents-mol') radiosonde_weight = weight - empty_weight - contents * mol2lbs CGx = self.fdm.get_property_value('inertia/cg-x-in') CGy = self.fdm.get_property_value('inertia/cg-y-in') CGz = self.fdm.get_property_value('inertia/cg-z-in') X = self.fdm.get_property_value('inertia/pointmass-location-X-inches') Y = self.fdm.get_property_value('inertia/pointmass-location-Y-inches') Z = self.fdm.get_property_value('inertia/pointmass-location-Z-inches') self.assertAlmostEqual(CGx, X * radiosonde_weight / weight, delta=1E-7) self.assertAlmostEqual(CGy, Y * radiosonde_weight / weight, delta=1E-7) self.assertAlmostEqual(CGz, Z * radiosonde_weight / weight, delta=1E-7) 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))