def testFunctionWithIndexedProps(self): tree = et.parse(self.sandbox.path_to_jsbsim_file('engine', 'eng_PegasusXc.xml')) # Define the function starter-max-power-W as a 'post' function root = tree.getroot() startPowFunc_tag = root.find("function/[@name='propulsion/engine[#]/starter-max-power-W']") startPowFunc_tag.attrib['type']='post' tree.write('eng_PegasusXc.xml') # Copy the propeller file. shutil.copy(self.sandbox.path_to_jsbsim_file('engine', 'prop_deHavilland5000.xml'), '.') fdm = CreateFDM(self.sandbox) fdm.set_engine_path('.') fdm.load_script(self.sandbox.path_to_jsbsim_file('scripts', 'Short_S23_1.xml')) fdm.run_ic() pm = fdm.get_property_manager() self.assertTrue(pm.hasNode('propulsion/engine[0]/starter-max-power-W')) self.assertTrue(pm.hasNode('propulsion/engine[1]/starter-max-power-W')) self.assertTrue(pm.hasNode('propulsion/engine[2]/starter-max-power-W')) self.assertTrue(pm.hasNode('propulsion/engine[3]/starter-max-power-W')) while fdm.run(): rpm = [fdm['propulsion/engine[0]/engine-rpm'], fdm['propulsion/engine[1]/engine-rpm'], fdm['propulsion/engine[2]/engine-rpm'], fdm['propulsion/engine[3]/engine-rpm']] for i in range(4): maxPower = max(0.0, 1.0-rpm[i]/400)*498.941*0.10471976*rpm[i] self.assertAlmostEqual(fdm['propulsion/engine[%d]/starter-max-power-W' % (i,)], maxPower)
def testEnginePowerVC(self): # Check that the same results are obtained whether the engine power # velocity correction is given in a <table> or <function> fdm = CreateFDM(self.sandbox) fdm.load_script(self.sandbox.path_to_jsbsim_file('scripts', 'L4102.xml')) fdm.run_ic() while fdm.run(): pass del fdm ref = pd.read_csv('L410.csv', index_col=0) tree = et.parse(self.sandbox.path_to_jsbsim_file('engine', 'engtm601.xml')) # Modify the engine definition to use a <function> rather than a # <table> component. root = tree.getroot() engPowVC_tag = root.find("table/[@name='EnginePowerVC']") root.remove(engPowVC_tag) del engPowVC_tag.attrib['name'] func_engPowVC = et.SubElement(root, 'function') func_engPowVC.attrib['name'] = 'EnginePowerVC' func_engPowVC.append(engPowVC_tag) tree.write('engtm601.xml') # Copy the propeller file. shutil.copy(self.sandbox.path_to_jsbsim_file('engine', 'vrtule2.xml'), '.') self.sandbox.delete_csv_files() fdm = CreateFDM(self.sandbox) fdm.set_engine_path('.') fdm.load_script(self.sandbox.path_to_jsbsim_file('scripts', 'L4102.xml')) fdm.run_ic() while fdm.run(): pass current = pd.read_csv('L410.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-5 between the # two data sets. diff = FindDifferences(ref, current, 0.0) self.longMessage = True self.assertEqual(len(diff), 0, msg='\n'+diff.to_string())
def testTableWithIndexedVars(self): tree = et.parse( self.sandbox.path_to_jsbsim_file('engine', 'eng_PegasusXc.xml')) # Define the function starter-max-power-W as a 'post' function root = tree.getroot() startPowFunc_tag = root.find( "function/[@name='propulsion/engine[#]/starter-max-power-W']") startPowFunc_tag.attrib['type'] = 'post' max_tag = startPowFunc_tag.find('product/max') diff_tag = max_tag.find('difference') max_tag.remove(diff_tag) table_tag = et.SubElement(max_tag, 'table') table_tag.attrib['name'] = 'propulsion/engine[#]/starter-tabular-data' indepVar_tag = et.SubElement(table_tag, 'independentVar') indepVar_tag.attrib['lookup'] = 'row' indepVar_tag.text = 'propulsion/engine[#]/engine-rpm' tData_tag = et.SubElement(table_tag, 'tableData') tData_tag.text = '0.0 1.0\n400.0 0.0' tree.write('eng_PegasusXc.xml') # Copy the propeller file. shutil.copy( self.sandbox.path_to_jsbsim_file('engine', 'prop_deHavilland5000.xml'), '.') fdm = CreateFDM(self.sandbox) fdm.set_engine_path('.') fdm.load_script( self.sandbox.path_to_jsbsim_file('scripts', 'Short_S23_1.xml')) fdm.run_ic() pm = fdm.get_property_manager() self.assertTrue(pm.hasNode('propulsion/engine[0]/starter-max-power-W')) self.assertTrue(pm.hasNode('propulsion/engine[1]/starter-max-power-W')) self.assertTrue(pm.hasNode('propulsion/engine[2]/starter-max-power-W')) self.assertTrue(pm.hasNode('propulsion/engine[3]/starter-max-power-W')) while fdm.run(): rpm = [ fdm['propulsion/engine[0]/engine-rpm'], fdm['propulsion/engine[1]/engine-rpm'], fdm['propulsion/engine[2]/engine-rpm'], fdm['propulsion/engine[3]/engine-rpm'] ] for i in xrange(4): tabularData = max(0.0, 1.0 - rpm[i] / 400) maxPower = tabularData * 498.941 * 0.10471976 * rpm[i] self.assertAlmostEqual( fdm['propulsion/engine[%d]/starter-max-power-W' % (i, )], maxPower) self.assertAlmostEqual( fdm['propulsion/engine[%d]/starter-tabular-data' % (i, )], tabularData)
def testTableWithIndexedVars(self): tree = et.parse(self.sandbox.path_to_jsbsim_file('engine', 'eng_PegasusXc.xml')) # Define the function starter-max-power-W as a 'post' function root = tree.getroot() startPowFunc_tag = root.find("function/[@name='propulsion/engine[#]/starter-max-power-W']") startPowFunc_tag.attrib['type']='post' max_tag = startPowFunc_tag.find('product/max') diff_tag = max_tag.find('difference') max_tag.remove(diff_tag) table_tag = et.SubElement(max_tag,'table') table_tag.attrib['name']='propulsion/engine[#]/starter-tabular-data' indepVar_tag = et.SubElement(table_tag, 'independentVar') indepVar_tag.attrib['lookup']='row' indepVar_tag.text = 'propulsion/engine[#]/engine-rpm' tData_tag = et.SubElement(table_tag, 'tableData') tData_tag.text ='0.0 1.0\n400.0 0.0' tree.write('eng_PegasusXc.xml') # Copy the propeller file. shutil.copy(self.sandbox.path_to_jsbsim_file('engine', 'prop_deHavilland5000.xml'), '.') fdm = CreateFDM(self.sandbox) fdm.set_engine_path('.') fdm.load_script(self.sandbox.path_to_jsbsim_file('scripts', 'Short_S23_1.xml')) fdm.run_ic() pm = fdm.get_property_manager() self.assertTrue(pm.hasNode('propulsion/engine[0]/starter-max-power-W')) self.assertTrue(pm.hasNode('propulsion/engine[1]/starter-max-power-W')) self.assertTrue(pm.hasNode('propulsion/engine[2]/starter-max-power-W')) self.assertTrue(pm.hasNode('propulsion/engine[3]/starter-max-power-W')) while fdm.run(): rpm = [fdm['propulsion/engine[0]/engine-rpm'], fdm['propulsion/engine[1]/engine-rpm'], fdm['propulsion/engine[2]/engine-rpm'], fdm['propulsion/engine[3]/engine-rpm']] for i in range(4): tabularData = max(0.0, 1.0-rpm[i]/400) maxPower = tabularData*498.941*0.10471976*rpm[i] self.assertAlmostEqual(fdm['propulsion/engine[%d]/starter-max-power-W' % (i,)], maxPower) self.assertAlmostEqual(fdm['propulsion/engine[%d]/starter-tabular-data' % (i,)], tabularData)
class TestTurbine(JSBSimTestCase): def defaultSpoolUp(self, N2norm): sigma = self.fdm['atmosphere/sigma'] n = min(1.0, N2norm + 0.1) return self.delay / (1 + 3 * (1-n)*(1-n)*(1-n) + (1 - sigma)) def runScript(self, n1SpoolUp, n1SpoolDown, n2SpoolUp, n2SpoolDown): while self.fdm.run(): n1 = self.fdm['propulsion/engine/n1'] n2 = self.fdm['propulsion/engine/n2'] N2norm = (n2-self.idleN2)/self.N2_factor; if n2 >= 100.: # Trigger the engine spool down self.fdm['fcs/throttle-cmd-norm'] = 0.0 if N2norm > 0.0: self.assertAlmostEqual(n1, newN1) self.assertAlmostEqual(n2, newN2) if n2 > 15.0: sigma = self.fdm['atmosphere/sigma'] n = min(1.0, N2norm + 0.1) spoolup = self.delay / (1 + 3 * (1-n)*(1-n)*(1-n) + (1 - sigma)) throttlePos = self.fdm['fcs/throttle-cmd-norm'] targetN1 = self.idleN1+throttlePos*self.N1_factor targetN2 = self.idleN2+throttlePos*self.N2_factor newN1 = seek(n1, targetN1, n1SpoolUp(N2norm), n1SpoolDown(N2norm)) newN2 = seek(n2, targetN2, n2SpoolUp(N2norm), n2SpoolDown(N2norm)) if N2norm == 0.0 and self.fdm['fcs/throttle-cmd-norm'] == 0.0: break 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)