예제 #1
0
    def test_pitot_angle(self):
        script_name = 'ball_chute.xml'
        script_path = self.sandbox.path_to_jsbsim_file('scripts', script_name)

        # Add a Pitot angle to the Cessna 172
        tree, aircraft_name, path_to_jsbsim_aircrafts = CopyAircraftDef(
            script_path, self.sandbox)
        root = tree.getroot()
        pitot_angle_deg = 5.0
        self.addPitotTube(root, 5.0)
        contact_tag = root.find('./ground_reactions/contact')
        contact_tag.attrib['type'] = 'STRUCTURE'
        tree.write(
            self.sandbox('aircraft', aircraft_name, aircraft_name + '.xml'))

        fdm = CreateFDM(self.sandbox)
        fdm.set_aircraft_path('aircraft')
        fdm.load_model('ball')
        pitot_angle = pitot_angle_deg * math.pi / 180.
        weight = fdm['inertia/weight-lbs']
        spring_tag = contact_tag.find('./spring_coeff')
        spring_coeff = float(spring_tag.text)
        print("Weight=%d Spring=%d" % (weight, spring_coeff))
        fdm['ic/h-sl-ft'] = weight / spring_coeff
        fdm['forces/hold-down'] = 1.0
        fdm.run_ic()

        ExecuteUntil(fdm, 10.)

        for i in range(36):
            for j in range(-9, 10):
                angle = math.pi * i / 18.0
                angle2 = math.pi * j / 18.0
                ca2 = math.cos(angle2)
                fdm['atmosphere/wind-north-fps'] = 10. * math.cos(angle) * ca2
                fdm['atmosphere/wind-east-fps'] = 10. * math.sin(angle) * ca2
                fdm['atmosphere/wind-down-fps'] = 10. * math.sin(angle2)
                fdm.run()

                vg = fdm['velocities/vg-fps']
                self.assertAlmostEqual(vg, 0.0, delta=1E-7)

                vt = fdm['velocities/vt-fps']
                self.assertAlmostEqual(vt, 10., delta=1E-7)

                mach = vt / fdm['atmosphere/a-fps']
                P = fdm['atmosphere/P-psf']
                pt = P * math.pow(1 + 0.2 * mach * mach, 3.5)
                psl = fdm['atmosphere/P-sl-psf']
                rhosl = fdm['atmosphere/rho-sl-slugs_ft3']
                A = math.pow((pt - P) / psl + 1.0, 1.0 / 3.5)
                alpha = fdm['aero/alpha-rad']
                beta = fdm['aero/beta-rad']
                vc = math.sqrt(
                    7.0 * psl / rhosl *
                    (A - 1.0)) * math.cos(alpha + pitot_angle) * math.cos(beta)

                self.assertAlmostEqual(fdm['velocities/vc-kts'],
                                       max(0.0, vc) / 1.68781,
                                       delta=1E-7)
예제 #2
0
    def test_hold_down_with_gnd_reactions(self):
        fdm = CreateFDM(self.sandbox)
        fdm.load_script(self.sandbox.path_to_jsbsim_file('scripts',
                                                         'c1721.xml'))
        fdm.run_ic()
        ExecuteUntil(fdm, 0.25)

        fdm['forces/hold-down'] = 1.0
        h0 = fdm['position/h-sl-ft']
        pitch = fdm['attitude/pitch-rad']
        roll = fdm['attitude/roll-rad']
        heading = fdm['attitude/heading-true-rad']

        while fdm['simulation/sim-time-sec'] < 2.0:
            fdm.run()
            self.assertAlmostEqual(fdm['accelerations/pdot-rad_sec2'], 0.0)
            self.assertAlmostEqual(fdm['accelerations/qdot-rad_sec2'], 0.0)
            self.assertAlmostEqual(fdm['accelerations/rdot-rad_sec2'], 0.0)
            self.assertAlmostEqual(fdm['accelerations/udot-ft_sec2'], 0.0)
            self.assertAlmostEqual(fdm['accelerations/vdot-ft_sec2'], 0.0)
            self.assertAlmostEqual(fdm['accelerations/wdot-ft_sec2'], 0.0)

        self.assertAlmostEqual(fdm['position/h-sl-ft'], h0, delta=1E-6)
        self.assertAlmostEqual(fdm['attitude/pitch-rad'], pitch)
        self.assertAlmostEqual(fdm['attitude/roll-rad'], roll)
        self.assertAlmostEqual(fdm['attitude/heading-true-rad'], heading)
예제 #3
0
    def test_direct_steer(self):
        fdm = CreateFDM(self.sandbox)
        fdm.load_model('c172r')
        aircraft_path = self.sandbox.path_to_jsbsim_file('aircraft')
        fdm.load_ic(os.path.join(aircraft_path, 'c172r', 'reset00'), False)
        fdm.run_ic()
        self.assertAlmostEqual(fdm['fcs/steer-cmd-norm'], 0.0)
        self.assertAlmostEqual(fdm['fcs/steer-pos-deg'], 0.0)

        # Should be part of a unit test in C++ ?
        fpectl.turnon_sigfpe()

        grndreact = fdm.get_ground_reactions()
        for i in xrange(grndreact.get_num_gear_units()):
            gear = grndreact.get_gear_unit(i)
            self.assertEqual(gear.get_steer_norm(), 0.0)

        fpectl.turnoff_sigfpe()

        fdm['fcs/steer-pos-deg'] = 5.0
        self.assertAlmostEqual(fdm['fcs/steer-pos-deg'], 5.0)
        fdm.run()
        self.assertAlmostEqual(fdm['fcs/steer-cmd-norm'], 0.0)
        fdm['fcs/steer-cmd-norm'] = 1.0
        self.assertAlmostEqual(fdm['fcs/steer-cmd-norm'], 1.0)
        fdm.run()
        self.assertAlmostEqual(fdm['fcs/steer-cmd-norm'], 1.0)
        self.assertAlmostEqual(fdm['fcs/steer-pos-deg'], 10.0)
예제 #4
0
    def test_hold_down_with_gnd_reactions(self):
        fdm = CreateFDM(self.sandbox)
        fdm.load_script(
            self.sandbox.path_to_jsbsim_file('scripts', 'c1721.xml'))
        fdm.run_ic()
        ExecuteUntil(fdm, 0.25)

        fdm['forces/hold-down'] = 1.0
        h0 = fdm['position/h-sl-ft']
        pitch = fdm['attitude/pitch-rad']
        roll = fdm['attitude/roll-rad']
        heading = fdm['attitude/heading-true-rad']

        while fdm['simulation/sim-time-sec'] < 2.0:
            fdm.run()
            self.assertAlmostEqual(fdm['accelerations/pdot-rad_sec2'], 0.0)
            self.assertAlmostEqual(fdm['accelerations/qdot-rad_sec2'], 0.0)
            self.assertAlmostEqual(fdm['accelerations/rdot-rad_sec2'], 0.0)
            self.assertAlmostEqual(fdm['accelerations/udot-ft_sec2'], 0.0)
            self.assertAlmostEqual(fdm['accelerations/vdot-ft_sec2'], 0.0)
            self.assertAlmostEqual(fdm['accelerations/wdot-ft_sec2'], 0.0)

        self.assertAlmostEqual(fdm['position/h-sl-ft'], h0, delta=1E-6)
        self.assertAlmostEqual(fdm['attitude/pitch-rad'], pitch)
        self.assertAlmostEqual(fdm['attitude/roll-rad'], roll)
        self.assertAlmostEqual(fdm['attitude/heading-true-rad'], heading)
예제 #5
0
    def test_direct_steer(self):
        fdm = CreateFDM(self.sandbox)
        fdm.load_model('c172r')
        aircraft_path = self.sandbox.path_to_jsbsim_file('aircraft')
        fdm.load_ic(os.path.join(aircraft_path, 'c172r', 'reset00'), False)
        fdm.run_ic()
        self.assertAlmostEqual(fdm['fcs/steer-cmd-norm'], 0.0)
        self.assertAlmostEqual(fdm['fcs/steer-pos-deg'], 0.0)

        # Should be part of a unit test in C++ ?
        fpectl.turnon_sigfpe()

        grndreact = fdm.get_ground_reactions()
        for i in xrange(grndreact.get_num_gear_units()):
            gear = grndreact.get_gear_unit(i)
            self.assertEqual(gear.get_steer_norm(), 0.0)

        fpectl.turnoff_sigfpe()

        fdm['fcs/steer-pos-deg'] = 5.0
        self.assertAlmostEqual(fdm['fcs/steer-pos-deg'], 5.0)
        fdm.run()
        self.assertAlmostEqual(fdm['fcs/steer-cmd-norm'], 0.0)
        fdm['fcs/steer-cmd-norm'] = 1.0
        self.assertAlmostEqual(fdm['fcs/steer-cmd-norm'], 1.0)
        fdm.run()
        self.assertAlmostEqual(fdm['fcs/steer-cmd-norm'], 1.0)
        self.assertAlmostEqual(fdm['fcs/steer-pos-deg'], 10.0)
예제 #6
0
    def test_pitot_angle(self):
        script_name = 'ball_chute.xml'
        script_path = self.sandbox.path_to_jsbsim_file('scripts', script_name)

        # Add a Pitot angle to the Cessna 172
        tree, aircraft_name, path_to_jsbsim_aircrafts = CopyAircraftDef(script_path, self.sandbox)
        root = tree.getroot()
        pitot_angle_deg = 5.0
        self.addPitotTube(root, 5.0)
        contact_tag = root.find('./ground_reactions/contact')
        contact_tag.attrib['type'] = 'STRUCTURE'
        tree.write(self.sandbox('aircraft', aircraft_name,
                                aircraft_name+'.xml'))

        fdm = CreateFDM(self.sandbox)
        fdm.set_aircraft_path('aircraft')
        fdm.load_model('ball')
        pitot_angle = pitot_angle_deg * math.pi / 180.
        weight = fdm['inertia/weight-lbs']
        spring_tag = contact_tag.find('./spring_coeff')
        spring_coeff = float(spring_tag.text)
        print "Weight=%d Spring=%d" % (weight, spring_coeff)
        fdm['ic/h-sl-ft'] = weight / spring_coeff
        fdm['forces/hold-down'] = 1.0
        fdm.run_ic()

        ExecuteUntil(fdm, 10.)

        for i in xrange(36):
            for j in xrange(-9, 10):
                angle = math.pi * i / 18.0
                angle2 = math.pi * j / 18.0
                ca2 = math.cos(angle2)
                fdm['atmosphere/wind-north-fps'] = 10. * math.cos(angle) * ca2
                fdm['atmosphere/wind-east-fps'] = 10. * math.sin(angle) * ca2
                fdm['atmosphere/wind-down-fps'] = 10. * math.sin(angle2)
                fdm.run()

                vg = fdm['velocities/vg-fps']
                self.assertAlmostEqual(vg, 0.0, delta=1E-7)

                vt = fdm['velocities/vt-fps']
                self.assertAlmostEqual(vt, 10., delta=1E-7)

                mach = vt / fdm['atmosphere/a-fps']
                P = fdm['atmosphere/P-psf']
                pt = P * math.pow(1+0.2*mach*mach, 3.5)
                psl = fdm['atmosphere/P-sl-psf']
                rhosl = fdm['atmosphere/rho-sl-slugs_ft3']
                A = math.pow((pt-P)/psl+1.0, 1.0/3.5)
                alpha = fdm['aero/alpha-rad']
                beta = fdm['aero/beta-rad']
                vc = math.sqrt(7.0*psl/rhosl*(A-1.0))*math.cos(alpha+pitot_angle)*math.cos(beta)

                self.assertAlmostEqual(fdm['velocities/vc-kts'],
                                       max(0.0, vc) / 1.68781, delta=1E-7)
