Skip to content

Commit

Permalink
MNT: Add quaternion conversion functions to rocketpy.tools and update…
Browse files Browse the repository at this point in the history
… Flight
  • Loading branch information
Gui-FernandesBR committed Jan 22, 2024
1 parent ead9219 commit c1216b2
Show file tree
Hide file tree
Showing 4 changed files with 82 additions and 20 deletions.
1 change: 1 addition & 0 deletions .pylintrc
Original file line number Diff line number Diff line change
Expand Up @@ -436,6 +436,7 @@ disable=raw-checker-failed,
no-else-return,
inconsistent-return-statements,
unspecified-encoding,
no-member, # because we use funcify_method decorator

# Enable the message, report, category or checker with the given id(s). You can
# either give multiple identifier separated by comma (,) or put this option
Expand Down
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ straightforward as possible.
- MNT: Add repr method to Parachute class [#490](https://github.com/RocketPy-Team/RocketPy/pull/490)
- ENH: Function Reverse Arithmetic Priority [#488](https://github.com/RocketPy-Team/RocketPy/pull/488)
- DOC: Update Header Related Docs
- MNT: Encapsulate quaternion conversions [#537](https://github.com/RocketPy-Team/RocketPy/pull/537)

### Fixed

Expand Down
36 changes: 16 additions & 20 deletions rocketpy/simulation/flight.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,12 @@
from ..mathutils.vector_matrix import Matrix, Vector
from ..plots.flight_plots import _FlightPlots
from ..prints.flight_prints import _FlightPrints
from ..tools import find_closest
from ..tools import (
find_closest,
quaternions_to_phi,
quaternions_to_precession,
quaternions_to_theta,
)


class Flight:
Expand Down Expand Up @@ -2295,33 +2300,24 @@ def lateral_attitude_angle(self):
@funcify_method("Time (s)", "Precession Angle - ψ (°)", "spline", "constant")
def psi(self):
"""Precession angle as a Function of time."""
psi = (180 / np.pi) * (
np.arctan2(self.e3[:, 1], self.e0[:, 1])
+ np.arctan2(-self.e2[:, 1], -self.e1[:, 1])
) # Precession angle
psi = np.column_stack([self.time, psi]) # Precession angle
return psi
psi = quaternions_to_precession(
self.e0.y_array, self.e1.y_array, self.e2.y_array, self.e3.y_array
)
return np.column_stack([self.time, psi])

@funcify_method("Time (s)", "Spin Angle - φ (°)", "spline", "constant")
def phi(self):
"""Spin angle as a Function of time."""
phi = (180 / np.pi) * (
np.arctan2(self.e3[:, 1], self.e0[:, 1])
- np.arctan2(-self.e2[:, 1], -self.e1[:, 1])
) # Spin angle
phi = np.column_stack([self.time, phi]) # Spin angle
return phi
phi = quaternions_to_phi(
self.e0.y_array, self.e1.y_array, self.e2.y_array, self.e3.y_array
)
return np.column_stack([self.time, phi])

@funcify_method("Time (s)", "Nutation Angle - θ (°)", "spline", "constant")
def theta(self):
"""Nutation angle as a Function of time."""
theta = (
(180 / np.pi)
* 2
* np.arcsin(-((self.e1[:, 1] ** 2 + self.e2[:, 1] ** 2) ** 0.5))
) # Nutation angle
theta = np.column_stack([self.time, theta]) # Nutation angle
return theta
theta = quaternions_to_theta(self.e1.y_array, self.e2.y_array)
return np.column_stack([self.time, theta])

# Fluid Mechanics variables
# Freestream Velocity
Expand Down
64 changes: 64 additions & 0 deletions rocketpy/tools.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import re
from bisect import bisect_left

import numpy as np
import pytz
from cftime import num2pydate
from packaging import version as packaging_version
Expand Down Expand Up @@ -381,6 +382,69 @@ def check_requirement_version(module_name, version):
return True


# Flight


def quaternions_to_precession(e0, e1, e2, e3):
"""Calculates the Precession angle
Parameters
----------
e0 : float
Euler parameter 0, must be between -1 and 1
e1 : float
Euler parameter 1, must be between -1 and 1
e2 : float
Euler parameter 2, must be between -1 and 1
e3 : float
Euler parameter 3, must be between -1 and 1
Returns
-------
float
Euler Precession angle in degrees
"""
return (180 / np.pi) * (np.arctan2(e3, e0) + np.arctan2(-e2, -e1))


def quaternions_to_phi(e0, e1, e2, e3):
"""Calculates the Spin angle from quaternions.
Parameters
----------
e0 : float
Euler parameter 0, must be between -1 and 1
e1 : float
Euler parameter 1, must be between -1 and 1
e2 : float
Euler parameter 2, must be between -1 and 1
e3 : float
Euler parameter 3, must be between -1 and 1
Returns
-------
float
Euler Spin angle in degrees
"""
return (180 / np.pi) * (np.arctan2(e3, e0) - np.arctan2(-e2, -e1))


def quaternions_to_theta(e1, e2):
"""Calculates the Nutation angle from quaternions.
Parameters
----------
e1 : float
Euler parameter 1, must be between -1 and 1
e2 : float
Euler parameter 2, must be between -1 and 1
Returns
-------
float
Euler Nutation angle in degrees
"""
return (180 / np.pi) * 2 * np.arcsin(-((e1**2 + e2**2) ** 0.5))


if __name__ == "__main__":
import doctest

Expand Down

0 comments on commit c1216b2

Please sign in to comment.