def setUp(self): JSBSimTestCase.setUp(self) self.fdm = CreateFDM(self.sandbox) self.script_path = self.sandbox.path_to_jsbsim_file('scripts', 'c1722.xml') # Read the time step 'dt' from the script file self.tree = et.parse(self.script_path) root = self.tree.getroot() use_tag = root.find('use') aircraft_name = use_tag.attrib['aircraft'] self.run_tag = root.find('run') self.dt = float(self.run_tag.attrib['dt']) # Read the date at which the trim will be run for event in root.findall('run/event'): if event.attrib['name'] == 'Trim': cond_tag = event.find('condition') self.trim_date = float(cond_tag.text.split()[-1]) break # Read the output rate and the output file from the aircraft file aircraft_path = self.sandbox.path_to_jsbsim_file('aircraft', aircraft_name, append_xml(aircraft_name)) tree = et.parse(aircraft_path) output_tag = tree.getroot().find('output') self.output_file = output_tag.attrib['name'] self.rateHz = float(output_tag.attrib['rate']) self.rate = int(1.0 / (self.rateHz * self.dt))
def LoadScript(self, tree, script_path, prop_output_to_CSV=[]): # Make a local copy of files referenced by the script. for element in list(tree.getroot()): if 'file' in element.keys(): name = append_xml(element.attrib['file']) name_with_path = os.path.join(os.path.dirname(script_path), name) if os.path.exists(name_with_path): shutil.copy(name_with_path, name) # Generate a CSV file to check that it is correctly initialized # with the initial values output_tag = et.SubElement(tree.getroot(), 'output') output_tag.attrib['name'] = 'check_csv_values.csv' output_tag.attrib['type'] = 'CSV' output_tag.attrib['rate'] = '10' position_tag = et.SubElement(output_tag, 'position') position_tag.text = 'ON' velocities_tag = et.SubElement(output_tag, 'velocities') velocities_tag.text = 'ON' for props in prop_output_to_CSV: property_tag = et.SubElement(output_tag, 'property') property_tag.text = props f = os.path.split(script_path)[-1] # Script name tree.write(f) # Initialize the script fdm = self.create_fdm() self.assertTrue(fdm.load_script(f), msg="Failed to load script %s" % (f,)) fdm.run_ic() return (f, fdm)
def setUp(self): self.sandbox = SandBox() self.fdm = CreateFDM(self.sandbox) self.script_path = self.sandbox.path_to_jsbsim_file('scripts', 'c1722.xml') # Read the time step 'dt' from the script file self.tree = et.parse(self.sandbox.elude(self.script_path)) root = self.tree.getroot() use_tag = root.find("./use") aircraft_name = use_tag.attrib['aircraft'] self.run_tag = root.find("./run") self.dt = float(self.run_tag.attrib['dt']) # Read the date at which the trim will be run event_tags = root.findall('./run/event') for event in event_tags: if event.attrib['name'] == 'Trim': cond_tag = event.find('./condition') self.trim_date = float(string.split(cond_tag.text)[-1]) break # Read the output rate and the output file from the aircraft file aircraft_path = self.sandbox.path_to_jsbsim_file('aircraft', aircraft_name, append_xml(aircraft_name)) tree = et.parse(self.sandbox.elude(aircraft_path)) output_tag = tree.getroot().find("./output") self.output_file = self.sandbox(output_tag.attrib['name']) self.rateHz = float(output_tag.attrib['rate']) self.rate = int(1.0 / (self.rateHz * self.dt))
def test_CAS_ic(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, path_to_jsbsim_aircrafts = CopyAircraftDef(script_path, self.sandbox) self.addPitotTube(tree.getroot(), 5.0) tree.write(self.sandbox('aircraft', aircraft_name, aircraft_name+'.xml')) # Read the CAS specified in the IC file tree = et.parse(script_path) use_element = tree.getroot().find('use') IC_file = use_element.attrib['initialize'] tree = et.parse(os.path.join(path_to_jsbsim_aircrafts, append_xml(IC_file))) vc_tag = tree.getroot().find('./vc') VCAS = float(vc_tag.text) if 'unit' in vc_tag.attrib and vc_tag.attrib['unit'] == 'FT/SEC': VCAS /= 1.68781 # Converts in kts # Run the IC and check that the model is initialized correctly fdm = CreateFDM(self.sandbox) fdm.set_aircraft_path('aircraft') fdm.load_script(script_path) fdm.run_ic() self.assertAlmostEqual(fdm['ic/vc-kts'], VCAS, delta=1E-7) self.assertAlmostEqual(fdm['velocities/vc-kts'], VCAS, delta=1E-7)
def setUp(self): JSBSimTestCase.setUp(self) self.fdm = CreateFDM(self.sandbox) self.script_path = self.sandbox.path_to_jsbsim_file( 'scripts', 'c1722.xml') # Read the time step 'dt' from the script file self.tree = et.parse(self.script_path) root = self.tree.getroot() use_tag = root.find('use') aircraft_name = use_tag.attrib['aircraft'] self.run_tag = root.find('run') self.dt = float(self.run_tag.attrib['dt']) # Read the date at which the trim will be run for event in root.findall('run/event'): if event.attrib['name'] == 'Trim': cond_tag = event.find('condition') self.trim_date = float(cond_tag.text.split()[-1]) break # Read the output rate and the output file from the aircraft file aircraft_path = self.sandbox.path_to_jsbsim_file( 'aircraft', aircraft_name, append_xml(aircraft_name)) tree = et.parse(aircraft_path) output_tag = tree.getroot().find('output') self.output_file = output_tag.attrib['name'] self.rateHz = float(output_tag.attrib['rate']) self.rate = int(1.0 / (self.rateHz * self.dt))
def InsertAndCompare(self, section_element, tree): file_name = append_xml(section_element.attrib['file']) section_file = os.path.join(self.path_to_jsbsim_aircrafts, file_name) # If <section> is actually <system>, we need to iterate over all the # directories in which the file is allowed to be stored until the file # is located. if not os.path.exists( section_file) and section_element.tag == 'system': section_file = os.path.join(self.path_to_jsbsim_aircrafts, "systems", file_name) if not os.path.exists(section_file): section_file = self.sandbox.path_to_jsbsim_file( "systems", file_name) # The original <section> tag is dropped and replaced by the content of # the file. section_root = et.parse(section_file).getroot() del section_element.attrib['file'] section_element.attrib.update(section_root.attrib) section_element.extend(section_root) tree.write( os.path.join(self.aircraft_path, self.aircraft_name + '.xml')) self.Compare(section_element.tag + " file:" + section_file)
def InsertAndCompare(self, section_element, tree): file_name = append_xml(section_element.attrib['file']) section_file = os.path.join(self.path_to_jsbsim_aircrafts, file_name) # If <section> is actually <system>, we need to iterate over all the # directories in which the file is allowed to be stored until the file # is located. if not os.path.exists(section_file) and section_element.tag == 'system': section_file = os.path.join(self.path_to_jsbsim_aircrafts, "systems", file_name) if not os.path.exists(section_file): section_file = self.sandbox.path_to_jsbsim_file("systems", file_name) # The original <section> tag is dropped and replaced by the content of # the file. section_root = et.parse(section_file).getroot() del section_element.attrib['file'] section_element.attrib.update(section_root.attrib) section_element.extend(section_root) tree.write(os.path.join(self.aircraft_path, self.aircraft_name+'.xml')) self.Compare(section_element.tag+" file:"+section_file)
def LoadScript(self, tree, script_path, prop_output_to_CSV=[]): # Make a local copy of files referenced by the script. for element in list(tree.getroot()): if 'file' in element.keys(): name = append_xml(element.attrib['file']) name_with_path = os.path.join(os.path.dirname(script_path), name) if os.path.exists(name_with_path): shutil.copy(name_with_path, name) # Generate a CSV file to check that it is correctly initialized # with the initial values output_tag = et.SubElement(tree.getroot(), 'output') output_tag.attrib['name'] = 'check_csv_values.csv' output_tag.attrib['type'] = 'CSV' output_tag.attrib['rate'] = '10' position_tag = et.SubElement(output_tag, 'position') position_tag.text = 'ON' velocities_tag = et.SubElement(output_tag, 'velocities') velocities_tag.text = 'ON' for props in prop_output_to_CSV: property_tag = et.SubElement(output_tag, 'property') property_tag.text = props f = os.path.split(script_path)[-1] # Script name tree.write(f) # Initialize the script fdm = CreateFDM(self.sandbox) self.assertTrue(fdm.load_script(f), msg="Failed to load script %s" % (f,)) fdm.run_ic() return (f, fdm)
def testAircrafts(self): aircraft_path = self.sandbox.elude(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, append_xml(d)) # 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)) break 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, append_xml(d)) # 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 setUp(self): self.sandbox = SandBox() self.fdm = CreateFDM(self.sandbox) self.script_path = self.sandbox.path_to_jsbsim_file("scripts", "c1722.xml") # Read the time step 'dt' from the script file self.tree = et.parse(self.sandbox.elude(self.script_path)) root = self.tree.getroot() use_tag = root.find("./use") aircraft_name = use_tag.attrib["aircraft"] self.run_tag = root.find("./run") self.dt = float(self.run_tag.attrib["dt"]) # Read the date at which the trim will be run event_tags = root.findall("./run/event") for event in event_tags: if event.attrib["name"] == "Trim": cond_tag = event.find("./condition") self.trim_date = float(string.split(cond_tag.text)[-1]) break # Read the output rate and the output file from the aircraft file aircraft_path = self.sandbox.path_to_jsbsim_file("aircraft", aircraft_name, append_xml(aircraft_name)) tree = et.parse(self.sandbox.elude(aircraft_path)) output_tag = tree.getroot().find("./output") self.output_file = self.sandbox(output_tag.attrib["name"]) self.rateHz = float(output_tag.attrib["rate"]) self.rate = int(1.0 / (self.rateHz * self.dt))
def getElementTrees(self, s): # Read the IC file name from the script tree = et.parse(s) use_tag = tree.getroot().find('use') aircraft_name = use_tag.attrib['aircraft'] aircraft_path = os.path.join('aircraft', aircraft_name) path_to_jsbsim_aircrafts = self.sandbox.path_to_jsbsim_file(aircraft_path) IC_file = append_xml(use_tag.attrib['initialize']) IC_tree = et.parse(os.path.join(path_to_jsbsim_aircrafts, IC_file)) return (tree, IC_tree)
def test_initial_conditions(self): # A dictionary that contains the XML tags to extract from the IC file # along with the name of the properties that contain the values # extracted from the IC file. vars = [{'tag': 'vt', 'unit': convtofps, 'default_unit': 'FT/SEC', 'ic_prop': 'ic/vt-fps', 'prop': 'velocities/vt-fps', 'CSV_header': 'V_{Total} (ft/s)'}, {'tag': 'ubody', 'unit': convtofps, 'default_unit': 'FT/SEC', 'ic_prop': 'ic/u-fps', 'prop': 'velocities/u-fps', 'CSV_header': 'UBody'}, {'tag': 'vbody', 'unit': convtofps, 'default_unit': 'FT/SEC', 'ic_prop': 'ic/v-fps', 'prop': 'velocities/v-fps', 'CSV_header': 'VBody'}, {'tag': 'wbody', 'unit': convtofps, 'default_unit': 'FT/SEC', 'ic_prop': 'ic/w-fps', 'prop': 'velocities/w-fps', 'CSV_header': 'WBody'}, {'tag': 'vnorth', 'unit': convtofps, 'default_unit': 'FT/SEC', 'ic_prop': 'ic/vn-fps', 'prop': 'velocities/v-north-fps', 'CSV_header': 'V_{North} (ft/s)'}, {'tag': 'veast', 'unit': convtofps, 'default_unit': 'FT/SEC', 'ic_prop': 'ic/ve-fps', 'prop': 'velocities/v-east-fps', 'CSV_header': 'V_{East} (ft/s)'}, {'tag': 'vdown', 'unit': convtofps, 'default_unit': 'FT/SEC', 'ic_prop': 'ic/vd-fps', 'prop': 'velocities/v-down-fps', 'CSV_header': 'V_{Down} (ft/s)'}, {'tag': 'latitude', 'unit': convtodeg, 'default_unit': 'RAD', 'ic_prop': 'ic/lat-gc-deg', 'prop': 'position/lat-gc-deg', 'CSV_header': 'Latitude (deg)'}, {'tag': 'longitude', 'unit': convtodeg, 'default_unit': 'RAD', 'ic_prop': 'ic/long-gc-deg', 'prop': 'position/long-gc-deg', 'CSV_header': 'Longitude (deg)'}, {'tag': 'altitude', 'unit': convtoft, 'default_unit': 'FT', 'ic_prop': 'ic/h-agl-ft', 'prop': 'position/h-agl-ft', 'CSV_header': 'Altitude AGL (ft)'}, {'tag': 'altitudeAGL', 'unit': convtoft, 'default_unit': 'FT', 'ic_prop': 'ic/h-agl-ft', 'prop': 'position/h-agl-ft', 'CSV_header': 'Altitude AGL (ft)'}, {'tag': 'altitudeMSL', 'unit': convtoft, 'default_unit': 'FT', 'ic_prop': 'ic/h-sl-ft', 'prop': 'position/h-sl-ft', 'CSV_header': 'Altitude ASL (ft)'}, {'tag': 'phi', 'unit': convtodeg, 'default_unit': 'RAD', 'ic_prop': 'ic/phi-deg', 'prop': 'attitude/phi-deg', 'CSV_header': 'Phi (deg)'}, {'tag': 'theta', 'unit': convtodeg, 'default_unit': 'RAD', 'ic_prop': 'ic/theta-deg', 'prop': 'attitude/theta-deg', 'CSV_header': 'Theta (deg)'}, {'tag': 'psi', 'unit': convtodeg, 'default_unit': 'RAD', 'ic_prop': 'ic/psi-true-deg', 'prop': 'attitude/psi-deg', 'CSV_header': 'Psi (deg)'}, {'tag': 'elevation', 'unit': convtoft, 'default_unit': 'FT', 'ic_prop': 'ic/terrain-elevation-ft', 'prop': 'position/terrain-elevation-asl-ft', 'CSV_header': 'Terrain Elevation (ft)'}] script_path = self.sandbox.path_to_jsbsim_file('scripts') for f in os.listdir(self.sandbox.elude(script_path)): # TODO These scripts need some further investigation if f in ('ZLT-NT-moored-1.xml',): continue fullpath = os.path.join(self.sandbox.elude(script_path), f) # Does f contains a JSBSim script ? if not CheckXMLFile(fullpath, 'runscript'): continue # Read the IC file name from the script tree = et.parse(fullpath) root = tree.getroot() use_tag = root.find('use') aircraft_name = use_tag.attrib['aircraft'] aircraft_path = os.path.join('aircraft', aircraft_name) path_to_jsbsim_aircrafts = self.sandbox.elude(self.sandbox.path_to_jsbsim_file(aircraft_path)) IC_file = append_xml(use_tag.attrib['initialize']) IC_tree = et.parse(os.path.join(path_to_jsbsim_aircrafts, IC_file)) IC_root = IC_tree.getroot() # Only testing version 1.0 of init files if 'version' in IC_root.attrib: if float(IC_root.attrib['version']) == 2.0: continue # 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 not var['specified']: 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 # Generate a CSV file to check that it is correctly initialized with # the initial values output_tag = et.SubElement(root, 'output') output_tag.attrib['name'] = 'check_csv_values.csv' output_tag.attrib['type'] = 'CSV' output_tag.attrib['rate'] = '10' position_tag = et.SubElement(output_tag, 'position') position_tag.text = 'ON' velocities_tag = et.SubElement(output_tag, 'velocities') velocities_tag.text = 'ON' tree.write(self.sandbox(f)) # Initialize the script fdm = CreateFDM(self.sandbox) fdm.load_script(f) fdm.run_ic() # Sanity check, we just initialized JSBSim with the ICs, the time # must be set to 0.0 self.assertEqual(fdm.get_property_value('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 value = var['value'] prop = fdm.get_property_value(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 script %s: %s should be %f but found %f" % (f, var['tag'], value, prop)) prop = fdm.get_property_value(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 script %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. ExecuteUntil(fdm, 1.0) # Copies the CSV file content in a table ref = pd.read_csv(self.sandbox('check_csv_values.csv')) # Sanity check: make sure that the time step 0.0 has been copied in # the CSV file. 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 value = var['value'] csv_value = 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 script %s: %s should be %f but found %f" % (f, var['tag'], value, csv_value)) del fdm
def test_initial_conditions(self): prop_output_to_CSV = ['velocities/vc-kts'] # A dictionary that contains the XML tags to extract from the IC file # along with the name of the properties that contain the values # extracted from the IC file. vars = [{'tag': 'vt', 'unit': convtofps, 'default_unit': 'FT/SEC', 'ic_prop': 'ic/vt-fps', 'prop': 'velocities/vt-fps', 'CSV_header': 'V_{Total} (ft/s)'}, {'tag': 'vc', 'unit': convtokts, 'default_unit': 'KTS', 'ic_prop': 'ic/vc-kts', 'prop': 'velocities/vc-kts', 'CSV_header': '/fdm/jsbsim/velocities/vc-kts'}, {'tag': 'ubody', 'unit': convtofps, 'default_unit': 'FT/SEC', 'ic_prop': 'ic/u-fps', 'prop': 'velocities/u-fps', 'CSV_header': 'UBody'}, {'tag': 'vbody', 'unit': convtofps, 'default_unit': 'FT/SEC', 'ic_prop': 'ic/v-fps', 'prop': 'velocities/v-fps', 'CSV_header': 'VBody'}, {'tag': 'wbody', 'unit': convtofps, 'default_unit': 'FT/SEC', 'ic_prop': 'ic/w-fps', 'prop': 'velocities/w-fps', 'CSV_header': 'WBody'}, {'tag': 'vnorth', 'unit': convtofps, 'default_unit': 'FT/SEC', 'ic_prop': 'ic/vn-fps', 'prop': 'velocities/v-north-fps', 'CSV_header': 'V_{North} (ft/s)'}, {'tag': 'veast', 'unit': convtofps, 'default_unit': 'FT/SEC', 'ic_prop': 'ic/ve-fps', 'prop': 'velocities/v-east-fps', 'CSV_header': 'V_{East} (ft/s)'}, {'tag': 'vdown', 'unit': convtofps, 'default_unit': 'FT/SEC', 'ic_prop': 'ic/vd-fps', 'prop': 'velocities/v-down-fps', 'CSV_header': 'V_{Down} (ft/s)'}, {'tag': 'latitude', 'unit': convtodeg, 'default_unit': 'RAD', 'ic_prop': 'ic/lat-gc-deg', 'prop': 'position/lat-gc-deg', 'CSV_header': 'Latitude (deg)'}, {'tag': 'longitude', 'unit': convtodeg, 'default_unit': 'RAD', 'ic_prop': 'ic/long-gc-deg', 'prop': 'position/long-gc-deg', 'CSV_header': 'Longitude (deg)'}, {'tag': 'altitude', 'unit': convtoft, 'default_unit': 'FT', 'ic_prop': 'ic/h-agl-ft', 'prop': 'position/h-agl-ft', 'CSV_header': 'Altitude AGL (ft)'}, {'tag': 'altitudeAGL', 'unit': convtoft, 'default_unit': 'FT', 'ic_prop': 'ic/h-agl-ft', 'prop': 'position/h-agl-ft', 'CSV_header': 'Altitude AGL (ft)'}, {'tag': 'altitudeMSL', 'unit': convtoft, 'default_unit': 'FT', 'ic_prop': 'ic/h-sl-ft', 'prop': 'position/h-sl-ft', 'CSV_header': 'Altitude ASL (ft)'}, {'tag': 'phi', 'unit': convtodeg, 'default_unit': 'RAD', 'ic_prop': 'ic/phi-deg', 'prop': 'attitude/phi-deg', 'CSV_header': 'Phi (deg)'}, {'tag': 'theta', 'unit': convtodeg, 'default_unit': 'RAD', 'ic_prop': 'ic/theta-deg', 'prop': 'attitude/theta-deg', 'CSV_header': 'Theta (deg)'}, {'tag': 'psi', 'unit': convtodeg, 'default_unit': 'RAD', 'ic_prop': 'ic/psi-true-deg', 'prop': 'attitude/psi-deg', 'CSV_header': 'Psi (deg)'}, {'tag': 'elevation', 'unit': convtoft, 'default_unit': 'FT', 'ic_prop': 'ic/terrain-elevation-ft', 'prop': 'position/terrain-elevation-asl-ft', 'CSV_header': 'Terrain Elevation (ft)'}] script_path = self.sandbox.path_to_jsbsim_file('scripts') for f in os.listdir(self.sandbox.elude(script_path)): # TODO These scripts need some further investigation if f in ('ZLT-NT-moored-1.xml', '737_cruise_steady_turn_simplex.xml'): continue fullpath = os.path.join(self.sandbox.elude(script_path), f) # Does f contains a JSBSim script ? if not CheckXMLFile(fullpath, 'runscript'): continue # Read the IC file name from the script tree = et.parse(fullpath) root = tree.getroot() use_tag = root.find('use') aircraft_name = use_tag.attrib['aircraft'] aircraft_path = os.path.join('aircraft', aircraft_name) path_to_jsbsim_aircrafts = self.sandbox.elude(self.sandbox.path_to_jsbsim_file(aircraft_path)) IC_file = append_xml(use_tag.attrib['initialize']) IC_tree = et.parse(os.path.join(path_to_jsbsim_aircrafts, IC_file)) IC_root = IC_tree.getroot() # Only testing version 1.0 of init files if 'version' in IC_root.attrib: if float(IC_root.attrib['version']) == 2.0: continue # 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 not var['specified']: 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 # Generate a CSV file to check that it is correctly initialized # with the initial values output_tag = et.SubElement(root, 'output') output_tag.attrib['name'] = 'check_csv_values.csv' output_tag.attrib['type'] = 'CSV' output_tag.attrib['rate'] = '10' position_tag = et.SubElement(output_tag, 'position') position_tag.text = 'ON' velocities_tag = et.SubElement(output_tag, 'velocities') velocities_tag.text = 'ON' for props in prop_output_to_CSV: property_tag = et.SubElement(output_tag, 'property') property_tag.text = props tree.write(self.sandbox(f)) # Initialize the script fdm = CreateFDM(self.sandbox) fdm.load_script(f) fdm.run_ic() # Sanity check, we just initialized JSBSim with the ICs, the time # must be set to 0.0 self.assertEqual(fdm.get_property_value('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 value = var['value'] prop = fdm.get_property_value(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 script %s: %s should be %f but found %f" % (f, var['tag'], value, prop)) prop = fdm.get_property_value(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 script %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 script %s" % (f,)) else: raise # Copies the CSV file content in a table ref = pd.read_csv(self.sandbox('check_csv_values.csv')) # Sanity check: make sure that the time step 0.0 has been copied in # the CSV file. 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 value = var['value'] csv_value = 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 script %s: %s should be %f but found %f" % (f, var['tag'], value, csv_value)) del fdm
def testSpoolUp(self): # Check that the same results are obtained whether the N1 & N2 spool up # are specified via the legacy <bypassratio> parameter or a <function> script_path = self.sandbox.path_to_jsbsim_file('scripts', 'f16_test.xml') tree = et.parse(script_path) use_element = tree.getroot().find('use') aircraft_name = use_element.attrib['aircraft'] tree = et.parse(self.sandbox.path_to_jsbsim_file('aircraft', aircraft_name, aircraft_name+'.xml')) engine_element = tree.getroot().find('propulsion/engine') engine_name = append_xml(engine_element.attrib['file']) tree = et.parse(self.sandbox.path_to_jsbsim_file('engine', engine_name)) root = tree.getroot() self.idleN1 = float(root.find('idlen1').text) maxN1 = float(root.find('maxn1').text) self.idleN2 = float(root.find('idlen2').text) maxN2 = float(root.find('maxn2').text) BPR = float(root.find('bypassratio').text) self.N1_factor = maxN1 - self.idleN1 self.N2_factor = maxN2 - self.idleN2 self.fdm = CreateFDM(self.sandbox) self.fdm.load_script(script_path) self.fdm.run_ic() self.dt = self.fdm['simulation/dt'] self.delay = 90.0*self.dt / (BPR + 3.0); self.runScript(self.defaultSpoolUp, lambda n2Norm: self.defaultSpoolUp(n2Norm)*2.4, self.defaultSpoolUp, lambda n2Norm: self.defaultSpoolUp(n2Norm)*3.0) del self.fdm # Check N1 spool up custom function # Append a <function name="N1SpoolUp"> to the engine definition func_spoolUpDown = et.SubElement(root, 'function') func_spoolUpDown.attrib['name'] = 'N1SpoolUp' func_body = et.parse(self.sandbox.path_to_jsbsim_file('tests', 'N1SpoolUp.xml')) func_spoolUpDown.append(func_body.getroot()) tree.write(engine_name) shutil.copy(self.sandbox.path_to_jsbsim_file('engine','direct.xml'), '.') self.fdm = CreateFDM(self.sandbox) self.fdm.set_engine_path('.') self.fdm.load_script(script_path) self.fdm.run_ic() self.runScript(lambda n2Norm: self.fdm['propulsion/engine/n1']*self.dt/20.0, lambda n2Norm: self.defaultSpoolUp(n2Norm)*2.4, self.defaultSpoolUp, lambda n2Norm: self.defaultSpoolUp(n2Norm)*3.0) del self.fdm # Check N1 spool down custom function func_spoolUpDown.attrib['name'] = 'N1SpoolDown' tree.write(engine_name) self.fdm = CreateFDM(self.sandbox) self.fdm.set_engine_path('.') self.fdm.load_script(script_path) self.fdm.run_ic() self.runScript(self.defaultSpoolUp, lambda n2Norm: self.fdm['propulsion/engine/n1']*self.dt/20.0, self.defaultSpoolUp, lambda n2Norm: self.defaultSpoolUp(n2Norm)*3.0) del self.fdm # Check N2 spool up custom function func_spoolUpDown.attrib['name'] = 'N2SpoolUp' tree.write(engine_name) self.fdm = CreateFDM(self.sandbox) self.fdm.set_engine_path('.') self.fdm.load_script(script_path) self.fdm.run_ic() self.runScript(self.defaultSpoolUp, lambda n2Norm: self.defaultSpoolUp(n2Norm)*2.4, lambda n2Norm: self.fdm['propulsion/engine/n1']*self.dt/20.0, lambda n2Norm: self.defaultSpoolUp(n2Norm)*3.0) del self.fdm # Check N2 spool down custom function func_spoolUpDown.attrib['name'] = 'N2SpoolDown' tree.write(engine_name) self.fdm = CreateFDM(self.sandbox) self.fdm.set_engine_path('.') self.fdm.load_script(script_path) self.fdm.run_ic() self.runScript(self.defaultSpoolUp, lambda n2Norm: self.defaultSpoolUp(n2Norm)*2.4, self.defaultSpoolUp, lambda n2Norm: self.fdm['propulsion/engine/n1']*self.dt/20.0)