Example #1
0
    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))
Example #2
0
    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)
Example #3
0
    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))
Example #4
0
    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)
Example #5
0
    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))
Example #6
0
    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)
Example #7
0
    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)
Example #8
0
    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)
Example #9
0
    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
Example #10
0
    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
Example #11
0
    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))
Example #12
0
    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)
Example #13
0
    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)
Example #14
0
    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
Example #15
0
    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
Example #16
0
    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)