예제 #1
0
    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)
예제 #2
0
    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())
예제 #3
0
    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)
예제 #4
0
    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)
예제 #5
0
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)