예제 #7
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())
예제 #8
0
    def testKinematicSetInitialValue(self):
        fdm = CreateFDM(self.sandbox)
        fdm.load_model('p51d')
        fdm.load_ic('reset01', True)
        fdm.run_ic()

        fdm['gear/gear-cmd-norm'] = 0.5
        fdm['gear/gear-pos-norm'] = 0.5

        while fdm['simulation/sim-time-sec'] < 1.0:
            fdm.run()
            self.assertAlmostEqual(fdm['gear/gear-cmd-norm'], 0.5)
            self.assertAlmostEqual(fdm['gear/gear-pos-norm'], 0.5)
예제 #9
0
    def test_static_hold_down(self):
        fdm = CreateFDM(self.sandbox)
        fdm.load_model('J246')
        aircraft_path = self.sandbox.path_to_jsbsim_file('aircraft')
        fdm.load_ic(os.path.join(aircraft_path, 'J246', 'LC39'), False)
        fdm['forces/hold-down'] = 1.0
        fdm.run_ic()
        h0 = fdm['position/h-sl-ft']
        t = 0.0

        while t < 420.0:
            fdm.run()
            t = fdm['simulation/sim-time-sec']
            self.assertAlmostEqual(fdm['position/h-sl-ft'], h0, delta=1E-5)
예제 #10
0
    def test_static_hold_down(self):
        fdm = CreateFDM(self.sandbox)
        fdm.load_model('J246')
        aircraft_path = self.sandbox.path_to_jsbsim_file('aircraft')
        fdm.load_ic(os.path.join(aircraft_path, 'J246', 'LC39'), False)
        fdm['forces/hold-down'] = 1.0
        fdm.run_ic()
        h0 = fdm['position/h-sl-ft']
        t = 0.0

        while t < 420.0:
            fdm.run()
            t = fdm['simulation/sim-time-sec']
            self.assertAlmostEqual(fdm['position/h-sl-ft'], h0, delta=1E-5)
예제 #11
0
    def testKinematicSetInitialValue(self):
        fdm = CreateFDM(self.sandbox)
        fdm.load_model('p51d')
        fdm.load_ic(self.sandbox.path_to_jsbsim_file('aircraft', 'p51d',
                                                     'reset01'), False)
        fdm.run_ic()

        fdm['gear/gear-cmd-norm'] = 0.5
        fdm['gear/gear-pos-norm'] = 0.5

        while fdm['simulation/sim-time-sec'] < 1.0:
            fdm.run()
            self.assertAlmostEqual(fdm['gear/gear-cmd-norm'], 0.5)
            self.assertAlmostEqual(fdm['gear/gear-pos-norm'], 0.5)
예제 #12
0
 def test_steer_with_fcs(self):
     fdm = CreateFDM(self.sandbox)
     fdm.load_model('L410')
     aircraft_path = self.sandbox.path_to_jsbsim_file('aircraft')
     fdm.load_ic(os.path.join(aircraft_path, 'L410', 'reset00'), False)
     fdm.run_ic()
     self.assertAlmostEqual(fdm['fcs/steer-cmd-norm'], 0.0)
     self.assertAlmostEqual(fdm['fcs/steer-pos-deg'], 0.0)
     fdm['fcs/steer-cmd-norm'] = 1.0
     self.assertAlmostEqual(fdm['fcs/steer-cmd-norm'], 1.0)
     fdm.run()
     self.assertAlmostEqual(fdm['fcs/steer-cmd-norm'], 1.0)
     self.assertAlmostEqual(fdm['fcs/steer-pos-deg'], 5.0)
     fdm['/controls/switches/full-steering-sw'] = 1.0
     fdm.run()
     self.assertAlmostEqual(fdm['fcs/steer-cmd-norm'], 1.0)
     self.assertAlmostEqual(fdm['fcs/steer-pos-deg'], 0.0)
     fdm['/controls/switches/full-steering-sw'] = 2.0
     fdm.run()
     self.assertAlmostEqual(fdm['fcs/steer-cmd-norm'], 1.0)
     self.assertAlmostEqual(fdm['fcs/steer-pos-deg'], 45.0)
     fdm['fcs/steer-cmd-norm'] = -0.5
     fdm.run()
     self.assertAlmostEqual(fdm['fcs/steer-cmd-norm'], -0.5)
     self.assertAlmostEqual(fdm['fcs/steer-pos-deg'], -22.5)
예제 #13
0
 def test_steer_with_fcs(self):
     fdm = CreateFDM(self.sandbox)
     fdm.load_model('L410')
     aircraft_path = self.sandbox.path_to_jsbsim_file('aircraft')
     fdm.load_ic(os.path.join(aircraft_path, 'L410', 'reset00'), False)
     fdm.run_ic()
     self.assertAlmostEqual(fdm['fcs/steer-cmd-norm'], 0.0)
     self.assertAlmostEqual(fdm['fcs/steer-pos-deg'], 0.0)
     fdm['fcs/steer-cmd-norm'] = 1.0
     self.assertAlmostEqual(fdm['fcs/steer-cmd-norm'], 1.0)
     fdm.run()
     self.assertAlmostEqual(fdm['fcs/steer-cmd-norm'], 1.0)
     self.assertAlmostEqual(fdm['fcs/steer-pos-deg'], 5.0)
     fdm['/controls/switches/full-steering-sw'] = 1.0
     fdm.run()
     self.assertAlmostEqual(fdm['fcs/steer-cmd-norm'], 1.0)
     self.assertAlmostEqual(fdm['fcs/steer-pos-deg'], 0.0)
     fdm['/controls/switches/full-steering-sw'] = 2.0
     fdm.run()
     self.assertAlmostEqual(fdm['fcs/steer-cmd-norm'], 1.0)
     self.assertAlmostEqual(fdm['fcs/steer-pos-deg'], 45.0)
     fdm['fcs/steer-cmd-norm'] = -0.5
     fdm.run()
     self.assertAlmostEqual(fdm['fcs/steer-cmd-norm'], -0.5)
     self.assertAlmostEqual(fdm['fcs/steer-pos-deg'], -22.5)
예제 #14
0
    def testKinematicSetInitialValue(self):
        fdm = CreateFDM(self.sandbox)
        fdm.load_model('p51d')
        fdm.load_ic(
            self.sandbox.path_to_jsbsim_file('aircraft', 'p51d', 'reset01'),
            False)
        fdm.run_ic()

        fdm['gear/gear-cmd-norm'] = 0.5
        fdm['gear/gear-pos-norm'] = 0.5

        while fdm['simulation/sim-time-sec'] < 1.0:
            fdm.run()
            self.assertAlmostEqual(fdm['gear/gear-cmd-norm'], 0.5)
            self.assertAlmostEqual(fdm['gear/gear-pos-norm'], 0.5)
예제 #15
0
    def test_static_hold_down(self):
        fdm = CreateFDM(self.sandbox)
        fdm.load_model('J246')
        fdm.load_ic('LC39', True)
        fdm['forces/hold-down'] = 1.0
        fdm.run_ic()
        h0 = fdm['position/vrp-radius-ft']
        t = 0.0

        while t < 420.0:
            fdm.run()
            t = fdm['simulation/sim-time-sec']
            self.assertAlmostEqual(fdm['position/vrp-radius-ft'] / h0,
                                   1.0,
                                   delta=1E-9)
예제 #16
0
    def testSteadyFlight(self):
        script_name = 'c1722.xml'
        script_path = self.sandbox.path_to_jsbsim_file('scripts', script_name)
        self.AddAccelerometersToAircraft(script_path)

        fdm = CreateFDM(self.sandbox)
        fdm.set_aircraft_path('aircraft')
        fdm.load_script(script_path)
        # Switch the accel on
        fdm.set_property_value('fcs/accelerometer/on', 1.0)
        # Use the standard gravity (i.e. GM/r^2)
        fdm.set_property_value('simulation/gravity-model', 0)
        # Simplifies the transformation to compare the accelerometer with the
        # gravity
        fdm.set_property_value('ic/psi-true-rad', 0.0)
        fdm.run_ic()

        while fdm.get_property_value('simulation/sim-time-sec') <= 0.5:
            fdm.run()

        fdm.set_property_value('simulation/do_simple_trim', 1)
        ax = fdm.get_property_value('accelerations/udot-ft_sec2')
        ay = fdm.get_property_value('accelerations/vdot-ft_sec2')
        az = fdm.get_property_value('accelerations/wdot-ft_sec2')
        g = fdm.get_property_value('accelerations/gravity-ft_sec2')
        theta = fdm.get_property_value('attitude/theta-rad')

        # There is a lag of one time step between the computations of the
        # accelerations and the update of the accelerometer
        fdm.run()
        fax = fdm.get_property_value('fcs/accelerometer/X')
        fay = fdm.get_property_value('fcs/accelerometer/Y')
        faz = fdm.get_property_value('fcs/accelerometer/Z')

        fax -= ax
        fay -= ay
        faz -= az

        # Deltas are relaxed because the tolerances of the trimming algorithm
        # are quite relaxed themselves.
        self.assertAlmostEqual(faz / (g * math.cos(theta)), -1.0, delta=1E-5)
        self.assertAlmostEqual(fax / (g * math.sin(theta)), 1.0, delta=1E-5)
        self.assertAlmostEqual(math.sqrt(fax * fax + fay * fay + faz * faz) /
                               g,
                               1.0,
                               delta=1E-6)

        del fdm
예제 #17
0
    def testOrbit(self):
        script_name = 'ball_orbit.xml'
        script_path = self.sandbox.path_to_jsbsim_file('scripts', script_name)
        self.AddAccelerometersToAircraft(script_path)

        # The time step is too small in ball_orbit so let's increase it to 0.1s
        # for a quicker run
        tree = et.parse(script_path)
        run_tag = tree.getroot().find('./run')
        run_tag.attrib['dt'] = '0.1'
        tree.write(script_name)

        fdm = CreateFDM(self.sandbox)
        fdm.set_aircraft_path('aircraft')
        fdm.load_script(script_name)
        # Switch the accel on
        fdm['fcs/accelerometer/on'] = 1.0
        fdm.run_ic()

        while fdm.run():
            self.assertAlmostEqual(fdm['fcs/accelerometer/X'], 0.0, delta=1E-8)
            self.assertAlmostEqual(fdm['fcs/accelerometer/Y'], 0.0, delta=1E-8)
            self.assertAlmostEqual(fdm['fcs/accelerometer/Z'], 0.0, delta=1E-8)
            self.assertAlmostEqual(fdm['accelerations/a-pilot-x-ft_sec2'], 0.0,
                                   delta=1E-8)
            self.assertAlmostEqual(fdm['accelerations/a-pilot-y-ft_sec2'], 0.0,
                                   delta=1E-8)
            self.assertAlmostEqual(fdm['accelerations/a-pilot-z-ft_sec2'], 0.0,
                                   delta=1E-8)

        del fdm
