ModelSpace
All Classes Namespaces Functions Variables Enumerations Pages
Quaternion.hpp
1/******************************************************************************
2* Copyright (c) ATTX LLC 2024. All Rights Reserved.
3*
4* This software and associated documentation (the "Software") are the
5* proprietary and confidential information of ATTX, LLC. The Software is
6* furnished under a license agreement between ATTX and the user organization
7* and may be used or copied only in accordance with the terms of the agreement.
8* Refer to 'license/attx_license.adoc' for standard license terms.
9*
10* EXPORT CONTROL NOTICE: THIS SOFTWARE MAY INCLUDE CONTENT CONTROLLED UNDER THE
11* INTERNATIONAL TRAFFIC IN ARMS REGULATIONS (ITAR) OR THE EXPORT ADMINISTRATION
12* REGULATIONS (EAR99). No part of the Software may be used, reproduced, or
13* transmitted in any form or by any means, for any purpose, without the express
14* written permission of ATTX, LLC.
15******************************************************************************/
16/*
17Quaternion header file
18
19Author: Alex Reynolds
20*/
21#ifndef QUATERNION_HPP
22#define QUATERNION_HPP
23
24#include <cmath>
25
26#include "core/Matrix.hpp"
27#include "core/CartesianVector.hpp"
28#include "core/safemath.hpp"
29#include "core/matrixmath.hpp"
30
31#include "DCM.hpp"
32
33namespace clockwerk {
34
35 /// Forward declaration of MRP for conversion
36 template<typename T>
37 class MRP;
38
39 /// @brief Quaternion class for attitude representation
40 ///
41 /// This file defines a simple Quaternion attitude representation for cartesian
42 /// coordinate systems. It is largely the same as the base vector,
43 /// with the following exceptions:
44 /// - Set to be 4 elements
45 /// - Functions defined to convert to other attitude representations
46 /// - Function defined to calculate rate of change as a function of omega
47 ///
48 /// Naming conventions
49 /// ------------------
50 /// - All naming conventions and equations are per Analytical Mechanics of
51 /// Space Systems by Schaub and Junkins
52 /// - The omega vector is sometimes denoted by w and assumed frame consistent with
53 /// the attitude representation. For example, if a DCM represents the
54 /// relative orientation between two frames [BN] the omega vector is
55 /// assumed to be w_(B/N)
56 /// - The naming convention for all vectors is:
57 /// variablename_obj1_obj2__frameN (note the double underscore preceding frame)
58 /// and reads back as:
59 /// "variable variablename representing the relationship between obj1 and obj2
60 /// represented in frameN"
61 /// - Unless otherwise noted angles are in RADIANS
62 ///
63 /// NOTE: All attitude representations, including DCMs, are assumed to represent a
64 /// three dimensional, cartesian coordinate system because that is what they
65 /// are used, and in many cases defined, for.
66 template<typename T>
67 class Quaternion : public CartesianVector<T, 4> {
68 public:
69 /// @brief Default constructor generates Quaternion sequence as zero rotation
70 /// -- 1 0 0 0
71 Quaternion<T>();
72
73 /// Constructor for Matrix class with initialization.
74 /// Initializes matrix to values passed in via array
75 Quaternion<T>(const T(&initial)[4]);
76
77 /// Copy constructor for Quaternion class. Copies data from Quaternion
78 /// object to the current instance
79 Quaternion<T>(const Quaternion<T> &initial);
80
81 /// Constructor for Matrix class with initialization.
82 /// Initializes matrix to values passed in via array
83 Quaternion<T>(const std::array<T, 4> &initial);
84
85 /// Destructor -- doesn't do anything because we don't dynamically
86 /// allocate
87 ~Quaternion<T>() {}
88
89 /// @brief Equals operator overload for quaternion
90 Quaternion<T>& operator=(const Quaternion<T>& other);
91
92 /// ---------------------------------------------------------------------------
93 /// Dynamics and kinematics functions
94 /// ---------------------------------------------------------------------------
95 /// @brief Function to calculate the rate of change in the current
96 /// representation based on the omega vector
97 /// @param omega_f1_f2__f1 Angular velocity vector for the attitude
98 /// representation - omega of frame 1 wrt frame 2
99 /// expressed in frame 1
100 /// @param quatdot_f1_f2 Rate of change in the current Quaternion
101 void rate(const CartesianVector<T, 3> &omega_f1_f2__f1, Matrix<T, 4, 1> &quatdot_f1_f2) const;
102
103 /// ---------------------------------------------------------------------------
104 /// Conversions to other attitude representations
105 /// ---------------------------------------------------------------------------
106 /// @brief Function to convert current attitude to DCM
107 /// @param PBR return of DCM in PBR case
108 /// @return Integer error code corresponding to errors in clockwerkerrors.h
109 void toDCM(DCM<T> &dcm_f1_f2) const;
110 DCM<T> toDCM() const;
111
112 /// @brief Function to convert current attitude to MRP
113 /// @param PBR return of MRP in PBR case
114 /// @return Integer error code corresponding to errors in clockwerkerrors.h
115 void toMRP(MRP<T> &mrp_f1_f2) const;
116 MRP<T> toMRP() const;
117
118 /// @brief Calculate the rotation angle represented by the quaternion
119 /// @param val Implicit return of rotation angle
120 /// @return Error code corresponding to success/failure
121 int rotationAngle(double &val) const;
122 };
123
124 template <typename T>
125 Quaternion<T>::Quaternion() :
126 CartesianVector<T, 4>({1, 0, 0, 0}) {}
127
128 template <typename T>
129 Quaternion<T>::Quaternion(const T(&initial)[4]) :
130 CartesianVector<T, 4>(initial) {}
131
132 template <typename T>
133 Quaternion<T>::Quaternion(const Quaternion<T> &initial) :
134 CartesianVector<T, 4>(initial) {}
135
136 template <typename T>
137 Quaternion<T>::Quaternion(const std::array<T, 4> &initial) :
138 CartesianVector<T, 4>(initial) {}
139
140 template <typename T>
141 Quaternion<T>& Quaternion<T>::operator=(const Quaternion<T>& other)
142 {
143 /// Guard self assignment
144 if (this == &other)
145 return *this;
146
147 /// Copy values from current matrix to return
148 unsigned int i;
149 for(i = 0; i < 4; i++) {
150 this->values[i][0] = other.values[i][0];
151 }
152 return *this;
153 }
154
155 template <typename T>
156 void Quaternion<T>::rate(const CartesianVector<T, 3> &omega_f1_f2__f1, Matrix<T, 4, 1> &quatdot_f1_f2) const {
157 quatdot_f1_f2.values[0][0] = -omega_f1_f2__f1.values[0][0]*CartesianVector<T, 4>::values[1][0] - omega_f1_f2__f1.values[1][0]*CartesianVector<T, 4>::values[2][0] - omega_f1_f2__f1.values[2][0]*CartesianVector<T, 4>::values[3][0];
158 quatdot_f1_f2.values[1][0] = omega_f1_f2__f1.values[0][0]*CartesianVector<T, 4>::values[0][0] + omega_f1_f2__f1.values[2][0]*CartesianVector<T, 4>::values[2][0] - omega_f1_f2__f1.values[1][0]*CartesianVector<T, 4>::values[3][0];
159 quatdot_f1_f2.values[2][0] = omega_f1_f2__f1.values[1][0]*CartesianVector<T, 4>::values[0][0] - omega_f1_f2__f1.values[2][0]*CartesianVector<T, 4>::values[1][0] + omega_f1_f2__f1.values[0][0]*CartesianVector<T, 4>::values[3][0];
160 quatdot_f1_f2.values[3][0] = omega_f1_f2__f1.values[2][0]*CartesianVector<T, 4>::values[0][0] + omega_f1_f2__f1.values[1][0]*CartesianVector<T, 4>::values[1][0] - omega_f1_f2__f1.values[0][0]*CartesianVector<T, 4>::values[2][0];
161 multiply(static_cast<T>(0.5), quatdot_f1_f2, quatdot_f1_f2);
162 }
163
164 template <typename T>
165 void Quaternion<T>::toDCM(DCM<T> &dcm_f1_f2) const {
166 /// Calculate parameters to simplify calculation
167 T q02, q12, q22, q32, q0q1, q0q2, q0q3, q1q2, q1q3, q2q3;
168 q02 = CartesianVector<T, 4>::values[0][0]*CartesianVector<T, 4>::values[0][0];
169 q12 = CartesianVector<T, 4>::values[1][0]*CartesianVector<T, 4>::values[1][0];
170 q22 = CartesianVector<T, 4>::values[2][0]*CartesianVector<T, 4>::values[2][0];
171 q32 = CartesianVector<T, 4>::values[3][0]*CartesianVector<T, 4>::values[3][0];
172 q0q1 = CartesianVector<T, 4>::values[0][0]*CartesianVector<T, 4>::values[1][0];
173 q0q2 = CartesianVector<T, 4>::values[0][0]*CartesianVector<T, 4>::values[2][0];
174 q0q3 = CartesianVector<T, 4>::values[0][0]*CartesianVector<T, 4>::values[3][0];
175 q1q2 = CartesianVector<T, 4>::values[1][0]*CartesianVector<T, 4>::values[2][0];
176 q1q3 = CartesianVector<T, 4>::values[1][0]*CartesianVector<T, 4>::values[3][0];
177 q2q3 = CartesianVector<T, 4>::values[2][0]*CartesianVector<T, 4>::values[3][0];
178
179 /// Now calculate DCM
180 dcm_f1_f2.values[0][0] = q02 + q12 - q22 - q32;
181 dcm_f1_f2.values[0][1] = 2*(q1q2 + q0q3);
182 dcm_f1_f2.values[0][2] = 2*(q1q3 - q0q2);
183 dcm_f1_f2.values[1][0] = 2*(q1q2 - q0q3);
184 dcm_f1_f2.values[1][1] = q02 - q12 + q22 - q32;
185 dcm_f1_f2.values[1][2] = 2*(q2q3 + q0q1);
186 dcm_f1_f2.values[2][0] = 2*(q1q3 + q0q2);
187 dcm_f1_f2.values[2][1] = 2*(q2q3 - q0q1);
188 dcm_f1_f2.values[2][2] = q02 - q12 - q22 + q32;
189 }
190 template <typename T>
191 DCM<T> Quaternion<T>::toDCM() const {
192 DCM<T> tmp;
193 toDCM(tmp);
194 return tmp;
195 }
196
197 template <typename T>
198 void Quaternion<T>::toMRP(MRP<T> &mrp_f1_f2) const {
199 /// Calculate intermediate parameter
200 T divisor = 1 + CartesianVector<T, 4>::values[0][0];
201
202 mrp_f1_f2.values[0][0] = CartesianVector<T, 4>::values[1][0]/divisor;
203 mrp_f1_f2.values[1][0] = CartesianVector<T, 4>::values[2][0]/divisor;
204 mrp_f1_f2.values[2][0] = CartesianVector<T, 4>::values[3][0]/divisor;
205 }
206 template <typename T>
207 MRP<T> Quaternion<T>::toMRP() const {
208 MRP<T> tmp;
209 toMRP(tmp);
210 return tmp;
211 }
212
213 template <typename T>
214 int Quaternion<T>::rotationAngle(double &val) const {
215 if(CartesianVector<T, 4>::values[0][0] > 1.0 || CartesianVector<T, 4>::values[0][0] < -1.0) {
216 return ERROR_INVALID_RANGE;
217 }
218
219 val = 2.0*std::acos(CartesianVector<T, 4>::values[0][0]);
220 return NO_ERROR;
221 }
222
223}
224
225#endif
Standard vector class derived from Matrix.
Definition CartesianVector.hpp:39
Class defining a direction cosine matrix inherited from Matrix.
Definition DCM.hpp:71
Matrix math implementation.
Definition Matrix.hpp:54
void toMRP(MRP< T > &mrp_f1_f2) const
Function to convert current attitude to MRP.
Definition Quaternion.hpp:198
void rate(const CartesianVector< T, 3 > &omega_f1_f2__f1, Matrix< T, 4, 1 > &quatdot_f1_f2) const
Function to calculate the rate of change in the current representation based on the omega vector.
Definition Quaternion.hpp:156
Quaternion< T > & operator=(const Quaternion< T > &other)
Equals operator overload for quaternion.
Definition Quaternion.hpp:141
void toDCM(DCM< T > &dcm_f1_f2) const
Function to convert current attitude to DCM.
Definition Quaternion.hpp:165
int rotationAngle(double &val) const
Calculate the rotation angle represented by the quaternion.
Definition Quaternion.hpp:214
#define NO_ERROR
Definition clockwerkerrors.h:31
#define ERROR_INVALID_RANGE
Definition clockwerkerrors.h:50