Source code for latom.plots.timeseries

"""
@authors: Alberto FOSSA' Giuliana Elena MICELI

"""

import numpy as np
import matplotlib.pyplot as plt


[docs]class TwoDimStatesTimeSeries: """Plot the two-dimensional simulation's states in time. Parameters ---------- r : float Equatorial radius of central attracting body [m] or [-] time : ndarray Time vector for implicit NLP solution [s] or [-] states : ndarray States time series for implicit NLP solution as `[r, theta, u, v, m]` time_exp : ndarray or ``None``, optional Time vector for explicit simulation [s] o [-] or ``None``. Default is ``None`` states_exp : ndarray or ``None``, optional States time series for explicit simulation as `[r, theta, u, v, m]` or ``None``. Default is ``None`` thrust : ndarray or ``None`` Thrust time series [N] or [-] or ``None``. Default is ``None`` threshold : float or ``None``, optional Threshold value to determine the on/off control structure or ``None``. Default is ``1e-6`` r_safe : ndarray or ``None``, optional Time series for minimum safe altitude [m] or [-] or ``None``. Default is ``None`` threshold : float The threshold for the thrust values labels : iterable, optional Labels for the different phases. Default is `('powered', 'coast')` Attributes ---------- R : float Equatorial radius of central attracting body [m] or [-] scaler : float Value to scale the distances units : list List of measurement units for distances, velocities and time time : ndarray Time vector for implicit NLP solution [s] or [-] states : ndarray States time series for implicit NLP solution as `[r, theta, u, v, m]` time_exp : ndarray or ``None`` Time vector for explicit simulation [s] o [-] or ``None`` states_exp : ndarray or ``None`` States time series for explicit simulation as `[r, theta, u, v, m]` or ``None`` time_pow : ndarray Time vector for implicit NLP solution corresponding to a powered phase [s] or [-] states_pow : ndarray States time series for implicit NLP solution corresponding to a powered phase as `[r, theta, u, v, m]` time_coast : ndarray Time vector for implicit NLP solution corresponding to a coasting phase [s] or [-] states_coast : ndarray States time series for implicit NLP solution corresponding to a coasting phase as `[r, theta, u, v, m]` r_safe : ndarray or ``None`` Time series for minimum safe altitude [m] or [-] or ``None`` labels : iterable Labels for the different phases """ def __init__(self, r, time, states, time_exp=None, states_exp=None, thrust=None, threshold=1e-6, r_safe=None, labels=('powered', 'coast')): """Initializes `TwoDimStatesTimeSeries` class. """ self.R = r if not np.isclose(r, 1.0): self.scaler = 1e3 self.units = ['km', 'km/s', 's'] else: self.scaler = 1.0 self.units = ['-', '-', '-'] self.time = time self.states = states self.time_exp = time_exp self.states_exp = states_exp if thrust is not None: self.time_pow = self.time[(thrust >= threshold).flatten(), :] self.states_pow = self.states[(thrust >= threshold).flatten(), :] self.time_coast = self.time[(thrust < threshold).flatten(), :] self.states_coast = self.states[(thrust < threshold).flatten(), :] self.r_safe = r_safe self.labels = labels
[docs] def plot(self): """Plot the two-dimensional simulation's states and in time. """ fig, axs = plt.subplots(2, 2, constrained_layout=True) if self.r_safe is not None: axs[0, 0].plot(self.time, (self.r_safe - self.R)/self.scaler, color='k', label='safe altitude') if self.states_exp is not None: # explicit simulation axs[0, 0].plot(self.time_exp, (self.states_exp[:, 0] - self.R)/self.scaler, color='g', label='explicit') axs[1, 0].plot(self.time_exp, self.states_exp[:, 1]*180/np.pi, color='g', label='explicit') axs[0, 1].plot(self.time_exp, self.states_exp[:, 2]/self.scaler, color='g', label='explicit') axs[1, 1].plot(self.time_exp, self.states_exp[:, 3]/self.scaler, color='g', label='explicit') if not hasattr(self, 'time_pow'): # implicit solution with constant thrust axs[0, 0].plot(self.time, (self.states[:, 0] - self.R)/self.scaler, 'o', color='b', label='implicit') axs[1, 0].plot(self.time, self.states[:, 1]*180/np.pi, 'o', color='b', label='implicit') axs[0, 1].plot(self.time, self.states[:, 2]/self.scaler, 'o', color='b', label='implicit') axs[1, 1].plot(self.time, self.states[:, 3]/self.scaler, 'o', color='b', label='implicit') else: # implicit solution with variable thrust axs[0, 0].plot(self.time_coast, (self.states_coast[:, 0] - self.R)/self.scaler, 'o', color='b', label=self.labels[1]) axs[1, 0].plot(self.time_coast, self.states_coast[:, 1]*180/np.pi, 'o', color='b', label=self.labels[1]) axs[0, 1].plot(self.time_coast, self.states_coast[:, 2]/self.scaler, 'o', color='b', label=self.labels[1]) axs[1, 1].plot(self.time_coast, self.states_coast[:, 3]/self.scaler, 'o', color='b', label=self.labels[1]) axs[0, 0].plot(self.time_pow, (self.states_pow[:, 0] - self.R)/self.scaler, 'o', color='r', label=self.labels[0]) axs[1, 0].plot(self.time_pow, self.states_pow[:, 1]*180/np.pi, 'o', color='r', label=self.labels[0]) axs[0, 1].plot(self.time_pow, self.states_pow[:, 2]/self.scaler, 'o', color='r', label=self.labels[0]) axs[1, 1].plot(self.time_pow, self.states_pow[:, 3]/self.scaler, 'o', color='r', label=self.labels[0]) axs[0, 0].set_ylabel(''.join(['h (', self.units[0], ')'])) axs[0, 0].set_title('Altitude') axs[1, 0].set_ylabel('theta (deg)') axs[1, 0].set_title('Angle') axs[0, 1].set_ylabel(''.join(['u (', self.units[1], ')'])) axs[0, 1].set_title('Radial velocity') axs[1, 1].set_ylabel(''.join(['v (', self.units[1], ')'])) axs[1, 1].set_title('Tangential velocity') for i in range(2): for j in range(2): axs[i, j].set_xlabel(''.join(['time (', self.units[2], ')'])) axs[i, j].grid() axs[i, j].legend(loc='best')
[docs]class TwoDimControlsTimeSeries: """Plot the two-dimensional simulation's controls in time. Parameters ---------- time : ndarray Time vector for implicit NLP solution [s] or [-] controls : ndarray Controls time series for implicit NLP solution as `[thrust, alpha]` threshold : float or ``None``, optional Threshold value to determine the on/off control structure or ``None``. Default is ``1e-6`` units : iterable, optional Measurements units for thrust, time. Default is `('N', 's')` Attributes ---------- time : ndarray Time vector for implicit NLP solution [s] or [-] thrust : ndarray Thrust magnitude time series for implicit NLP solution [N] or [-] alpha : ndarray Thrust direction time series for implicit NLP solution [rad] threshold : float or ``None`` Threshold value to determine the on/off control structure or ``None`` units : iterable Measurements units for thrust, time """ def __init__(self, time, controls, threshold=1e-6, units=('N', 's')): """Initializes `TwoDimControlsTimeSeries` class. """ self.time = time self.thrust = controls[:, 0] self.alpha = controls[:, 1] self.threshold = threshold self.units = units if threshold is not None: self.alpha[(self.thrust < threshold).flatten()] = None
[docs] def plot(self): """Plot the two-dimensional simulation's controls in time. """ if self.threshold is None: fig, ax = plt.subplots(1, 1, constrained_layout=True) ax.plot(self.time, self.alpha*180/np.pi, 'o', color='r') ax.set_xlabel(''.join(['time (', self.units[1], ')'])) ax.set_ylabel('alpha (deg)') ax.set_title('Thrust direction') ax.grid() else: fig, axs = plt.subplots(2, 1, constrained_layout=True) axs[0].plot(self.time, self.alpha*180/np.pi, 'o', color='r') axs[0].set_xlabel(''.join(['time (', self.units[1], ')'])) axs[0].set_ylabel('alpha (deg)') axs[0].set_title('Thrust direction') axs[0].grid() # throttle axs[1].plot(self.time, self.thrust, 'o', color='r') axs[1].set_xlabel(''.join(['time (', self.units[1], ')'])) axs[1].set_ylabel(''.join(['thrust (', self.units[0], ')'])) axs[1].set_title('Thrust magnitude') axs[1].grid()