예제 #18
0
    def test_wind_frame(self):
        script_path = self.sandbox.path_to_jsbsim_file('scripts',
                                                       'ball_chute.xml')
        fdm = CreateFDM(self.sandbox)

        fdm.load_script(script_path)
        fdm.run_ic()

        self.assertAlmostEqual(fdm['external_reactions/parachute/location-x-in'],
                               12.0)
        self.assertAlmostEqual(fdm['external_reactions/parachute/location-y-in'],
                               0.0)
        self.assertAlmostEqual(fdm['external_reactions/parachute/location-z-in'],
                               0.0)
        self.assertAlmostEqual(fdm['external_reactions/parachute/x'], -1.0)
        self.assertAlmostEqual(fdm['external_reactions/parachute/y'], 0.0)
        self.assertAlmostEqual(fdm['external_reactions/parachute/z'], 0.0)

        while fdm.run():
            Tw2b = fdm.get_auxiliary().get_Tw2b()
            mag = fdm['aero/qbar-psf'] * fdm['fcs/parachute_reef_pos_norm']*20.0
            f = Tw2b * np.mat([-1.0, 0.0, 0.0]).T * mag
            self.assertAlmostEqual(fdm['forces/fbx-external-lbs'], f[0, 0])
            self.assertAlmostEqual(fdm['forces/fby-external-lbs'], f[1, 0])
            self.assertAlmostEqual(fdm['forces/fbz-external-lbs'], f[2, 0])

            m = np.cross(self.getLeverArm(fdm,'parachute'),
                         np.array([f[0,0], f[1,0], f[2, 0]]))
            self.assertAlmostEqual(fdm['moments/l-external-lbsft'], m[0])
            self.assertAlmostEqual(fdm['moments/m-external-lbsft'], m[1])
            self.assertAlmostEqual(fdm['moments/n-external-lbsft'], m[2])
예제 #19
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)
예제 #20
0
    def testOrbit(self):
        script_name = 'ball_orbit.xml'
        script_path = self.sandbox.path_to_jsbsim_file('scripts', script_name)
        self.AddAccelerometersToAircraft(script_path)

        # The time step is too small in ball_orbit so let's increase it to 0.1s
        # for a quicker run
        tree = et.parse(script_path)
        run_tag = tree.getroot().find('./run')
        run_tag.attrib['dt'] = '0.1'
        tree.write(script_name)

        fdm = CreateFDM(self.sandbox)
        fdm.set_aircraft_path('aircraft')
        fdm.load_script(script_name)
        # Switch the accel on
        fdm['fcs/accelerometer/on'] = 1.0
        fdm.run_ic()

        while fdm.run():
            self.assertAlmostEqual(fdm['fcs/accelerometer/X'], 0.0, delta=1E-8)
            self.assertAlmostEqual(fdm['fcs/accelerometer/Y'], 0.0, delta=1E-8)
            self.assertAlmostEqual(fdm['fcs/accelerometer/Z'], 0.0, delta=1E-8)
            self.assertAlmostEqual(fdm['accelerations/a-pilot-x-ft_sec2'],
                                   0.0,
                                   delta=1E-8)
            self.assertAlmostEqual(fdm['accelerations/a-pilot-y-ft_sec2'],
                                   0.0,
                                   delta=1E-8)
            self.assertAlmostEqual(fdm['accelerations/a-pilot-z-ft_sec2'],
                                   0.0,
                                   delta=1E-8)

        del fdm
예제 #21
0
    def test_wind_frame(self):
        script_path = self.sandbox.path_to_jsbsim_file('scripts',
                                                       'ball_chute.xml')
        fdm = CreateFDM(self.sandbox)

        fdm.load_script(script_path)
        fdm.run_ic()

        self.assertAlmostEqual(
            fdm['external_reactions/parachute/location-x-in'], 12.0)
        self.assertAlmostEqual(
            fdm['external_reactions/parachute/location-y-in'], 0.0)
        self.assertAlmostEqual(
            fdm['external_reactions/parachute/location-z-in'], 0.0)
        self.assertAlmostEqual(fdm['external_reactions/parachute/x'], -1.0)
        self.assertAlmostEqual(fdm['external_reactions/parachute/y'], 0.0)
        self.assertAlmostEqual(fdm['external_reactions/parachute/z'], 0.0)

        while fdm.run():
            Tw2b = fdm.get_auxiliary().get_Tw2b()
            mag = fdm['aero/qbar-psf'] * fdm[
                'fcs/parachute_reef_pos_norm'] * 20.0
            f = Tw2b * np.mat([-1.0, 0.0, 0.0]).T * mag
            self.assertAlmostEqual(fdm['forces/fbx-external-lbs'], f[0, 0])
            self.assertAlmostEqual(fdm['forces/fby-external-lbs'], f[1, 0])
            self.assertAlmostEqual(fdm['forces/fbz-external-lbs'], f[2, 0])

            m = np.cross(self.getLeverArm(fdm, 'parachute'),
                         np.array([f[0, 0], f[1, 0], f[2, 0]]))
            self.assertAlmostEqual(fdm['moments/l-external-lbsft'], m[0])
            self.assertAlmostEqual(fdm['moments/m-external-lbsft'], m[1])
            self.assertAlmostEqual(fdm['moments/n-external-lbsft'], m[2])
예제 #22
0
def SubProcessScriptExecution(sandbox, script_path):
    fdm = CreateFDM(sandbox)
    fdm.load_script(script_path)
    fdm.run_ic()

    while fdm.run():
        pass
예제 #23
0
 def test_direct_steer(self):
     fdm = CreateFDM(self.sandbox)
     fdm.load_model('c172r')
     aircraft_path = self.sandbox.path_to_jsbsim_file('aircraft')
     fdm.load_ic(os.path.join(aircraft_path, 'c172r', 'reset00'), False)
     fdm.run_ic()
     self.assertAlmostEqual(fdm['fcs/steer-cmd-norm'], 0.0)
     self.assertAlmostEqual(fdm['fcs/steer-pos-deg'], 0.0)
     fdm['fcs/steer-pos-deg'] = 5.0
     self.assertAlmostEqual(fdm['fcs/steer-pos-deg'], 5.0)
     fdm.run()
     self.assertAlmostEqual(fdm['fcs/steer-cmd-norm'], 0.0)
     fdm['fcs/steer-cmd-norm'] = 1.0
     self.assertAlmostEqual(fdm['fcs/steer-cmd-norm'], 1.0)
     fdm.run()
     self.assertAlmostEqual(fdm['fcs/steer-cmd-norm'], 1.0)
     self.assertAlmostEqual(fdm['fcs/steer-pos-deg'], 10.0)
예제 #24
0
    def test_moments_update(self):
        script_path = self.sandbox.path_to_jsbsim_file('scripts', 'weather-balloon.xml')
        fdm = CreateFDM(self.sandbox)

        fdm.load_script(script_path)
        fdm.run_ic()

        # Moves the radio sonde to modify the CG location
        fdm.set_property_value('inertia/pointmass-location-X-inches', 5.0)

        # Check that the moment is immediately updated accordingly
        fdm.run()
        Fbz = fdm.get_property_value('forces/fbz-buoyancy-lbs')
        CGx = fdm.get_property_value('inertia/cg-x-in') / 12.0 # Converts from in to ft
        Mby = fdm.get_property_value('moments/m-buoyancy-lbsft')
        self.assertTrue(abs(Fbz * CGx + Mby) < 1E-7,
                        msg="Fbz*CGx = %f and Mby = %f do not match" % (-Fbz*CGx, Mby))
예제 #25
0
    def testMagnitude(self):
        fdm = CreateFDM(self.sandbox)
        fdm.load_script(
            self.sandbox.path_to_jsbsim_file('scripts', 'c172_cruise_8K.xml'))

        fdm.run_ic()
        t = 0.0

        startup_duration = 5.0
        steady_duration = 1.0
        end_duration = 5.0
        start_time = 10.0
        magnitude = 30.0

        end_time = start_time + startup_duration + steady_duration + end_duration

        while fdm['simulation/run_id'] == 0:
            fdm.run()
            wn = fdm['atmosphere/total-wind-north-fps']
            we = fdm['atmosphere/total-wind-east-fps']
            wd = fdm['atmosphere/total-wind-down-fps']

            if t >= start_time and t <= end_time:
                wmag = math.sqrt(wn * wn + we * we + wd * wd)
                t -= start_time
                if t <= startup_duration:
                    self.assertAlmostEqual(
                        0.5 * magnitude *
                        (1.0 - math.cos(math.pi * t / startup_duration)),
                        wmag,
                        delta=1E-3)
                else:
                    t -= startup_duration
                    if t <= steady_duration:
                        self.assertAlmostEqual(magnitude, wmag, delta=1E-8)
                    else:
                        t -= steady_duration
                        if t <= end_duration:
                            self.assertAlmostEqual(
                                0.5 * magnitude *
                                (1.0 + math.cos(math.pi * t / end_duration)),
                                wmag,
                                delta=1E-3)

            t = fdm['simulation/sim-time-sec']
예제 #26
0
    def testSteadyFlight(self):
        script_name = 'c1722.xml'
        script_path = self.sandbox.path_to_jsbsim_file('scripts', script_name)
        self.AddAccelerometersToAircraft(script_path)

        fdm = CreateFDM(self.sandbox)
        fdm.set_aircraft_path('aircraft')
        fdm.load_script(script_path)
        # Switch the accel on
        fdm.set_property_value('fcs/accelerometer/on', 1.0)
        # Use the standard gravity (i.e. GM/r^2)
        fdm.set_property_value('simulation/gravity-model', 0)
        # Simplifies the transformation to compare the accelerometer with the
        # gravity
        fdm.set_property_value('ic/psi-true-rad', 0.0)
        fdm.run_ic()

        while fdm.get_property_value('simulation/sim-time-sec') <= 0.5:
            fdm.run()

        fdm.set_property_value('simulation/do_simple_trim', 1)
        ax = fdm.get_property_value('accelerations/udot-ft_sec2')
        ay = fdm.get_property_value('accelerations/vdot-ft_sec2')
        az = fdm.get_property_value('accelerations/wdot-ft_sec2')
        g = fdm.get_property_value('accelerations/gravity-ft_sec2')
        theta = fdm.get_property_value('attitude/theta-rad')

        # There is a lag of one time step between the computations of the
        # accelerations and the update of the accelerometer
        fdm.run()
        fax = fdm.get_property_value('fcs/accelerometer/X')
        fay = fdm.get_property_value('fcs/accelerometer/Y')
        faz = fdm.get_property_value('fcs/accelerometer/Z')

        fax -= ax
        fay -= ay
        faz -= az

        # Deltas are relaxed because the tolerances of the trimming algorithm
        # are quite relaxed themselves.
        self.assertAlmostEqual(faz / (g * math.cos(theta)), -1.0, delta=1E-5)
        self.assertAlmostEqual(fax / (g * math.sin(theta)), 1.0, delta=1E-5)
        self.assertAlmostEqual(math.sqrt(fax*fax+fay*fay+faz*faz)/g, 1.0, delta=1E-6)

        del fdm
