.. 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>`_