.. DO NOT EDIT. .. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY. .. TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE: .. "nesc_test_cases/nesc_case15.py" .. LINE NUMBERS ARE GIVEN BELOW. .. only:: html .. note:: :class: sphx-glr-download-link-note :ref:`Go to the end <sphx_glr_download_nesc_test_cases_nesc_case15.py>` to download the full example code. .. rst-class:: sphx-glr-example-title .. _sphx_glr_nesc_test_cases_nesc_case15.py: =================================================== Case 15: Circular F-16 flight around North Pole =================================================== ============== =============== Verifies Propagation, geodetic transforms Gravitation J2 Geodesy WGS-84 rotating Atmosphere US 1976 STD Winds still air Vehicle F-16 with circumnavigating auto-pilot Notes Initially straight & level and engage auto-pilot ============== =============== .. GENERATED FROM PYTHON SOURCE LINES 17-151 .. code-block:: Python from simupy import systems from simupy.block_diagram import BlockDiagram import os import numpy as np from scipy import interpolate import matplotlib.pyplot as plt from nesc_testcase_helper import ( get_baselines, plot_nesc_comparisons, plot_F16_controls, nesc_options, nesc_colors, benchmark, ) from nesc_testcase_helper import ft_per_m from nesc_case11 import ( int_opts, BD, earth, rho_0, eval_trim, run_trimmer, knots_per_mps, ) import F16_model from F16_gnc import F16_gnc, trimmedKEAS F16_vehicle = F16_model.F16() spec_ic_args = dict( phi_D=89.95 * np.pi / 180, # latitude lamda_D=-45 * np.pi / 180, # longitude h=10_000 / ft_per_m, V_N=0.0 / ft_per_m, V_E=563.643 / ft_per_m, V_D=0.0 / ft_per_m, psi=90.0 * np.pi / 180, theta=0.0 * np.pi / 180, phi=0.0 * np.pi / 180, p_B=0.0 * np.pi / 180, q_B=0.0 * np.pi / 180, r_B=0.0 * np.pi / 180, ) earth_output_for_gnc_select = np.array( [ earth.phi_D_idx, earth.lamda_D_idx, earth.h_D_idx, earth.V_T_idx, earth.alpha_idx, earth.beta_idx, earth.psi_idx, earth.theta_idx, earth.phi_idx, earth.p_B_idx, earth.q_B_idx, earth.r_B_idx, earth.rho_idx, ] ) dim_feedback = len(earth_output_for_gnc_select) def get_gnc_function( throttleTrim, longStkTrim, keasCmd=trimmedKEAS, altCmd=spec_ic_args["h"] * ft_per_m, sasOn=True, apOn=True, circlePoleSW=True, ): def gnc_function(t, u): throttle, longStk, latStk, pedal = 0.0, 0.0, 0.0, 0.0 # pilot command ( latitude, longitude, alt, V_T, alpha, beta, psi, theta, phi, pb, qb, rb, # feedback rho, ) = u # rho to calculate equivalent airspeed Vequiv = V_T * np.sqrt(rho / rho_0) angles = np.array([latitude, longitude, alpha, beta, phi, theta, psi]) latitude, longitude, alpha, beta, phi, theta, psi = angles * 180 / np.pi control_eart = F16_gnc( throttle, longStk, latStk, pedal, sasOn, apOn, circlePoleSW, latitude, longitude, keasCmd, altCmd, alt * ft_per_m, Vequiv * knots_per_mps, alpha, beta, phi, theta, psi, pb, qb, rb, throttleTrim, longStkTrim, ) return control_eart return gnc_function int_opts["nsteps"] = 100_000 .. GENERATED FROM PYTHON SOURCE LINES 152-290 .. code-block:: Python if __name__ == "__main__": opt_args, opt_ctrl = run_trimmer( spec_ic_args, throttle_ic=0.0, longStk_ic=0.0, allow_roll=False ) trimmed_flight_condition = earth.ic_from_planetodetic(**opt_args) trimmed_KEAS = ( earth.output_equation_function(0, trimmed_flight_condition)[earth.V_T_idx] * np.sqrt( earth.output_equation_function(0, trimmed_flight_condition)[earth.rho_idx] / rho_0 ) * knots_per_mps ) earth.initial_condition = trimmed_flight_condition gnc_block = systems.SystemFromCallable( get_gnc_function( *opt_ctrl, keasCmd=trimmed_KEAS, ), dim_feedback, 4, ) BD = BlockDiagram(earth, F16_vehicle, gnc_block) BD.connect(earth, F16_vehicle, inputs=np.arange(earth.dim_output)) BD.connect(F16_vehicle, earth, inputs=np.arange(F16_vehicle.dim_output)) BD.connect( gnc_block, F16_vehicle, inputs=np.arange(earth.dim_output, earth.dim_output + 4), ) BD.connect(earth, gnc_block, outputs=earth_output_for_gnc_select) with benchmark() as b: res = BD.simulate(180, integrator_options=int_opts) plot_nesc_comparisons(res, "15") plot_F16_controls(res, "15", y_idx_offset=0) def xy_for_north_pole_ground_track(lat, long): xx = (90 - lat * 180 / np.pi) * np.cos(long) yy = (90 - lat * 180 / np.pi) * np.sin(long) return xx, yy plt.subplots(constrained_layout=True) plt.axis("equal") sim_lat = res.y[:, earth.phi_D_idx] sim_long = res.y[:, earth.lamda_D_idx] # refence_lats = np.array([90.0, 90-0.02, 90-0.04, 90-0.06])*np.pi/180 refence_lats = (90 - np.arange(5) / 60) * np.pi / 180 reference_longs = np.arange(0, 360, 30) * np.pi / 180 ref_steps = 100 ref_lag_long_list = [] for i in range(len(refence_lats)): ref_lag_long_list.append( (refence_lats[i], np.arange(ref_steps + 1) * 2 * np.pi / ref_steps) ) for j in range(len(reference_longs)): ref_lag_long_list.append( ((90 - np.arange(5) / 60) * np.pi / 180, reference_longs[j]) ) for lat, long in ref_lag_long_list: plt.plot(*xy_for_north_pole_ground_track(lat, long), "k--", alpha=0.25) baseline_pds, baseline_pd_labels = get_baselines("15") plt.plot( *xy_for_north_pole_ground_track(sim_lat, sim_long), "k-", alpha=1.0, label="SimuPy", ) plt.plot( *xy_for_north_pole_ground_track(sim_lat[0], sim_long[0]), "o", alpha=0.5, markerfacecolor="None", markeredgecolor="k", ) plt.plot( *xy_for_north_pole_ground_track(sim_lat[-1], sim_long[-1]), "x", alpha=0.5, markerfacecolor="None", markeredgecolor="k", ) for baseline_idx, baseline_pd in enumerate(baseline_pds): plt.plot( *xy_for_north_pole_ground_track( *(baseline_pd[["latitude_deg", "longitude_deg"]] * np.pi / 180).values.T ), nesc_colors[baseline_pd_labels[baseline_idx]], alpha=0.5, label="NESC %s" % (baseline_pd_labels[baseline_idx]), ) plt.plot( *xy_for_north_pole_ground_track( *( baseline_pd[["latitude_deg", "longitude_deg"]].iloc[0] * np.pi / 180 ).values.T ), "o", alpha=0.5, markerfacecolor="None", markeredgecolor=nesc_colors[baseline_pd_labels[baseline_idx]], ) plt.plot( *xy_for_north_pole_ground_track( *( baseline_pd[["latitude_deg", "longitude_deg"]].iloc[-1] * np.pi / 180 ).values.T ), "x", alpha=0.5, markerfacecolor="None", markeredgecolor=nesc_colors[baseline_pd_labels[baseline_idx]], ) plt.legend() if nesc_options["interactive_mode"]: plt.show() else: plt.savefig( os.path.join(nesc_options["save_relative_path"], "15_groundtrack.pdf") ) .. rst-class:: sphx-glr-horizontal * .. image-sg:: /nesc_test_cases/images/sphx_glr_nesc_case15_001.png :alt: nesc case15 :srcset: /nesc_test_cases/images/sphx_glr_nesc_case15_001.png :class: sphx-glr-multi-img * .. image-sg:: /nesc_test_cases/images/sphx_glr_nesc_case15_002.png :alt: nesc case15 :srcset: /nesc_test_cases/images/sphx_glr_nesc_case15_002.png :class: sphx-glr-multi-img * .. image-sg:: /nesc_test_cases/images/sphx_glr_nesc_case15_003.png :alt: nesc case15 :srcset: /nesc_test_cases/images/sphx_glr_nesc_case15_003.png :class: sphx-glr-multi-img * .. image-sg:: /nesc_test_cases/images/sphx_glr_nesc_case15_004.png :alt: nesc case15 :srcset: /nesc_test_cases/images/sphx_glr_nesc_case15_004.png :class: sphx-glr-multi-img * .. image-sg:: /nesc_test_cases/images/sphx_glr_nesc_case15_005.png :alt: nesc case15 :srcset: /nesc_test_cases/images/sphx_glr_nesc_case15_005.png :class: sphx-glr-multi-img * .. image-sg:: /nesc_test_cases/images/sphx_glr_nesc_case15_006.png :alt: nesc case15 :srcset: /nesc_test_cases/images/sphx_glr_nesc_case15_006.png :class: sphx-glr-multi-img * .. image-sg:: /nesc_test_cases/images/sphx_glr_nesc_case15_007.png :alt: nesc case15 :srcset: /nesc_test_cases/images/sphx_glr_nesc_case15_007.png :class: sphx-glr-multi-img * .. image-sg:: /nesc_test_cases/images/sphx_glr_nesc_case15_008.png :alt: nesc case15 :srcset: /nesc_test_cases/images/sphx_glr_nesc_case15_008.png :class: sphx-glr-multi-img * .. image-sg:: /nesc_test_cases/images/sphx_glr_nesc_case15_009.png :alt: nesc case15 :srcset: /nesc_test_cases/images/sphx_glr_nesc_case15_009.png :class: sphx-glr-multi-img * .. image-sg:: /nesc_test_cases/images/sphx_glr_nesc_case15_010.png :alt: nesc case15 :srcset: /nesc_test_cases/images/sphx_glr_nesc_case15_010.png :class: sphx-glr-multi-img * .. image-sg:: /nesc_test_cases/images/sphx_glr_nesc_case15_011.png :alt: nesc case15 :srcset: /nesc_test_cases/images/sphx_glr_nesc_case15_011.png :class: sphx-glr-multi-img * .. image-sg:: /nesc_test_cases/images/sphx_glr_nesc_case15_012.png :alt: nesc case15 :srcset: /nesc_test_cases/images/sphx_glr_nesc_case15_012.png :class: sphx-glr-multi-img .. rst-class:: sphx-glr-script-out .. code-block:: none Optimization terminated successfully. Current function value: 5.307430 Iterations: 260 Function evaluations: 539 pitch: 2.6742e+00 roll: 0.0000e+00 longStk: 13.0082 throttle: 13.8357 accelerations: [[-5.30742973e+00 -3.13605581e-08 -5.16943720e-08] [-6.38762633e-07 8.60861093e-08 5.56269331e-09]] time to simulate: 499.532 s .. rst-class:: sphx-glr-timing **Total running time of the script:** (8 minutes 26.644 seconds) .. _sphx_glr_download_nesc_test_cases_nesc_case15.py: .. only:: html .. container:: sphx-glr-footer sphx-glr-footer-example .. container:: sphx-glr-download sphx-glr-download-jupyter :download:`Download Jupyter notebook: nesc_case15.ipynb <nesc_case15.ipynb>` .. container:: sphx-glr-download sphx-glr-download-python :download:`Download Python source code: nesc_case15.py <nesc_case15.py>` .. container:: sphx-glr-download sphx-glr-download-zip :download:`Download zipped: nesc_case15.zip <nesc_case15.zip>` .. only:: html .. rst-class:: sphx-glr-signature `Gallery generated by Sphinx-Gallery <https://sphinx-gallery.github.io>`_