예제 #27
0
    def test_dynamic_hold_down(self):
        fdm = CreateFDM(self.sandbox)
        fdm.load_model('J246')
        fdm.load_ic('LC39', True)
        fdm['forces/hold-down'] = 1.0
        fdm.run_ic()
        h0 = fdm['position/vrp-radius-ft']
        # Start solid rocket boosters
        fdm['fcs/throttle-cmd-norm[0]'] = 1.0
        fdm['fcs/throttle-cmd-norm[1]'] = 1.0
        t = 0.0

        while t < 420.0:
            fdm.run()
            t = fdm['simulation/sim-time-sec']
            self.assertAlmostEqual(fdm['position/vrp-radius-ft'] / h0,
                                   1.0,
                                   delta=1E-9)
예제 #28
0
    def test_dynamic_hold_down(self):
        fdm = CreateFDM(self.sandbox)
        fdm.load_model('J246')
        aircraft_path = self.sandbox.path_to_jsbsim_file('aircraft')
        fdm.load_ic(os.path.join(aircraft_path, 'J246', 'LC39'), False)
        fdm['forces/hold-down'] = 1.0
        fdm.run_ic()
        h0 = fdm['position/vrp-radius-ft']
        # Start solid rocket boosters
        fdm['fcs/throttle-cmd-norm[0]'] = 1.0
        fdm['fcs/throttle-cmd-norm[1]'] = 1.0
        t = 0.0

        while t < 420.0:
            fdm.run()
            t = fdm['simulation/sim-time-sec']
            self.assertAlmostEqual(fdm['position/vrp-radius-ft'] / h0,
                                   1.0,
                                   delta=1E-9)
예제 #29
0
    def testOnGround(self):
        script_name = 'c1721.xml'
        script_path = self.sandbox.path_to_jsbsim_file('scripts', script_name)
        self.AddAccelerometersToAircraft(script_path)

        fdm = CreateFDM(self.sandbox)
        fdm.set_aircraft_path('aircraft')
        fdm.load_script(script_path)

        # Switch the accel on
        fdm.set_property_value('fcs/accelerometer/on', 1.0)
        # Use the standard gravity (i.e. GM/r^2)
        fdm.set_property_value('simulation/gravity-model', 0)
        # Simplifies the transformation to compare the accelerometer with the
        # gravity
        fdm.set_property_value('ic/psi-true-rad', 0.0)
        fdm.run_ic()

        for i in xrange(500):
            fdm.run()

        ax = fdm.get_property_value('accelerations/udot-ft_sec2')
        ay = fdm.get_property_value('accelerations/vdot-ft_sec2')
        az = fdm.get_property_value('accelerations/wdot-ft_sec2')
        g = fdm.get_property_value('accelerations/gravity-ft_sec2')
        theta = fdm.get_property_value('attitude/theta-rad')

        # There is a lag of one time step between the computations of the
        # accelerations and the update of the accelerometer
        fdm.run()
        fax = fdm.get_property_value('fcs/accelerometer/X')
        fay = fdm.get_property_value('fcs/accelerometer/Y')
        faz = fdm.get_property_value('fcs/accelerometer/Z')

        fax -= ax
        faz -= az

        self.assertAlmostEqual(fay, 0.0, delta=1E-6)
        self.assertAlmostEqual(fax / (g * math.sin(theta)), 1.0, delta=1E-5)
        self.assertAlmostEqual(faz / (g * math.cos(theta)), -1.0, delta=1E-7)

        del fdm
예제 #30
0
    def testOnGround(self):
        script_name = 'c1721.xml'
        script_path = self.sandbox.path_to_jsbsim_file('scripts', script_name)
        self.AddAccelerometersToAircraft(script_path)

        fdm = CreateFDM(self.sandbox)
        fdm.set_aircraft_path('aircraft')
        fdm.load_script(script_path)

        # Switch the accel on
        fdm.set_property_value('fcs/accelerometer/on', 1.0)
        # Use the standard gravity (i.e. GM/r^2)
        fdm.set_property_value('simulation/gravity-model', 0)
        # Simplifies the transformation to compare the accelerometer with the
        # gravity
        fdm.set_property_value('ic/psi-true-rad', 0.0)
        fdm.run_ic()

        for i in xrange(500):
            fdm.run()

        ax = fdm.get_property_value('accelerations/udot-ft_sec2')
        ay = fdm.get_property_value('accelerations/vdot-ft_sec2')
        az = fdm.get_property_value('accelerations/wdot-ft_sec2')
        g = fdm.get_property_value('accelerations/gravity-ft_sec2')
        theta = fdm.get_property_value('attitude/theta-rad')

        # There is a lag of one time step between the computations of the
        # accelerations and the update of the accelerometer
        fdm.run()
        fax = fdm.get_property_value('fcs/accelerometer/X')
        fay = fdm.get_property_value('fcs/accelerometer/Y')
        faz = fdm.get_property_value('fcs/accelerometer/Z')

        fax -= ax
        faz -= az

        self.assertAlmostEqual(fay, 0.0, delta=1E-6)
        self.assertAlmostEqual(fax / (g * math.sin(theta)), 1.0, delta=1E-5)
        self.assertAlmostEqual(faz / (g * math.cos(theta)), -1.0, delta=1E-7)

        del fdm
예제 #31
0
파일: CheckTrim.py 프로젝트: Outerra/jsbsim
    def test_trim_on_ground(self):
        # Check that the trim is made with up to date initial conditions
        fdm = CreateFDM(self.sandbox)
        fdm.load_model('c172x')
        fdm['ic/theta-deg'] = 90.0
        fdm.run_ic()
        fdm['ic/theta-deg'] = 0.0
        # If the trim fails, it will raise an exception
        fdm['simulation/do_simple_trim'] = 2  # Ground trim

        # Check that the aircraft has been trimmed successfully (velocities
        # should be zero i.e. the aircraft must be motionless once trimmed).
        while fdm['simulation/sim-time-sec'] <= 1.0:
            fdm.run()
            self.assertAlmostEqual(fdm['velocities/p-rad_sec'], 0., delta=1E-4)
            self.assertAlmostEqual(fdm['velocities/q-rad_sec'], 0., delta=1E-4)
            self.assertAlmostEqual(fdm['velocities/r-rad_sec'], 0., delta=1E-4)
            self.assertAlmostEqual(fdm['velocities/u-fps'], 0.0, delta=1E-4)
            self.assertAlmostEqual(fdm['velocities/v-fps'], 0.0, delta=1E-4)
            self.assertAlmostEqual(fdm['velocities/w-fps'], 0.0, delta=1E-4)
예제 #32
0
    def test_trim_on_ground(self):
        # Check that the trim is made with up to date initial conditions
        fdm = CreateFDM(self.sandbox)
        fdm.load_model('c172x')
        fdm['ic/theta-deg'] = 90.0
        fdm.run_ic()
        fdm['ic/theta-deg'] = 0.0
        # If the trim fails, it will raise an exception
        fdm['simulation/do_simple_trim'] = 2  # Ground trim

        # Check that the aircraft has been trimmed successfully (velocities
        # should be zero i.e. the aircraft must be motionless once trimmed).
        while fdm['simulation/sim-time-sec'] <= 1.0:
            fdm.run()
            self.assertAlmostEqual(fdm['velocities/p-rad_sec'], 0., delta=1E-4)
            self.assertAlmostEqual(fdm['velocities/q-rad_sec'], 0., delta=1E-4)
            self.assertAlmostEqual(fdm['velocities/r-rad_sec'], 0., delta=1E-4)
            self.assertAlmostEqual(fdm['velocities/u-fps'], 0.0, delta=1E-4)
            self.assertAlmostEqual(fdm['velocities/v-fps'], 0.0, delta=1E-4)
            self.assertAlmostEqual(fdm['velocities/w-fps'], 0.0, delta=1E-4)
예제 #33
0
    def testEnginePowerVC(self):
        fdm = CreateFDM(self.sandbox)
        fdm.load_script(self.sandbox.path_to_jsbsim_file('scripts',
                                                         'L4102.xml'))
        fdm.run_ic()
        pm = fdm.get_property_manager()
        self.assertTrue(pm.hasNode('propulsion/engine[0]/EnginePowerVC'))
        self.assertTrue(pm.hasNode('propulsion/engine[1]/EnginePowerVC'))

        while fdm.run():
            self.assertAlmostEqual(fdm['propulsion/engine[0]/EnginePowerVC'],
                                   fdm['propulsion/engine[1]/EnginePowerVC'])
예제 #34
0
    def testEnginePowerVC(self):
        fdm = CreateFDM(self.sandbox)
        fdm.load_script(
            self.sandbox.path_to_jsbsim_file('scripts', 'L4102.xml'))
        fdm.run_ic()
        pm = fdm.get_property_manager()
        self.assertTrue(pm.hasNode('propulsion/engine[0]/EnginePowerVC'))
        self.assertTrue(pm.hasNode('propulsion/engine[1]/EnginePowerVC'))

        while fdm.run():
            self.assertAlmostEqual(fdm['propulsion/engine[0]/EnginePowerVC'],
                                   fdm['propulsion/engine[1]/EnginePowerVC'])
예제 #35
0
    def testKinematicAndTrim(self):
        fdm = CreateFDM(self.sandbox)
        fdm.load_model('p51d')
        fdm.load_ic('reset01', True)
        self.assertEqual(fdm['gear/gear-cmd-norm'], 1.0)
        # Set the landing gears up. Since the command is equal to 1.0, the
        # <kinematic> system will trigger the gear down sequence.
        fdm['gear/gear-pos-norm'] = 0.0
        fdm.run_ic()

        # The test succeeds if the trim does not raise an exception i.e. if the
        # <kinematic> system does not interfer with the trim on ground
        # algorithm.
        fdm['simulation/do_simple_trim'] = 2  # Ground trim

        # Check that the gear is down after the trim as requested by
        # gear/gear-cmd-norm
        self.assertAlmostEqual(fdm['gear/gear-pos-norm'], 1.0)

        # Check that the gear is not moving to another position after trim.
        fdm.run()
        self.assertAlmostEqual(fdm['gear/gear-pos-norm'], 1.0)
