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)
def setUp(self): self.sandbox = SandBox() script_path = self.sandbox.path_to_jsbsim_file('scripts', 'c1722.xml') # The aircraft c172x does not contain an <input> tag so we need # to add one. tree, aircraft_name, b = CopyAircraftDef(script_path, self.sandbox) self.root = tree.getroot() input_tag = et.SubElement(self.root, 'input') input_tag.attrib['port']='1137' tree.write(self.sandbox('aircraft', aircraft_name, aircraft_name+'.xml')) self.fdm = CreateFDM(self.sandbox) self.fdm.set_aircraft_path('aircraft') self.fdm.load_script(script_path) self.fdm.run_ic() self.fdm.hold() # Execute JSBSim in a separate thread self.cond = threading.Condition() self.thread = JSBSimThread(self.fdm, self.cond, 5., time.time()) self.thread.start() # Wait for the thread to be started before connecting a telnet session self.cond.acquire() self.cond.wait() self.tn = telnetlib.Telnet("localhost", 1137) self.cond.release()
def test_CAS_ic(self): script_name = 'Short_S23_3.xml' script_path = self.sandbox.path_to_jsbsim_file('scripts', script_name) # Add a Pitot angle to the Short S23 tree, aircraft_name, path_to_jsbsim_aircrafts = CopyAircraftDef(script_path, self.sandbox) self.addPitotTube(tree.getroot(), 5.0) tree.write(self.sandbox('aircraft', aircraft_name, aircraft_name+'.xml')) # Read the CAS specified in the IC file tree = et.parse(script_path) use_element = tree.getroot().find('use') IC_file = use_element.attrib['initialize'] tree = et.parse(os.path.join(path_to_jsbsim_aircrafts, append_xml(IC_file))) vc_tag = tree.getroot().find('./vc') VCAS = float(vc_tag.text) if 'unit' in vc_tag.attrib and vc_tag.attrib['unit'] == 'FT/SEC': VCAS /= 1.68781 # Converts in kts # Run the IC and check that the model is initialized correctly fdm = CreateFDM(self.sandbox) fdm.set_aircraft_path('aircraft') fdm.load_script(script_path) fdm.run_ic() self.assertAlmostEqual(fdm['ic/vc-kts'], VCAS, delta=1E-7) self.assertAlmostEqual(fdm['velocities/vc-kts'], VCAS, delta=1E-7)
def setUp(self): JSBSimTestCase.setUp(self) self.script_path = self.sandbox.path_to_jsbsim_file('scripts', 'c1724.xml') # Since we will alter the aircraft definition file, we need make a copy # of it and of all the files it is refering to. self.tree, self.aircraft_name, self.path_to_jsbsim_aircrafts = CopyAircraftDef(self.script_path, self.sandbox)
def test_fuel_tanks_inertia(self): script_path = self.sandbox.path_to_jsbsim_file('scripts', 'c1722.xml') # The aircraft c172x does not contain an <inertia_factor> tag so we need # to add one. tree, aircraft_name, b = CopyAircraftDef(script_path, self.sandbox) tank_tag = tree.getroot().find('./propulsion/tank') inertia_factor = et.SubElement(tank_tag, 'inertia_factor') inertia_factor.text = '1.0' 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() contents0 = fdm.get_property_value('propulsion/tank/contents-lbs') ixx0 = fdm.get_property_value('propulsion/tank/local-ixx-slug_ft2') iyy0 = fdm.get_property_value('propulsion/tank/local-iyy-slug_ft2') izz0 = fdm.get_property_value('propulsion/tank/local-izz-slug_ft2') # Remove half of the tank contents and check that the inertias are # updated accordingly fdm.set_property_value('propulsion/tank/contents-lbs', 0.5*contents0) contents = fdm.get_property_value('propulsion/tank/contents-lbs') ixx = fdm.get_property_value('propulsion/tank/local-ixx-slug_ft2') iyy = fdm.get_property_value('propulsion/tank/local-iyy-slug_ft2') izz = fdm.get_property_value('propulsion/tank/local-izz-slug_ft2') self.assertTrue(abs(contents-0.5*contents0) < 1E-7, msg="The tank content (%f lbs) should be %f lbs" % (contents, 0.5*contents0)) self.assertTrue(abs(ixx-0.5*ixx0) < 1E-7, msg="The tank inertia Ixx (%f slug*ft^2) should be %f slug*ft^2" % (ixx, 0.5*ixx0)) self.assertTrue(abs(iyy-0.5*iyy0) < 1E-7, msg="The tank inertia Iyy (%f slug*ft^2) should be %f slug*ft^2" % (iyy, 0.5*iyy0)) self.assertTrue(abs(izz-0.5*izz0) < 1E-7, msg="The tank inertia Izz (%f slug*ft^2) should be %f slug*ft^2" % (izz, 0.5*izz0)) # Execute the script and check that the fuel inertias have been updated # along with the consumption. ExecuteUntil(fdm, 200.0) contents = fdm.get_property_value('propulsion/tank/contents-lbs') ixx = fdm.get_property_value('propulsion/tank/local-ixx-slug_ft2') iyy = fdm.get_property_value('propulsion/tank/local-iyy-slug_ft2') izz = fdm.get_property_value('propulsion/tank/local-izz-slug_ft2') contents_ratio = contents / contents0 ixx_ratio = ixx / ixx0 iyy_ratio = iyy / iyy0 izz_ratio = izz / izz0 self.assertTrue(abs(contents_ratio - ixx_ratio) < 1E-7, msg="Ixx does not vary as the tank content does\nIxx ratio=%f\nContents ratio=%f" % (ixx_ratio, contents_ratio)) self.assertTrue(abs(contents_ratio - iyy_ratio) < 1E-7, msg="Iyy does not vary as the tank content does\nIyy ratio=%f\nContents ratio=%f" % (iyy_ratio, contents_ratio)) self.assertTrue(abs(contents_ratio - izz_ratio) < 1E-7, msg="Izz does not vary as the tank content does\nIzz ratio=%f\nContents ratio=%f" % (izz_ratio, contents_ratio))
def test_grain_tanks_content(self): script_path = self.sandbox.path_to_jsbsim_file('scripts', 'J2460.xml') tree, aircraft_name, b = CopyAircraftDef(script_path, self.sandbox) id = 0 for tank in tree.getroot().findall('propulsion/tank'): grain_config = tank.find('grain_config') if grain_config and grain_config.attrib['type'] == 'CYLINDRICAL': break ++id capacity = float(tank.find('capacity').text) tank.find('contents').text = str(0.5 * capacity) tree.write( self.sandbox('aircraft', aircraft_name, aircraft_name + '.xml')) radius_tag = tank.find('radius') radius = float(radius_tag.text) if 'unit' in radius_tag.attrib and radius_tag.attrib['unit'] == 'IN': radius /= 12.0 bore_diameter_tag = tank.find('grain_config/bore_diameter') bore_radius = 0.5 * float(bore_diameter_tag.text) if 'unit' in bore_diameter_tag.attrib and bore_diameter_tag.attrib[ 'unit'] == 'IN': bore_radius /= 12.0 fdm = CreateFDM(self.sandbox) fdm.set_aircraft_path('aircraft') fdm.load_script(script_path) fdm.run_ic() tank_name = 'propulsion/tank[%g]' % (id, ) self.assertAlmostEqual(fdm[tank_name + '/contents-lbs'], 0.5 * capacity) fdm['propulsion/tank/contents-lbs'] = capacity mass = capacity / 32.174049 # Converting lbs to slugs ixx = 0.5 * mass * (radius * radius + bore_radius * bore_radius) self.assertAlmostEqual(fdm[tank_name + 'local-ixx-slug_ft2'], ixx) del fdm tank.find('contents').text = '0.0' 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() self.assertAlmostEqual(fdm[tank_name + '/contents-lbs'], 0.0) fdm['propulsion/tank/contents-lbs'] = capacity
def test_steer_type(self): self.script_path = self.sandbox.path_to_jsbsim_file( 'scripts', 'c1721.xml') self.tree, self.aircraft_name, b = CopyAircraftDef( self.script_path, self.sandbox) root = self.tree.getroot() self.max_steer_tag = root.find('ground_reactions/contact/max_steer') # Check the fixed type self.max_steer_tag.text = '0.0' fdm = self.steerType(False, False, False) del fdm # Check the castered type self.max_steer_tag.text = '360.0' self.isCastered() # Check the steered type self.max_steer_tag.text = '10.0' fdm = self.steerType(True, False, False) fdm['fcs/steer-cmd-norm'] = 0.5 fdm.run() self.assertAlmostEqual(fdm['fcs/steer-pos-deg'], 5.0) del fdm bogey_tag = root.find('ground_reactions/contact//max_steer/..') castered_tag = et.SubElement(bogey_tag, 'castered') castered_tag.text = '1.0' # Check that the bogey is castered no matter what is the value # of <max_steer> self.max_steer_tag.text = '10.0' self.isCastered() self.max_steer_tag.text = '0.0' self.isCastered() self.max_steer_tag.text = '360.0' self.isCastered() # Check the fixed type castered_tag.text = '0.0' self.max_steer_tag.text = '0.0' fdm = self.steerType(False, False, False) del fdm # Check the steered type self.max_steer_tag.text = '10.0' self.isSteered() # Check the steered type with 360.0 self.max_steer_tag.text = '360.0' self.isSteered()
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 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])
def testIndependenceOfInitialLocation(self): script_path = self.sandbox.path_to_jsbsim_file('scripts/ball.xml') tree, aircraft_name, _ = CopyAircraftDef(script_path, self.sandbox) tree.write( self.sandbox('aircraft', aircraft_name, aircraft_name + '.xml')) # Alter the initial conditions XML file to force the initial latitude # to 90 degrees. _, IC_tree, IC_file = self.getElementTrees(script_path) IC_root = IC_tree.getroot() lat_tag = IC_root.find('latitude') psi_tag = IC_root.find('psi') alt_tag = IC_root.find('altitude') psi_tag.text = '90.0' # Heading East lat_tag.text = '89.9' # Above the North Pole h0 = float(alt_tag.text) IC_tree.write(os.path.join('aircraft', aircraft_name, IC_file)) fdm = self.create_fdm() fdm.set_aircraft_path('aircraft') self.load_script('ball.xml') fdm.run_ic() p = fdm['ic/p-rad_sec'] q = fdm['ic/q-rad_sec'] r = fdm['ic/r-rad_sec'] self.delete_fdm() # Since the equatorial radius is 70159 ft larger than the polar radius # we need to decrease the altitude by the same amount in order to # initialize the vehicle at the same radius. alt_tag.text = str(h0 - 70159) psi_tag.text = '0.0' # Heading North lat_tag.text = '0.0' # Above equator # Longitude at which the polar orbit tested above would cross the equator lon_tag = IC_root.find('longitude') lon_tag.text = '90.0' IC_tree.write(os.path.join('aircraft', aircraft_name, IC_file)) fdm = self.create_fdm() fdm.set_aircraft_path('aircraft') self.load_script('ball.xml') fdm.run_ic() self.assertAlmostEqual(fdm['ic/p-rad_sec'], p) self.assertAlmostEqual(fdm['ic/q-rad_sec'], q) self.assertAlmostEqual(fdm['ic/r-rad_sec'], r)
def testKinematicNoScale(self): # Test the <nocale/> feature script_path = self.sandbox.path_to_jsbsim_file('scripts', 'c1721.xml') tree, aircraft_name, b = CopyAircraftDef(script_path, self.sandbox) kinematic_tag = tree.getroot().find('flight_control/channel/kinematic') et.SubElement(kinematic_tag, 'noscale') tree.write( self.sandbox('aircraft', aircraft_name, aircraft_name + '.xml')) fdm = CreateFDM(self.sandbox) fdm.set_aircraft_path('aircraft') fdm.load_model(aircraft_name) fdm.load_ic('reset00', True) fdm.run_ic() fdm['fcs/flap-cmd-norm'] = 12. ExecuteUntil(fdm, 2.2) self.assertAlmostEqual(fdm['fcs/flap-pos-deg'], 12.)
def test_alt_mod_vs_CAS(self): script_name = 'Short_S23_3.xml' script_path = self.sandbox.path_to_jsbsim_file('scripts', script_name) # Add a Pitot angle to the Short S23 tree, aircraft_name, b = CopyAircraftDef(script_path, self.sandbox) self.addPitotTube(tree.getroot(), 10.0) tree.write(self.sandbox('aircraft', aircraft_name, aircraft_name+'.xml')) fdm = CreateFDM(self.sandbox) fdm.set_aircraft_path('aircraft') fdm.load_model('Short_S23') fdm['ic/beta-deg'] = 15.0 # Add some sideslip fdm['ic/vc-kts'] = 172.0 fdm['ic/h-sl-ft'] = 15000. self.assertAlmostEqual(fdm['ic/vc-kts'], 172.0, delta=1E-7) self.assertAlmostEqual(fdm['ic/beta-deg'], 15.0, delta=1E-7) fdm.run_ic() self.assertAlmostEqual(fdm['velocities/vc-kts'], 172.0, delta=1E-7) self.assertAlmostEqual(fdm['aero/beta-deg'], 15.0, delta=1E-7)
def test_trim_with_actuator_delay(self): # This is a regression test that checks that actuators delays are # disabled when the trim takes place (GitHub issue #293). script_path = self.sandbox.path_to_jsbsim_file('scripts', 'c1722.xml') aircraft_tree, aircraft_name, _ = CopyAircraftDef( script_path, self.sandbox) root = aircraft_tree.getroot() elevator_actuator = root.find( "flight_control/channel/actuator[@name='fcs/elevator-actuator']") delay = et.SubElement(elevator_actuator, 'delay') delay.text = '0.1' aircraft_tree.write( self.sandbox('aircraft', aircraft_name, aircraft_name + '.xml')) fdm = self.create_fdm() fdm.set_aircraft_path(self.sandbox('aircraft')) fdm.load_script(script_path) fdm.run_ic() while fdm.run(): if fdm['simulation/trim-completed'] == 1: break
def BuildReference(self, script_name): # Run the script self.script = self.sandbox.path_to_jsbsim_file('scripts', script_name) self.sandbox.delete_csv_files() fdm = CreateFDM(self.sandbox) fdm.set_output_directive( self.sandbox.path_to_jsbsim_file('tests', 'output.xml')) fdm.load_script(self.script) fdm['simulation/randomseed'] = 0.0 fdm.run_ic() ExecuteUntil(fdm, 50.0) self.ref = pd.read_csv("output.csv", index_col=0) # Since the script will work with modified versions of the aircraft XML # definition file, we need to make a copy of the directory that # contains all the input data of that aircraft tree, self.aircraft_name, self.path_to_jsbsim_aircrafts = CopyAircraftDef( self.script, self.sandbox) self.aircraft_path = os.path.join('aircraft', self.aircraft_name)
def test_trim_westward(self): # This is a regression test after the bug reported in GitHub issue #163 # which reports a trim failure when the heading is set to 270 degrees or # -90 degrees i.e. westward. script_path = self.sandbox.path_to_jsbsim_file('scripts', '737_cruise.xml') aircraft_tree, aircraft_name, b = CopyAircraftDef( script_path, self.sandbox) aircraft_tree.write( self.sandbox('aircraft', aircraft_name, aircraft_name + '.xml')) IC_file = self.sandbox('aircraft', aircraft_name, 'cruise_init.xml') tree = et.parse(IC_file) heading_el = tree.find('psi') heading_el.text = '270.0' tree.write(IC_file) fdm = self.create_fdm() fdm.set_aircraft_path(self.sandbox('aircraft')) fdm.load_script(script_path) fdm.run_ic() while fdm['simulation/sim-time-sec'] < 6.0: fdm.run()
def testNorthPoleInitialization(self): script_path = self.sandbox.path_to_jsbsim_file('scripts/ball.xml') tree, aircraft_name, _ = CopyAircraftDef(script_path, self.sandbox) tree.write( self.sandbox('aircraft', aircraft_name, aircraft_name + '.xml')) # Alter the initial conditions XML file to force the initial latitude # to 90 degrees. _, IC_tree, IC_file = self.getElementTrees(script_path) IC_root = IC_tree.getroot() lat_tag = IC_root.find('latitude') lat_tag.text = '90.0' IC_tree.write(os.path.join('aircraft', aircraft_name, IC_file)) fdm = self.create_fdm() fdm.set_aircraft_path('aircraft') fpectl.turnon_sigfpe() self.load_script('ball.xml') fdm.run_ic() self.assertAlmostEqual(fdm['ic/lat-gc-deg'], 90.) while fdm['simulation/sim-time-sec'] < 1.: fdm.run() fpectl.turnoff_sigfpe()
def AddAccelerometersToAircraft(self, script_path): tree, aircraft_name, b = CopyAircraftDef(script_path, self.sandbox) system_tag = et.SubElement(tree.getroot(), 'system') system_tag.attrib['file'] = 'accelerometers' tree.write( self.sandbox('aircraft', aircraft_name, aircraft_name + '.xml'))
def test_input_socket(self): # The aircraft c172x does not contain an <input> tag so we need # to add one. tree, aircraft_name, b = CopyAircraftDef(self.script_path, self.sandbox) self.root = tree.getroot() input_tag = et.SubElement(self.root, 'input') input_tag.attrib['port'] = '1137' tree.write( self.sandbox('aircraft', aircraft_name, aircraft_name + '.xml')) fdm = CreateFDM(self.sandbox) fdm.set_aircraft_path('aircraft') fdm.load_script(self.script_path) fdm.run_ic() fdm.hold() tn = TelnetInterface(fdm, 5., 1137) self.sanityCheck(tn) # Check the aircraft name and its version msg = string.split(tn.sendCommand("info"), '\n') self.assertEqual(string.strip(string.split(msg[2], ':')[1]), string.strip(self.root.attrib['name'])) self.assertEqual(string.strip(string.split(msg[1], ':')[1]), string.strip(self.root.attrib['version'])) # Check that the simulation time is 0.0 self.assertEqual(float(string.strip(string.split(msg[3], ':')[1])), 0.0) self.assertEqual(tn.getSimTime(), 0.0) self.assertEqual(tn.getPropertyValue("simulation/sim-time-sec"), 0.0) # Check that 'iterate' iterates the correct number of times tn.sendCommand("iterate 19") self.assertEqual(tn.getSimTime(), 19. * tn.getDeltaT()) self.assertAlmostEqual(tn.getPropertyValue("simulation/sim-time-sec"), tn.getSimTime(), delta=1E-5) # Wait a little bit and make sure that the simulation time has not # changed meanwhile thus confirming that the simulation is on hold. tn.wait(0.1) self.assertEqual(tn.getSimTime(), 19. * tn.getDeltaT()) self.assertAlmostEqual(tn.getPropertyValue("simulation/sim-time-sec"), tn.getSimTime(), delta=1E-5) # Modify the tank[0] contents via the "send" command half_contents = 0.5 * tn.getPropertyValue( "propulsion/tank/contents-lbs") tn.sendCommand("set propulsion/tank/contents-lbs " + str(half_contents)) self.assertEqual(tn.getPropertyValue("propulsion/tank/contents-lbs"), half_contents) # Check the resume/hold commands tn.setRealTime(True) t = tn.getSimTime() tn.sendCommand("resume") tn.wait(0.5) self.assertNotEqual(tn.getSimTime(), t) tn.wait(0.5) tn.sendCommand("hold") tn.setRealTime(False) t = tn.getSimTime() self.assertAlmostEqual(tn.getPropertyValue("simulation/sim-time-sec"), t, delta=1E-5) # Wait a little bit and make sure that the simulation time has not # changed meanwhile thus confirming that the simulation is on hold. tn.wait(0.1) self.assertEqual(tn.getSimTime(), t) self.assertAlmostEqual(tn.getPropertyValue("simulation/sim-time-sec"), t, delta=1E-5)
def test_point_mass_inertia(self): script_path = self.sandbox.path_to_jsbsim_file('scripts', 'J2460.xml') fdm = CreateFDM(self.sandbox) fdm.set_output_directive( self.sandbox.path_to_jsbsim_file('tests', 'output.xml')) fdm.load_script(script_path) fdm.run_ic() ExecuteUntil(fdm, 50.0) ref = pd.read_csv("output.csv", index_col=0) tree, aircraft_name, path_to_jsbsim_aircrafts = CopyAircraftDef( script_path, self.sandbox) pointmass_element = tree.getroot().find( 'mass_balance/pointmass//form/..') weight_element = pointmass_element.find('weight') weight = float(weight_element.text) form_element = pointmass_element.find('form') radius_element = form_element.find('radius') radius, length = (0.0, 0.0) if radius_element is not None: radius = float(radius_element.text) length_element = form_element.find('length') if length_element is not None: length = float(length_element.text) shape = form_element.attrib['shape'] pointmass_element.remove(form_element) inertia = np.zeros((3, 3)) if string.strip(shape) == 'tube': inertia[0, 0] = radius * radius inertia[1, 1] = (6.0 * inertia[0, 0] + length * length) / 12.0 inertia[2, 2] = inertia[1, 1] inertia = inertia * weight / 32.174049 # converting slugs to lbs ixx_element = et.SubElement(pointmass_element, 'ixx') ixx_element.text = str(inertia[0, 0]) iyy_element = et.SubElement(pointmass_element, 'iyy') iyy_element.text = str(inertia[1, 1]) izz_element = et.SubElement(pointmass_element, 'izz') izz_element.text = str(inertia[2, 2]) tree.write( self.sandbox('aircraft', aircraft_name, aircraft_name + '.xml')) # Because JSBSim internals use static pointers, we cannot rely on # Python garbage collector to decide when the FDM is destroyed # otherwise we can get dangling pointers. del fdm fdm = CreateFDM(self.sandbox) fdm.set_aircraft_path('aircraft') fdm.set_output_directive( self.sandbox.path_to_jsbsim_file('tests', 'output.xml')) fdm.load_script(script_path) fdm.run_ic() ExecuteUntil(fdm, 50.0) mod = pd.read_csv("output.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, mod)) # Find all the data that are differing by more than 1E-8 between the # two data sets. diff = FindDifferences(ref, mod, 1E-8) self.longMessage = True self.assertEqual(len(diff), 0, msg='\n' + diff.to_string())