Source code for BSK_MultiSatPlotting

#
#  ISC License
#
#  Copyright (c) 2021, Autonomous Vehicle Systems Lab, University of Colorado at Boulder
#
#  Permission to use, copy, modify, and/or distribute this software for any
#  purpose with or without fee is hereby granted, provided that the above
#  copyright notice and this permission notice appear in all copies.
#
#  THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
#  WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
#  MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
#  ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
#  WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
#  ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
#  OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#
import matplotlib.pyplot as plt
import numpy as np
from Basilisk.utilities import macros
from Basilisk.utilities import unitTestSupport

# --------------------------------- COMPONENTS & SUBPLOT HANDLING ----------------------------------------------- #

def show_all_plots():
    plt.show()

def clear_all_plots():
    plt.close("all")

def save_all_plots(fileName, figureNames):
    figureList = {}
    numFigures = len(figureNames)
    for i in range(0, numFigures):
        pltName = fileName + "_" + figureNames[i]
        figureList[pltName] = plt.figure(i+1)
    return figureList

# ------------------------------------- MAIN PLOT HANDLING ------------------------------------------------------ #
color_x = 'dodgerblue'
color_y = 'salmon'
color_z = 'lightgreen'
m2km = 1.0 / 1000.0

[docs]def plot_attitude(timeData, dataSigmaBN, id=None): """Plot the spacecraft attitude.""" plt.figure(id) for idx in range(3): plt.plot(timeData, dataSigmaBN[:, idx], color=unitTestSupport.getLineColor(idx, 3), label=r'$\sigma_' + str(idx+1) + '$') plt.legend(loc='lower right') plt.xlabel('Time [min]') plt.ylabel(r'Attitude $\sigma_{B/N}$') return
[docs]def plot_attitude_error(timeData, dataSigmaBR, id=None): """Plot the spacecraft attitude error.""" plt.figure(id) for idx in range(3): plt.plot(timeData, dataSigmaBR[:, idx], color=unitTestSupport.getLineColor(idx, 3), label=r'$\sigma_' + str(idx+1) + '$') plt.legend(loc='lower right') plt.xlabel('Time [min]') plt.ylabel(r'Attitude Tracking Error $\sigma_{B/R}$') return
[docs]def plot_attitude_reference(timeData, dataSigmaRN, id=None): """Plot the spacecraft attitude reference.""" plt.figure(id) for idx in range(3): plt.plot(timeData, dataSigmaRN[:, idx], color=unitTestSupport.getLineColor(idx, 3), label=r'$\sigma_' + str(idx+1) + '$') plt.legend(loc='lower right') plt.xlabel('Time [min]') plt.ylabel(r'Attitude Reference $\sigma_{R/N}$') return
[docs]def plot_rate(timeData, dataOmegaBN, id=None): """Plot the body angular velocity rate tracking errors.""" plt.figure(id) for idx in range(3): plt.plot(timeData, dataOmegaBN[:, idx], color=unitTestSupport.getLineColor(idx, 3), label=r'$\omega_{BN,' + str(idx+1) + '}$') plt.legend(loc='lower right') plt.xlabel('Time [min]') plt.ylabel('Angular Rate (rad/s)') return
[docs]def plot_rate_error(timeData, dataOmegaBR, id=None): """Plot the body angular velocity rate tracking errors.""" plt.figure(id) for idx in range(3): plt.plot(timeData, dataOmegaBR[:, idx], color=unitTestSupport.getLineColor(idx, 3), label=r'$\omega_{BR,' + str(idx+1) + '}$') plt.legend(loc='lower right') plt.xlabel('Time [min]') plt.ylabel('Rate Tracking Error (rad/s)') return
[docs]def plot_rate_reference(timeData, dataOmegaRN, id=None): """Plot the body angular velocity rate reference.""" plt.figure(id) for idx in range(3): plt.plot(timeData, dataOmegaRN[:, idx], color=unitTestSupport.getLineColor(idx, 3), label=r'$\omega_{RN,' + str(idx+1) + '}$') plt.legend(loc='lower right') plt.xlabel('Time [min]') plt.ylabel('Reference Rate (rad/s)') return
[docs]def plot_rw_motor_torque(timeData, dataUsReq, dataRW, numRW, id=None): """Plot the RW motor torques.""" plt.figure(id) for idx in range(numRW): plt.plot(timeData, dataUsReq[:, idx], '--', color=unitTestSupport.getLineColor(idx, numRW), label=r'$\hat u_{s,' + str(idx+1) + '}$') plt.plot(timeData, dataRW[idx], color=unitTestSupport.getLineColor(idx, numRW), label='$u_{s,' + str(idx+1) + '}$') plt.legend(loc='lower right') plt.xlabel('Time [min]') plt.ylabel('RW Motor Torque (Nm)') return
[docs]def plot_rw_speeds(timeData, dataOmegaRW, numRW, id=None): """Plot the RW spin rates.""" plt.figure(id) for idx in range(numRW): plt.plot(timeData, dataOmegaRW[:, idx] / macros.RPM, color=unitTestSupport.getLineColor(idx, numRW), label=r'$\Omega_{' + str(idx+1) + '}$') plt.legend(loc='lower right') plt.xlabel('Time [min]') plt.ylabel('RW Speed (RPM) ') return
[docs]def plot_rw_voltages(timeData, dataVolt, numRW, id=None): """Plot the RW voltage inputs.""" plt.figure(id) for idx in range(numRW): plt.plot(timeData, dataVolt[:, idx], color=unitTestSupport.getLineColor(idx, numRW), label='$V_{' + str(idx+1) + '}$') plt.legend(loc='lower right') plt.xlabel('Time [min]') plt.ylabel('RW Voltage (V)') return
[docs]def plot_rw_power(timeData, dataRwPower, numRW, id=None): """Plot the RW power drain.""" plt.figure(id) for idx in range(numRW): plt.plot(timeData, dataRwPower[idx], color=unitTestSupport.getLineColor(idx, numRW), label='$p_{rw,' + str(idx+1) + '}$') plt.legend(loc='lower right') plt.xlabel('Time [min]') plt.ylabel('RW Power (W)') return
[docs]def plot_power(timeData, netData, supplyData, sinkData, id=None): """Plot the power inputs and outputs""" plt.figure(id) plt.plot(timeData, netData, label='Net Power') plt.plot(timeData, supplyData, label='Panel Power') plt.plot(timeData, sinkData, label='Power Draw') plt.xlabel('Time [min]') plt.ylabel('Power [W]') plt.grid(True) plt.legend(loc='lower right') return
[docs]def plot_battery(timeData, storageData, id=None): """Plot the energy inside the onboard battery""" plt.figure(id) plt.plot(timeData, storageData) plt.xlabel('Time [min]') plt.ylabel('Stored Energy [W-s]') return
[docs]def plot_rw_temperature(timeData, tempData, numRW, id=None): """Plot the reaction wheel temperatures""" plt.figure(id) for idx in range(numRW): plt.plot(timeData, tempData[idx], color=unitTestSupport.getLineColor(idx, numRW), label='$T_{rw,' + str(idx+1) + '}$') plt.legend(loc='lower right') plt.xlabel('Time [min]') plt.ylabel('RW Temperatures [ÂșC]') return
[docs]def plot_thrust(timeData, thrustData, numThr, id=None): """Plot the thrusters net force output""" plt.figure(id) for idx in range(numThr): plt.plot(timeData, thrustData[idx], color=unitTestSupport.getLineColor(idx, numThr), label='$F_{thr,' + str(idx + 1) + '}$') plt.legend(loc='lower right') plt.xlabel('Time [min]') plt.ylabel('Thrust [N]') return
[docs]def plot_thrust_percentage(timeData, thrustData, numThr, id=None): """Plot the thrust as a percentage of maximum""" plt.figure(id) for idx in range(numThr): plt.plot(timeData, thrustData[idx], color=unitTestSupport.getLineColor(idx, numThr), label='$F_{thr,' + str(idx + 1) + '}$') plt.legend(loc='lower right') plt.ylim([0, 1.1]) plt.xlabel('Time [min]') plt.ylabel('Thrust Percentage') return
[docs]def plot_fuel(timeData, fuelData, id=None): """Plot the fuel mass information""" plt.figure(id) plt.plot(timeData, fuelData) plt.xlabel('Time [min]') plt.ylabel('Stored Fuel Mass [kg]') return
[docs]def plot_orbit(r_BN, id=None): """Plot the spacecraft inertial orbitS.""" plt.figure(id, figsize=(6, 5)) ax = plt.axes(projection='3d') ax.plot(r_BN[:, 0] * m2km, r_BN[:, 1] * m2km, r_BN[:, 2] * m2km, label="Spacecraft") ax.set_xlim3d(-8000, 8000) ax.set_ylim3d(-8000, 8000) ax.set_zlim3d(-8000, 8000) ax.scatter(0, 0, 0, c=color_x) ax.set_title('Spacecraft Inertial Orbit') ax.set_xlabel('x [km]') ax.set_ylabel('y [km]') ax.set_zlabel('z [km]') ax.legend(loc=2) return
[docs]def plot_orbits(r_BN, numberSpacecraft, id=None): """Plot the spacecraft inertial orbits.""" plt.figure(id, figsize=(6, 5)) ax = plt.axes(projection='3d') for i in range(numberSpacecraft): ax.plot(r_BN[i][:, 0] * m2km, r_BN[i][:, 1] * m2km, r_BN[i][:, 2] * m2km, label="Spacecraft " + str(i), c=unitTestSupport.getLineColor(i, numberSpacecraft)) ax.set_xlim3d(-8000, 8000) ax.set_ylim3d(-8000, 8000) ax.set_zlim3d(-8000, 8000) ax.scatter(0, 0, 0, c=color_x) ax.set_title('Spacecraft Inertial Orbits') ax.set_xlabel('x [km]') ax.set_ylabel('y [km]') ax.set_zlabel('z [km]') ax.legend(loc=2) return
[docs]def plot_relative_orbits(r_BN, numberSpacecraft, id=None): """Plot the spacecraft inertial orbits.""" plt.figure(id, figsize=(6, 5)) ax = plt.axes(projection='3d') for i in range(numberSpacecraft): ax.plot(r_BN[i][:, 0] * m2km, r_BN[i][:, 1] * m2km, r_BN[i][:, 2] * m2km, label="Spacecraft " + str(i), c=unitTestSupport.getLineColor(i, numberSpacecraft)) ax.set_box_aspect((np.ptp(r_BN[i][:, 0]), np.ptp(r_BN[i][:, 1]), np.ptp(r_BN[i][:, 2]))) ax.scatter(0, 0, 0, c=color_x) ax.set_title('Spacecraft Relative Orbits in Hill Frame') ax.set_xlabel('$i_r$ [km]') ax.set_ylabel(r'$i_{\theta}$ [km]') ax.set_zlabel('$i_h$ [km]') ax.legend(loc=2) return
[docs]def plot_orbital_element_differences(timeData, oed, id=None): """Plot the orbital element difference between the chief and another spacecraft.""" plt.figure(id) plt.plot(timeData, oed[:, 0], label="da") plt.plot(timeData, oed[:, 1], label="de") plt.plot(timeData, oed[:, 2], label="di") plt.plot(timeData, oed[:, 3], label="dOmega") plt.plot(timeData, oed[:, 4], label="domega") plt.plot(timeData, oed[:, 5], label="dM") plt.legend() plt.xlabel("time [orbit]") plt.ylabel("Orbital Element Difference")