예제 #36
0
    def testMagnitude(self):
        fdm = CreateFDM(self.sandbox)
        fdm.load_script(self.sandbox.path_to_jsbsim_file('scripts',
                                                         'c172_cruise_8K.xml'))

        fdm.run_ic()
        t = 0.0

        startup_duration = 5.0
        steady_duration = 1.0
        end_duration = 5.0
        start_time = 10.0
        magnitude = 30.0

        end_time = start_time + startup_duration + steady_duration + end_duration

        while fdm.get_property_value('simulation/run_id') == 0:
            fdm.run()
            wn = fdm.get_property_value('atmosphere/total-wind-north-fps')
            we = fdm.get_property_value('atmosphere/total-wind-east-fps')
            wd = fdm.get_property_value('atmosphere/total-wind-down-fps')

            if t >= start_time and t <= end_time:
                wmag = math.sqrt(wn*wn + we*we + wd*wd)
                t -= start_time
                if t <= startup_duration:
                    self.assertAlmostEqual(0.5 * magnitude * (1.0 - math.cos(math.pi*t/startup_duration)),
                                           wmag, delta=1E-3)
                else:
                    t -= startup_duration
                    if t <= steady_duration:
                        self.assertAlmostEqual(magnitude, wmag, delta=1E-8)
                    else:
                        t -= steady_duration
                        if t <= end_duration:
                            self.assertAlmostEqual(0.5 * magnitude * (1.0 + math.cos(math.pi*t/end_duration)),
                                                   wmag, delta=1E-3)

            t = fdm.get_property_value('simulation/sim-time-sec')
예제 #37
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)
예제 #38
0
    def test_moment(self):
        script_path = self.sandbox.path_to_jsbsim_file('scripts',
                                                       'ball_chute.xml')
        tree, aircraft_name, aircraft_path = CopyAircraftDef(
            script_path, self.sandbox)
        extReact_element = tree.getroot().find('external_reactions')
        moment_element = et.SubElement(extReact_element, 'moment')
        moment_element.attrib['name'] = 'parachute'
        moment_element.attrib['frame'] = 'WIND'
        direction_element = et.SubElement(moment_element, 'direction')
        x_element = et.SubElement(direction_element, 'x')
        x_element.text = '0.2'
        y_element = et.SubElement(direction_element, 'y')
        y_element.text = '0.0'
        z_element = et.SubElement(direction_element, 'z')
        z_element.text = '-1.5'

        tree.write(
            self.sandbox('aircraft', aircraft_name, aircraft_name + '.xml'))

        fdm = CreateFDM(self.sandbox)
        fdm.set_aircraft_path('aircraft')
        fdm.load_script(script_path)
        fdm.run_ic()

        mDir = np.array([0.2, 0.0, -1.5])
        mDir /= np.linalg.norm(mDir)
        self.assertAlmostEqual(fdm['external_reactions/parachute/l'], mDir[0])
        self.assertAlmostEqual(fdm['external_reactions/parachute/m'], mDir[1])
        self.assertAlmostEqual(fdm['external_reactions/parachute/n'], mDir[2])

        fdm['external_reactions/parachute/magnitude-lbsft'] = -3.5

        while fdm.run():
            Tw2b = fdm.get_auxiliary().get_Tw2b()
            mag = fdm['aero/qbar-psf'] * fdm[
                'fcs/parachute_reef_pos_norm'] * 20.0
            f = Tw2b * np.mat([-1.0, 0.0, 0.0]).T * mag
            self.assertAlmostEqual(fdm['forces/fbx-external-lbs'], f[0, 0])
            self.assertAlmostEqual(fdm['forces/fby-external-lbs'], f[1, 0])
            self.assertAlmostEqual(fdm['forces/fbz-external-lbs'], f[2, 0])

            m = -3.5 * Tw2b * np.mat(mDir).T
            fm = np.cross(self.getLeverArm(fdm, 'parachute'),
                          np.array([f[0, 0], f[1, 0], f[2, 0]]))
            self.assertAlmostEqual(fdm['moments/l-external-lbsft'],
                                   m[0, 0] + fm[0])
            self.assertAlmostEqual(fdm['moments/m-external-lbsft'],
                                   m[1, 0] + fm[1])
            self.assertAlmostEqual(fdm['moments/n-external-lbsft'],
                                   m[2, 0] + fm[2])
예제 #39
0
    def testKinematicAndTrim(self):
        fdm = CreateFDM(self.sandbox)
        fdm.load_model('p51d')
        fdm.load_ic(self.sandbox.path_to_jsbsim_file('aircraft', 'p51d',
                                                     'reset01'), False)
        self.assertEqual(fdm['gear/gear-cmd-norm'], 1.0)
        # Set the landing gears up. Since the command is equal to 1.0, the
        # <kinematic> system will trigger the gear down sequence.
        fdm['gear/gear-pos-norm'] = 0.0
        fdm.run_ic()

        # The test succeeds if the trim does not raise an exception i.e. if the
        # <kinematic> system does not interfer with the trim on ground
        # algorithm.
        fdm['simulation/do_simple_trim'] = 2  # Ground trim

        # Check that the gear is down after the trim as requested by
        # gear/gear-cmd-norm
        self.assertAlmostEqual(fdm['gear/gear-pos-norm'], 1.0)

        # Check that the gear is not moving to another position after trim.
        fdm.run()
        self.assertAlmostEqual(fdm['gear/gear-pos-norm'], 1.0)
예제 #40
0
    def testOnGround(self):
        script_name = 'c1721.xml'
        script_path = self.sandbox.path_to_jsbsim_file('scripts', script_name)
        self.AddAccelerometersToAircraft(script_path)

        fdm = CreateFDM(self.sandbox)
        fdm.set_aircraft_path('aircraft')
        fdm.load_script(script_path)

        # Switch the accel on
        fdm['fcs/accelerometer/on'] = 1.0
        # Use the standard gravity (i.e. GM/r^2)
        fdm['simulation/gravity-model'] = 0
        # Simplifies the transformation to compare the accelerometer with the
        # gravity
        fdm['ic/psi-true-rad'] = 0.0
        fdm.run_ic()

        for i in xrange(1000):
            fdm.run()

        r = fdm['position/radius-to-vehicle-ft']
        g = fdm['accelerations/gravity-ft_sec2']
        latitude = fdm['position/lat-gc-rad']
        pitch = fdm['attitude/theta-rad']
        omega = 0.00007292115  # Earth rotation rate in rad/sec
        fc = r * math.cos(latitude) * omega * omega

        fax = fc * math.sin(latitude - pitch) + g * math.sin(pitch)
        faz = fc * math.cos(latitude - pitch) - g * math.cos(pitch)

        self.assertAlmostEqual(fdm['fcs/accelerometer/X'], fax, delta=1E-7)
        self.assertAlmostEqual(fdm['fcs/accelerometer/Y'], 0.0, delta=1E-7)
        self.assertAlmostEqual(fdm['fcs/accelerometer/Z'], faz, delta=1E-6)

        del fdm
예제 #41
0
    def testOnGround(self):
        script_name = 'c1721.xml'
        script_path = self.sandbox.path_to_jsbsim_file('scripts', script_name)
        self.AddAccelerometersToAircraft(script_path)

        fdm = CreateFDM(self.sandbox)
        fdm.set_aircraft_path('aircraft')
        fdm.load_script(script_path)

        # Switch the accel on
        fdm['fcs/accelerometer/on'] = 1.0
        # Use the standard gravity (i.e. GM/r^2)
        fdm['simulation/gravity-model'] = 0
        # Simplifies the transformation to compare the accelerometer with the
        # gravity
        fdm['ic/psi-true-rad'] = 0.0
        fdm.run_ic()

        for i in xrange(1000):
            fdm.run()

        r = fdm['position/radius-to-vehicle-ft']
        g = fdm['accelerations/gravity-ft_sec2']
        latitude = fdm['position/lat-gc-rad']
        pitch = fdm['attitude/theta-rad']
        omega = 0.00007292115  # Earth rotation rate in rad/sec
        fc = r * math.cos(latitude) * omega * omega

        fax = fc * math.sin(latitude - pitch) + g * math.sin(pitch)
        faz = fc * math.cos(latitude - pitch) - g * math.cos(pitch)

        self.assertAlmostEqual(fdm['fcs/accelerometer/X'], fax, delta=1E-7)
        self.assertAlmostEqual(fdm['fcs/accelerometer/Y'], 0.0, delta=1E-7)
        self.assertAlmostEqual(fdm['fcs/accelerometer/Z'], faz, delta=1E-6)

        del fdm
예제 #42
0
    def testOrbitCheckCase(self):
        os.environ['JSBSIM_DEBUG'] = str(0)
        fdm = CreateFDM(self.sandbox)
        fdm.load_script(self.sandbox.path_to_jsbsim_file('scripts', 'ball_orbit.xml'))
        fdm.run_ic()

        while fdm.run():
            pass

        ref, current = Table(), Table()
        ref.ReadCSV(self.sandbox.elude(self.sandbox.path_to_jsbsim_file('logged_data', 'BallOut.csv')))
        current.ReadCSV(self.sandbox('BallOut.csv'))

        diff = ref.compare(current)
        self.longMessage = True
        self.assertTrue(diff.empty(), msg='\n'+repr(diff))
예제 #43
0
    def testChannelRate(self):
        os.environ['JSBSIM_DEBUG'] = str(0)
        fdm = CreateFDM(self.sandbox)
        fdm.load_script(
            self.sandbox.path_to_jsbsim_file('scripts',
                                             'systems-rate-test-0.xml'))
        fdm.run_ic()

        while fdm['simulation/sim-time-sec'] < 30:
            fdm.run()
            self.assertEqual(fdm['simulation/frame'], fdm['tests/rate-1'])
            self.assertEqual(int(fdm['simulation/frame'] / 4),
                             fdm['tests/rate-4'])
            self.assertEqual(fdm['simulation/sim-time-sec'],
                             fdm['tests/rate-1-dt-sum'])
            self.assertAlmostEqual(
                fdm['simulation/dt'] * fdm['tests/rate-4'] * 4,
                fdm['tests/rate-4-dt-sum'])

        self.assertEqual(fdm['simulation/dt'], fdm['tests/rate-1-dt'])
        self.assertEqual(fdm['simulation/dt'] * 4, fdm['tests/rate-4-dt'])

        try:
            fdm['simulation/do_simple_trim'] = 1
        except RuntimeError as e:
            # The trim cannot succeed. Just make sure that the raised exception
            # is due to the trim failure otherwise rethrow.
            if e.args[0] != 'Trim Failed':
                raise

        while fdm['simulation/sim-time-sec'] < 40:
            self.assertEqual(fdm['simulation/frame'], fdm['tests/rate-1'])
            self.assertEqual(int(fdm['simulation/frame'] / 4),
                             fdm['tests/rate-4'])
            self.assertEqual(fdm['simulation/sim-time-sec'],
                             fdm['tests/rate-1-dt-sum'])
            self.assertAlmostEqual(
                fdm['simulation/dt'] * fdm['tests/rate-4'] * 4,
                fdm['tests/rate-4-dt-sum'])
            fdm.run()

        fdm.reset_to_initial_conditions(1)
        tf = fdm['tests/rate-1-dt-sum']
        xtraFrames = fdm['simulation/frame'] % 4

        while fdm['simulation/sim-time-sec'] < 30:
            fdm.run()
            self.assertEqual(fdm['simulation/frame'], fdm['tests/rate-1'])
            self.assertEqual(int((fdm['simulation/frame'] - xtraFrames) / 4),
                             fdm['tests/rate-4'])
            self.assertAlmostEqual(fdm['simulation/sim-time-sec'],
                                   fdm['tests/rate-1-dt-sum'] - tf)
            self.assertAlmostEqual(
                fdm['simulation/dt'] * fdm['tests/rate-4'] * 4,
                fdm['tests/rate-4-dt-sum'])
예제 #44
0
    def test_moment(self):
        script_path = self.sandbox.path_to_jsbsim_file('scripts',
                                                       'ball_chute.xml')
        tree, aircraft_name, aircraft_path = CopyAircraftDef(script_path,
                                                             self.sandbox)
        extReact_element = tree.getroot().find('external_reactions')
        moment_element = et.SubElement(extReact_element, 'moment')
        moment_element.attrib['name'] = 'parachute'
        moment_element.attrib['frame'] = 'WIND'
        direction_element = et.SubElement(moment_element, 'direction')
        x_element = et.SubElement(direction_element, 'x')
        x_element.text = '0.2'
        y_element = et.SubElement(direction_element, 'y')
        y_element.text = '0.0'
        z_element = et.SubElement(direction_element, 'z')
        z_element.text = '-1.5'

        tree.write(self.sandbox('aircraft', aircraft_name,
                                aircraft_name+'.xml'))

        fdm = CreateFDM(self.sandbox)
        fdm.set_aircraft_path('aircraft')
        fdm.load_script(script_path)
        fdm.run_ic()

        mDir = np.array([0.2, 0.0, -1.5])
        mDir /= np.linalg.norm(mDir)
        self.assertAlmostEqual(fdm['external_reactions/parachute/l'], mDir[0])
        self.assertAlmostEqual(fdm['external_reactions/parachute/m'], mDir[1])
        self.assertAlmostEqual(fdm['external_reactions/parachute/n'], mDir[2])

        fdm['external_reactions/parachute/magnitude-lbsft'] = -3.5

        while fdm.run():
            Tw2b = fdm.get_auxiliary().get_Tw2b()
            mag = fdm['aero/qbar-psf'] * fdm['fcs/parachute_reef_pos_norm']*20.0
            f = Tw2b * np.mat([-1.0, 0.0, 0.0]).T * mag
            self.assertAlmostEqual(fdm['forces/fbx-external-lbs'], f[0, 0])
            self.assertAlmostEqual(fdm['forces/fby-external-lbs'], f[1, 0])
            self.assertAlmostEqual(fdm['forces/fbz-external-lbs'], f[2, 0])

            m = -3.5 * Tw2b * np.mat(mDir).T
            fm = np.cross(self.getLeverArm(fdm,'parachute'),
                          np.array([f[0,0], f[1,0], f[2, 0]]))
            self.assertAlmostEqual(fdm['moments/l-external-lbsft'], m[0, 0] + fm[0])
            self.assertAlmostEqual(fdm['moments/m-external-lbsft'], m[1, 0] + fm[1])
            self.assertAlmostEqual(fdm['moments/n-external-lbsft'], m[2, 0] + fm[2])
예제 #45
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)
예제 #46
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)
예제 #47
0
    def testChannelRate(self):
        os.environ['JSBSIM_DEBUG'] = str(0)
        fdm = CreateFDM(self.sandbox)
        fdm.load_script(
            self.sandbox.path_to_jsbsim_file('scripts',
                                             'systems-rate-test-0.xml'))
        fdm.run_ic()

        while fdm['simulation/sim-time-sec'] < 30:
            fdm.run()
            self.assertEqual(fdm['simulation/frame'], fdm['tests/rate-1'])
            self.assertEqual(int(fdm['simulation/frame'] / 4),
                             fdm['tests/rate-4'])
            self.assertEqual(fdm['simulation/sim-time-sec'],
                             fdm['tests/rate-1-dt-sum'])
            self.assertAlmostEqual(
                fdm['simulation/dt'] * fdm['tests/rate-4'] * 4,
                fdm['tests/rate-4-dt-sum'])

        self.assertEqual(fdm['simulation/dt'], fdm['tests/rate-1-dt'])
        self.assertEqual(fdm['simulation/dt'] * 4, fdm['tests/rate-4-dt'])

        # Trigger the trimming and check that it fails (i.e. it raises an
        # exception TrimFailureError)
        with self.assertRaises(TrimFailureError):
            fdm['simulation/do_simple_trim'] = 1

        while fdm['simulation/sim-time-sec'] < 40:
            self.assertEqual(fdm['simulation/frame'], fdm['tests/rate-1'])
            self.assertEqual(int(fdm['simulation/frame'] / 4),
                             fdm['tests/rate-4'])
            self.assertEqual(fdm['simulation/sim-time-sec'],
                             fdm['tests/rate-1-dt-sum'])
            self.assertAlmostEqual(
                fdm['simulation/dt'] * fdm['tests/rate-4'] * 4,
                fdm['tests/rate-4-dt-sum'])
            fdm.run()

        fdm.reset_to_initial_conditions(1)
        tf = fdm['tests/rate-1-dt-sum']
        xtraFrames = fdm['simulation/frame'] % 4

        while fdm['simulation/sim-time-sec'] < 30:
            fdm.run()
            self.assertEqual(fdm['simulation/frame'], fdm['tests/rate-1'])
            self.assertEqual(int((fdm['simulation/frame'] - xtraFrames) / 4),
                             fdm['tests/rate-4'])
            self.assertAlmostEqual(fdm['simulation/sim-time-sec'],
                                   fdm['tests/rate-1-dt-sum'] - tf)
            self.assertAlmostEqual(
                fdm['simulation/dt'] * fdm['tests/rate-4'] * 4,
                fdm['tests/rate-4-dt-sum'])
예제 #48
0
    def testChannelRate(self):
        os.environ['JSBSIM_DEBUG'] = str(0)
        fdm = CreateFDM(self.sandbox)
        fdm.load_script(self.sandbox.path_to_jsbsim_file('scripts',
                                                         'systems-rate-test-0.xml'))
        fdm.run_ic()

        while fdm['simulation/sim-time-sec'] < 30:
            fdm.run()
            self.assertEqual(fdm['simulation/frame'], fdm['tests/rate-1'])
            self.assertEqual(int(fdm['simulation/frame']/4),
                             fdm['tests/rate-4'])
            self.assertEqual(fdm['simulation/sim-time-sec'],
                             fdm['tests/rate-1-dt-sum'])
            self.assertAlmostEqual(fdm['simulation/dt']*fdm['tests/rate-4']*4,
                                   fdm['tests/rate-4-dt-sum'])

        self.assertEqual(fdm['simulation/dt'], fdm['tests/rate-1-dt'])
        self.assertEqual(fdm['simulation/dt']*4, fdm['tests/rate-4-dt'])

        try:
            fdm['simulation/do_simple_trim'] = 1
        except RuntimeError as e:
            # The trim cannot succeed. Just make sure that the raised exception
            # is due to the trim failure otherwise rethrow.
            if e.args[0] != 'Trim Failed':
                raise

        while fdm['simulation/sim-time-sec'] < 40:
            self.assertEqual(fdm['simulation/frame'], fdm['tests/rate-1'])
            self.assertEqual(int(fdm['simulation/frame']/4),
                             fdm['tests/rate-4'])
            self.assertEqual(fdm['simulation/sim-time-sec'],
                             fdm['tests/rate-1-dt-sum'])
            self.assertAlmostEqual(fdm['simulation/dt']*fdm['tests/rate-4']*4,
                                   fdm['tests/rate-4-dt-sum'])
            fdm.run()

        fdm.reset_to_initial_conditions(1)
        tf = fdm['tests/rate-1-dt-sum']
        xtraFrames = fdm['simulation/frame'] % 4

        while fdm['simulation/sim-time-sec'] < 30:
            fdm.run()
            self.assertEqual(fdm['simulation/frame'], fdm['tests/rate-1'])
            self.assertEqual(int((fdm['simulation/frame']-xtraFrames)/4),
                             fdm['tests/rate-4'])
            self.assertAlmostEqual(fdm['simulation/sim-time-sec'],
                                   fdm['tests/rate-1-dt-sum']-tf)
            self.assertAlmostEqual(fdm['simulation/dt']*fdm['tests/rate-4']*4,
                                   fdm['tests/rate-4-dt-sum'])
예제 #49
0
    def testOrbitCheckCase(self):
        os.environ['JSBSIM_DEBUG'] = str(0)
        fdm = CreateFDM(self.sandbox)
        fdm.load_script(
            self.sandbox.path_to_jsbsim_file('scripts', 'ball_orbit.xml'))
        fdm.run_ic()

        while fdm.run():
            pass

        ref, current = Table(), Table()
        ref.ReadCSV(
            self.sandbox.elude(
                self.sandbox.path_to_jsbsim_file('logged_data',
                                                 'BallOut.csv')))
        current.ReadCSV(self.sandbox('BallOut.csv'))

        diff = ref.compare(current)
        self.longMessage = True
        self.assertTrue(diff.empty(), msg='\n' + repr(diff))
예제 #50
0
    def test_failhardover_without_clipto(self):
        tree, flight_control_element, actuator_element = self.prepare_actuator(
        )
        rate_limit = float(actuator_element.find('rate_limit').text)
        fail_hardover = actuator_element.attrib[
            'name'] + "/malfunction/fail_hardover"
        clipto = actuator_element.find('clipto')
        clipmax = float(clipto.find('max').text)
        actuator_element.remove(clipto)
        output_file = os.path.join('aircraft', self.aircraft_name,
                                   self.aircraft_name + '.xml')
        tree.write(output_file)

        fdm = CreateFDM(self.sandbox)
        fdm.set_aircraft_path('aircraft')
        fdm.load_script(self.script_path)
        fdm.run_ic()

        # Displace the actuator in the maximum position.
        fdm[self.input_prop] = clipmax
        t = fdm['simulation/sim-time-sec']
        dt = clipmax / rate_limit
        while fdm['simulation/sim-time-sec'] <= t + dt:
            fdm.run()

        # Check the maximum position has been reached.
        self.assertAlmostEqual(fdm[self.output_prop], clipmax)

        # Trigger "fail hardover"
        fdm[fail_hardover] = 1.0
        t = fdm['simulation/sim-time-sec']
        dt = clipmax / rate_limit
        while fdm['simulation/sim-time-sec'] <= t + dt:
            fdm.run()

        # Check the actuator is failed in neutral position
        self.assertAlmostEqual(fdm[self.output_prop], 0.0)

        # Check that setting an input different from the neutral position does
        # not result in a modification of the actuator position.
        fdm[self.input_prop] = clipmax
        t = fdm['simulation/sim-time-sec']
        dt = clipmax / rate_limit
        while fdm['simulation/sim-time-sec'] <= t + dt:
            fdm.run()
            self.assertAlmostEqual(fdm[self.output_prop], 0.0)
예제 #51
0
    def testOrbitCheckCase(self):
        os.environ['JSBSIM_DEBUG'] = str(0)
        fdm = CreateFDM(self.sandbox)
        fdm.load_script(
            self.sandbox.path_to_jsbsim_file('scripts', 'ball_orbit.xml'))
        fdm.run_ic()

        while fdm.run():
            pass

        ref = pd.read_csv(self.sandbox.path_to_jsbsim_file(
            'logged_data', 'BallOut.csv'),
                          index_col=0)
        current = pd.read_csv('BallOut.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, 1E-5)
        self.longMessage = True
        self.assertEqual(len(diff), 0, msg='\n' + diff.to_string())
예제 #52
0
    def testOrbitCheckCase(self):
        os.environ['JSBSIM_DEBUG'] = str(0)
        fdm = CreateFDM(self.sandbox)
        fdm.load_script(self.sandbox.path_to_jsbsim_file('scripts',
                                                         'ball_orbit.xml'))
        fdm.run_ic()

        while fdm.run():
            pass

        ref = pd.read_csv(self.sandbox.path_to_jsbsim_file('logged_data',
                                                           'BallOut.csv'),
                          index_col=0)
        current = pd.read_csv('BallOut.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, 1E-5)
        self.longMessage = True
        self.assertEqual(len(diff), 0, msg='\n'+diff.to_string())
예제 #53
0
class TestAeroFuncFrame(JSBSimTestCase):
    def setUp(self):
        JSBSimTestCase.setUp(self)

        self.fdm = CreateFDM(self.sandbox)
        self.script_path = self.sandbox.path_to_jsbsim_file('scripts',
                                                            'x153.xml')
        self.tree, self.aircraft_name, b = CopyAircraftDef(self.script_path, self.sandbox)

        self.aero2wind = np.mat(np.identity(3));
        self.aero2wind[0,0] *= -1.0
        self.aero2wind[2,2] *= -1.0
        self.auxilliary = self.fdm.get_auxiliary()

    def tearDown(self):
        del self.fdm
        JSBSimTestCase.tearDown(self)

    def getTs2b(self):
        alpha = self.fdm['aero/alpha-rad']
        ca = math.cos(alpha)
        sa = math.sin(alpha)
        Ts2b = np.mat([[ca, 0., -sa],
                       [0., 1., 0.],
                       [sa, 0., ca]])
        return Ts2b

    def checkForcesAndMoments(self, getForces, getMoment, aeroFunc):
        self.fdm.load_script(self.script_path)
        self.fdm.run_ic()

        rp = np.mat([self.fdm['metrics/aero-rp-x-in'],
                     -self.fdm['metrics/aero-rp-y-in'],
                     self.fdm['metrics/aero-rp-z-in']])
        result = {}

        while self.fdm.run():
            for axis in aeroFunc.keys():
                result[axis] = 0.0

                for func in aeroFunc[axis]:
                    result[axis] += self.fdm[func]

            Fa, Fb = getForces(result)
            Tb2s = self.getTs2b().T
            Fs = self.aero2wind * (Tb2s * Fb)

            Mb_MRC = getMoment(result)
            cg = np.mat([self.fdm['inertia/cg-x-in'],
                         -self.fdm['inertia/cg-y-in'],
                         self.fdm['inertia/cg-z-in']])
            arm_ft = (cg - rp)/12.0 # Convert from inches to ft
            Mb = Mb_MRC + np.cross(arm_ft, Fb.T)
            Tb2w = self.auxilliary.get_Tb2w()
            Mw = Tb2w * Mb.T
            Ms = Tb2s * Mb.T

            self.assertAlmostEqual(Fa[0,0], self.fdm['forces/fwx-aero-lbs'])
            self.assertAlmostEqual(Fa[1,0], self.fdm['forces/fwy-aero-lbs'])
            self.assertAlmostEqual(Fa[2,0], self.fdm['forces/fwz-aero-lbs'])
            self.assertAlmostEqual(Fb[0,0], self.fdm['forces/fbx-aero-lbs'])
            self.assertAlmostEqual(Fb[1,0], self.fdm['forces/fby-aero-lbs'])
            self.assertAlmostEqual(Fb[2,0], self.fdm['forces/fbz-aero-lbs'])
            self.assertAlmostEqual(Fs[0,0], self.fdm['forces/fsx-aero-lbs'])
            self.assertAlmostEqual(Fs[1,0], self.fdm['forces/fsy-aero-lbs'])
            self.assertAlmostEqual(Fs[2,0], self.fdm['forces/fsz-aero-lbs'])
            self.assertAlmostEqual(Mb[0,0], self.fdm['moments/l-aero-lbsft'])
            self.assertAlmostEqual(Mb[0,1], self.fdm['moments/m-aero-lbsft'])
            self.assertAlmostEqual(Mb[0,2], self.fdm['moments/n-aero-lbsft'])
            self.assertAlmostEqual(Ms[0,0], self.fdm['moments/roll-stab-aero-lbsft'])
            self.assertAlmostEqual(Ms[1,0], self.fdm['moments/pitch-stab-aero-lbsft'])
            self.assertAlmostEqual(Ms[2,0], self.fdm['moments/yaw-stab-aero-lbsft'])
            self.assertAlmostEqual(Mw[0,0], self.fdm['moments/roll-wind-aero-lbsft'])
            self.assertAlmostEqual(Mw[1,0], self.fdm['moments/pitch-wind-aero-lbsft'])
            self.assertAlmostEqual(Mw[2,0], self.fdm['moments/yaw-wind-aero-lbsft'])

    def checkAerodynamicsFrame(self, newAxisName, getForces, getMoment, frame):
        aeroFunc = {}

        for axis in self.tree.findall('aerodynamics/axis'):
            axisName = newAxisName[axis.attrib['name']]
            axis.attrib['name'] = axisName
            if frame:
                axis.attrib['frame'] = frame
            aeroFunc[axisName] = []

            for func in axis.findall('function'):
                aeroFunc[axisName].append(func.attrib['name'])

                if (frame == 'BODY' or len(frame) == 0) and (axisName == 'X' or axisName == 'Z'):
                    # Convert the signs of X and Z forces so that the force
                    # along X is directed backward and the force along Z is
                    # directed upward.
                    product_tag = func.find('product')
                    value_tag = et.SubElement(product_tag, 'value')
                    value_tag.text = '-1.0'

        self.tree.write(self.sandbox('aircraft', self.aircraft_name,
                                     self.aircraft_name+'.xml'))
        self.fdm.set_aircraft_path('aircraft')

        self.checkForcesAndMoments(getForces, getMoment, aeroFunc)

    def checkBodyFrame(self, frame):
        newAxisName = {'DRAG': 'X', 'SIDE': 'Y', 'LIFT': 'Z',
                       'ROLL': 'ROLL', 'PITCH': 'PITCH', 'YAW': 'YAW'}

        def getForces(result):
            Tb2w = self.auxilliary.get_Tb2w()
            Fb = np.mat([result['X'], result['Y'], result['Z']]).T
            Fw = Tb2w * Fb
            Fa = self.aero2wind * Fw
            return Fa, Fb

        def getMoment(result):
            return np.mat([result['ROLL'], result['PITCH'], result['YAW']])

        self.checkAerodynamicsFrame(newAxisName, getForces, getMoment, '')

    def testBodyFrame(self):
        self.checkBodyFrame('')

    def testBodyFrameAltSyntax(self):
        self.checkBodyFrame('BODY')

    def testAxialFrame(self):
        newAxisName = {'DRAG': 'AXIAL', 'SIDE': 'SIDE', 'LIFT': 'NORMAL',
                       'ROLL': 'ROLL', 'PITCH': 'PITCH', 'YAW': 'YAW'}

        def getForces(result):
            Tb2w = self.auxilliary.get_Tb2w()
            Fnative = np.mat([result['AXIAL'], result['SIDE'], result['NORMAL']]).T
            Fb = self.aero2wind * Fnative
            Fw = Tb2w * Fb
            Fa = self.aero2wind * Fw
            return Fa, Fb

        def getMoment(result):
            return np.mat([result['ROLL'], result['PITCH'], result['YAW']])

        self.checkAerodynamicsFrame(newAxisName, getForces, getMoment, '')

    def testWindFrame(self):
        newAxisName = {'DRAG': 'X', 'SIDE': 'Y', 'LIFT': 'Z',
                       'ROLL': 'ROLL', 'PITCH': 'PITCH', 'YAW': 'YAW'}

        def getForces(result):
            Tw2b = self.auxilliary.get_Tw2b()
            Fa = np.mat([result['X'], result['Y'], result['Z']]).T
            Fw = self.aero2wind * Fa
            Fb = Tw2b * Fw
            return Fa, Fb

        def getMoment(result):
            Tw2b = self.auxilliary.get_Tw2b()
            Mw = np.mat([result['ROLL'], result['PITCH'], result['YAW']]).T
            Mb = Tw2b*Mw
            return Mb.T

        self.checkAerodynamicsFrame(newAxisName, getForces, getMoment, 'WIND')

    def testAeroFrame(self):
        aeroFunc = {}

        for axis in self.tree.findall('aerodynamics/axis'):
            axisName = axis.attrib['name']
            aeroFunc[axisName] = []

            for func in axis.findall('function'):
                aeroFunc[axisName].append(func.attrib['name'])

        def getForces(result):
            Tw2b = self.auxilliary.get_Tw2b()
            Fa = np.mat([result['DRAG'], result['SIDE'], result['LIFT']]).T
            Fw = self.aero2wind * Fa
            Fb = Tw2b * Fw
            return Fa, Fb

        def getMoment(result):
            return np.mat([result['ROLL'], result['PITCH'], result['YAW']])

        self.checkForcesAndMoments(getForces, getMoment, aeroFunc)

    def testStabilityFrame(self):
        newAxisName = {'DRAG': 'X', 'SIDE': 'Y', 'LIFT': 'Z',
                       'ROLL': 'ROLL', 'PITCH': 'PITCH', 'YAW': 'YAW'}

        def getForces(result):
            Tb2w = self.auxilliary.get_Tb2w()
            Ts2b = self.getTs2b()
            Fs = np.mat([result['X'], result['Y'], result['Z']]).T
            Fb = Ts2b * (self.aero2wind * Fs)
            Fw = Tb2w * Fb
            Fa = self.aero2wind * Fw
            return Fa, Fb

        def getMoment(result):
            Ts2b = self.getTs2b()
            Ms = np.mat([result['ROLL'], result['PITCH'], result['YAW']]).T
            Mb = Ts2b*Ms
            return Mb.T

        self.checkAerodynamicsFrame(newAxisName, getForces, getMoment, 'STABILITY')
예제 #54
0
class CheckOutputRate(JSBSimTestCase):
    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 tearDown(self):
        del self.fdm
        JSBSimTestCase.tearDown(self)

    def testOutputRate(self):
        self.fdm.load_script(self.script_path)

        # Check that the output is enabled by default
        self.assertEqual(self.fdm["simulation/output/enabled"], 1.0)

        # Check that the rate is consistent with the values extracted from the
        # script and the aircraft definition
        self.assertAlmostEqual(self.fdm["simulation/output/log_rate_hz"],
                               self.rateHz, delta=1E-5)

        self.fdm.run_ic()

        for i in range(self.rate):
            self.fdm.run()

        output = pd.read_csv(self.output_file)

        # According to the settings, the output file must contain 2 lines in
        # addition to the headers :
        # 1. The initial conditions
        # 2. The output after 'rate' iterations
        self.assertEqual(output['Time'].iloc[0], 0.0)
        self.assertEqual(output['Time'].iloc[1], self.rate * self.dt)
        self.assertEqual(output['Time'].iloc[1],
                         self.fdm["simulation/sim-time-sec"])

    def testDisablingOutput(self):
        self.fdm.load_script(self.script_path)

        # Disables the output during the initialization
        self.fdm["simulation/output/enabled"] = 0.0
        self.fdm.run_ic()
        self.fdm["simulation/output/enabled"] = 1.0

        for i in range(self.rate):
            self.fdm.run()

        output = pd.read_csv(self.output_file)

        # According to the settings, the output file must contain 1 line in
        # addition to the headers :
        # 1. The output after 'rate' iterations
        self.assertEqual(output['Time'].iloc[0],
                         self.fdm["simulation/sim-time-sec"])

    def testTrimRestoresOutputSettings(self):
        self.fdm.load_script(self.script_path)

        # Disables the output during the initialization
        self.fdm["simulation/output/enabled"] = 0.0
        self.fdm.run_ic()

        # Check that the output remains disabled even after the trim is
        # executed
        while self.fdm["simulation/sim-time-sec"] < self.trim_date + 2.0*self.dt:
            self.fdm.run()
            self.assertEqual(self.fdm["simulation/output/enabled"], 0.0)

        # Re-enable the output and check that the output rate is unaffected by
        # the previous operations
        self.fdm["simulation/output/enabled"] = 1.0
        frame = int(self.fdm["simulation/frame"])

        for i in range(self.rate):
            self.fdm.run()

        output = pd.read_csv(self.output_file)

        # The frame at which the data is logged must be the next multiple of
        # the output rate
        self.assertEqual(int(output['Time'].iloc[0] / self.dt),
                         (1 + frame // self.rate)*self.rate)

    def testDisablingOutputInScript(self):
        property = et.SubElement(self.run_tag, 'property')
        property.text = 'simulation/output/enabled'
        property.attrib['value'] = "0.0"
        self.tree.write('c1722_0.xml')

        self.fdm.load_script('c1722_0.xml')

        # Check that the output is disabled
        self.assertEqual(self.fdm["simulation/output/enabled"], 0.0)

        self.fdm.run_ic()
        self.fdm["simulation/output/enabled"] = 1.0

        for i in range(self.rate):
            self.fdm.run()

        output = pd.read_csv(self.output_file)

        # According to the settings, the output file must contain 1 line in
        # addition to the headers :
        # 1. The output after 'rate' iterations
        self.assertEqual(output['Time'].iloc[0],
                         self.fdm["simulation/sim-time-sec"])
예제 #55
0
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))
예제 #56
0
    def test_body_frame(self):
        fdm = CreateFDM(self.sandbox)
        aircraft_path = self.sandbox.path_to_jsbsim_file('aircraft')
        fdm.load_model('f16')

        aircraft_path = os.path.join(aircraft_path, 'f16')
        fdm.load_ic(os.path.join(aircraft_path, 'reset00.xml'), False)
        fdm.run_ic()

        self.assertAlmostEqual(fdm['external_reactions/pushback/location-x-in'],
                               -2.98081)
        self.assertAlmostEqual(fdm['external_reactions/pushback/location-y-in'],
                               0.0)
        self.assertAlmostEqual(fdm['external_reactions/pushback/location-z-in'],
                               -1.9683)
        self.assertAlmostEqual(fdm['external_reactions/pushback/x'], 1.0)
        self.assertAlmostEqual(fdm['external_reactions/pushback/y'], 0.0)
        self.assertAlmostEqual(fdm['external_reactions/pushback/z'], 0.0)
        self.assertAlmostEqual(fdm['external_reactions/pushback/magnitude'],
                               0.0)

        self.assertAlmostEqual(fdm['external_reactions/hook/location-x-in'],
                               100.669)
        self.assertAlmostEqual(fdm['external_reactions/hook/location-y-in'],
                               0.0)
        self.assertAlmostEqual(fdm['external_reactions/hook/location-z-in'],
                               -28.818)
        dx = -0.9995
        dz = 0.01
        fhook = np.array([dx, 0.0, dz])
        fhook /= np.linalg.norm(fhook)
        
        self.assertAlmostEqual(fdm['external_reactions/hook/x'], fhook[0])
        self.assertAlmostEqual(fdm['external_reactions/hook/y'], fhook[1])
        self.assertAlmostEqual(fdm['external_reactions/hook/z'], fhook[2])
        self.assertAlmostEqual(fdm['external_reactions/hook/magnitude'], 0.0)

        self.assertAlmostEqual(fdm['forces/fbx-external-lbs'], 0.0)
        self.assertAlmostEqual(fdm['forces/fby-external-lbs'], 0.0)
        self.assertAlmostEqual(fdm['forces/fbz-external-lbs'], 0.0)
        self.assertAlmostEqual(fdm['moments/l-external-lbsft'], 0.0)
        self.assertAlmostEqual(fdm['moments/m-external-lbsft'], 0.0)
        self.assertAlmostEqual(fdm['moments/n-external-lbsft'], 0.0)

        # Check the 'pushback' external force alone
        fdm['/sim/model/pushback/position-norm'] = 1.0
        fdm['/sim/model/pushback/target-speed-fps'] = 1.0
        fdm['/sim/model/pushback/kp'] = 0.05
        fdm.run()

        fpb = np.array([1.0, 0.0, 0.0]) * 0.05
        self.assertAlmostEqual(fdm['external_reactions/pushback/magnitude'],
                               0.05)
        self.assertAlmostEqual(fdm['forces/fbx-external-lbs'], fpb[0])
        self.assertAlmostEqual(fdm['forces/fby-external-lbs'], fpb[1])
        self.assertAlmostEqual(fdm['forces/fbz-external-lbs'], fpb[2])

        m = np.cross(self.getLeverArm(fdm, 'pushback'), fpb)
        self.assertAlmostEqual(fdm['moments/l-external-lbsft'], m[0])
        self.assertAlmostEqual(fdm['moments/m-external-lbsft'], m[1])
        self.assertAlmostEqual(fdm['moments/n-external-lbsft'], m[2])

        # Reset the 'pushback' external force to zero
        fdm['/sim/model/pushback/position-norm'] = 0.0
        fdm.run()
        self.assertAlmostEqual(fdm['external_reactions/pushback/magnitude'], 0.0)
        self.assertAlmostEqual(fdm['forces/fbx-external-lbs'], 0.0)
        self.assertAlmostEqual(fdm['forces/fby-external-lbs'], 0.0)
        self.assertAlmostEqual(fdm['forces/fbz-external-lbs'], 0.0)
        self.assertAlmostEqual(fdm['moments/l-external-lbsft'], 0.0)
        self.assertAlmostEqual(fdm['moments/m-external-lbsft'], 0.0)
        self.assertAlmostEqual(fdm['moments/n-external-lbsft'], 0.0)

        # Check the 'hook' external force alone
        fdm['external_reactions/hook/magnitude'] = 10.0
        fhook *= 10.0
        fdm.run()
        self.assertAlmostEqual(fdm['forces/fbx-external-lbs'], fhook[0])
        self.assertAlmostEqual(fdm['forces/fby-external-lbs'], fhook[1])
        self.assertAlmostEqual(fdm['forces/fbz-external-lbs'], fhook[2])

        m = np.cross(self.getLeverArm(fdm, 'hook'), fhook)
        self.assertAlmostEqual(fdm['moments/l-external-lbsft'], m[0])
        self.assertAlmostEqual(fdm['moments/m-external-lbsft'], m[1])
        self.assertAlmostEqual(fdm['moments/n-external-lbsft'], m[2])

        # Add the 'pushback' force to the hook force and check that the global
        # external forces is the sum of the push back force and the hook force.
        fdm['/sim/model/pushback/position-norm'] = 1.0
        fdm.run()
        fp = fdm['systems/pushback/force']
        fpb = np.array([1.0, 0.0, 0.0]) * fp
        f = fhook + fpb
        self.assertAlmostEqual(fdm['external_reactions/pushback/magnitude'], fp)
        self.assertAlmostEqual(fdm['forces/fbx-external-lbs'], f[0])
        self.assertAlmostEqual(fdm['forces/fby-external-lbs'], f[1])
        self.assertAlmostEqual(fdm['forces/fbz-external-lbs'], f[2])

        # Modify the push back force direction and check that the global external
        # force is modified accordingly.
        fdm['external_reactions/pushback/x'] = 1.5
        fdm['external_reactions/pushback/y'] = 0.1
        fdm.run()
        fp = fdm['systems/pushback/force']
        fpb = np.array([1.5, 0.1, 0.0]) * fp
        f = fhook + fpb
        self.assertAlmostEqual(fdm['external_reactions/pushback/magnitude'], fp)
        self.assertAlmostEqual(fdm['forces/fbx-external-lbs'], f[0])
        self.assertAlmostEqual(fdm['forces/fby-external-lbs'], f[1])
        self.assertAlmostEqual(fdm['forces/fbz-external-lbs'], f[2])

        m = (np.cross(self.getLeverArm(fdm, 'pushback'), fpb)
             + np.cross(self.getLeverArm(fdm, 'hook'), fhook))
        self.assertAlmostEqual(fdm['moments/l-external-lbsft'], m[0])
        self.assertAlmostEqual(fdm['moments/m-external-lbsft'], m[1])
        self.assertAlmostEqual(fdm['moments/n-external-lbsft'], m[2])

        fdm['external_reactions/hook/location-y-in'] = 50.0
        fdm.run()
        fp = fdm['systems/pushback/force']
        fpb = np.array([1.5, 0.1, 0.0]) * fp
        f = fhook + fpb
        self.assertAlmostEqual(fdm['external_reactions/pushback/magnitude'], fp)
        self.assertAlmostEqual(fdm['forces/fbx-external-lbs'], f[0])
        self.assertAlmostEqual(fdm['forces/fby-external-lbs'], f[1])
        self.assertAlmostEqual(fdm['forces/fbz-external-lbs'], f[2])

        m = (np.cross(self.getLeverArm(fdm, 'pushback'), fpb)
             + np.cross(self.getLeverArm(fdm, 'hook'), fhook))
        self.assertAlmostEqual(fdm['moments/l-external-lbsft'], m[0])
        self.assertAlmostEqual(fdm['moments/m-external-lbsft'], m[1])
        self.assertAlmostEqual(fdm['moments/n-external-lbsft'], m[2])
예제 #57
0
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))