87 Quaternion(
double inI,
double inJ,
double inK,
double inS) noexcept :
88 components_{ inI, inJ, inK, inS }
99 Quaternion(
const std::array<double, 4>& components) noexcept :
100 components_{ components }
114 components_{ 0., 0., 0., 0. }
116 if (inArray.
size() == 3)
119 eulerToQuat(inArray[0], inArray[1], inArray[2]);
121 else if (inArray.
size() == 4)
127 else if (inArray.
size() == 9)
150 const double halfAngle = inAngle / 2.;
151 const double sinHalfAngle = std::sin(halfAngle);
153 components_[0] = normAxis.
x * sinHalfAngle;
154 components_[1] = normAxis.
y * sinHalfAngle;
155 components_[2] = normAxis.
z * sinHalfAngle;
156 components_[3] = std::cos(halfAngle);
179 return 2. * std::acos(
s());
201 eyeTimesScalar.
zeros();
202 eyeTimesScalar(0, 0) = inQuat2.
s();
203 eyeTimesScalar(1, 1) = inQuat2.
s();
204 eyeTimesScalar(2, 2) = inQuat2.
s();
208 q.
put(
Slice(0, 3),
Slice(0, 3), eyeTimesScalar + epsilonHat);
209 q(3, 0) = -inQuat2.
i();
210 q(3, 1) = -inQuat2.
j();
211 q(3, 2) = -inQuat2.
k();
240 const auto sinHalfAngle = std::sin(halfAngle);
241 auto axis =
Vec3(
i() / sinHalfAngle,
j() / sinHalfAngle,
k() / sinHalfAngle);
244 return axis.normalize();
255 return { -
i(), -
j(), -
k(),
s() };
264 [[nodiscard]]
double i() const noexcept
266 return components_[0];
298 [[nodiscard]]
double j() const noexcept
300 return components_[1];
309 [[nodiscard]]
double k() const noexcept
311 return components_[2];
325 if (inPercent < 0. || inPercent > 1.)
339 const double oneMinus = 1. - inPercent;
340 std::array<double, 4> newComponents{};
343 inQuat1.components_.end(),
344 inQuat2.components_.begin(),
345 newComponents.begin(),
346 [inPercent, oneMinus](
double component1,
double component2) ->
double
347 { return oneMinus * component1 + inPercent * component2; });
349 return { newComponents };
362 return nlerp(*
this, inQuat2, inPercent);
371 [[nodiscard]]
double pitch() const noexcept
373 return std::asin(2 * (
s() *
j() -
k() *
i()));
385 return { 0., inAngle, 0. };
406 propagate(inAngularVelocity, inDeltaT, getBodyOmegaOperator(inAngularVelocity));
510 propagate(inAngularVelocity, inDeltaT, getInertialOmegaOperator(inAngularVelocity));
611 [[nodiscard]]
double roll() const noexcept
625 return { inAngle, 0., 0. };
637 if (inVector.
size() != 3)
642 return *
this * inVector;
654 return *
this * inVec3;
663 [[nodiscard]]
double s() const noexcept
665 return components_[3];
679 if (inPercent < 0 || inPercent > 1)
705 constexpr double DOT_THRESHOLD = 0.9995;
706 if (dotProduct > DOT_THRESHOLD)
710 return nlerp(inQuat1, inQuat2, inPercent);
713 dotProduct =
clip(dotProduct, -1., 1.);
714 const double theta0 = std::acos(dotProduct);
715 const double theta = theta0 * inPercent;
717 const double s0 = std::cos(theta) -
718 dotProduct * std::sin(theta) / std::sin(theta0);
719 const double s1 = std::sin(theta) / std::sin(theta0);
735 return slerp(*
this, inQuat2, inPercent);
744 [[nodiscard]] std::string
str()
const
762 const double q0 =
i();
763 const double q1 =
j();
764 const double q2 =
k();
765 const double q3 =
s();
772 dcm(0, 0) = q3sqr + q0sqr - q1sqr - q2sqr;
773 dcm(0, 1) = 2. * (q0 * q1 - q3 * q2);
774 dcm(0, 2) = 2. * (q0 * q2 + q3 * q1);
775 dcm(1, 0) = 2. * (q0 * q1 + q3 * q2);
776 dcm(1, 1) = q3sqr + q1sqr - q0sqr - q2sqr;
777 dcm(1, 2) = 2. * (q1 * q2 - q3 * q0);
778 dcm(2, 0) = 2. * (q0 * q2 - q3 * q1);
779 dcm(2, 1) = 2. * (q1 * q2 + q3 * q0);
780 dcm(2, 2) = q3sqr + q2sqr - q0sqr - q1sqr;
793 auto componentsCopy = components_;
806 const Vec3 eulerAxis = { 1., 0., 0. };
816 [[nodiscard]]
double yaw() const noexcept
830 return { 0., 0., inAngle };
842 const Vec3 eulerAxis = { 0., 1., 0. };
855 const Vec3 eulerAxis = { 0., 0., 1. };
868 const auto comparitor = [](
double value1,
double value2)
noexcept ->
bool
871 return stl_algorithms::equal(components_.begin(), components_.end(), inRhs.components_.begin(), comparitor);
883 return !(*
this == inRhs);
897 inRhs.components_.begin(),
899 std::plus<double>());
929 inRhs.components_.begin(),
931 std::minus<double>());
970 double q0 = inRhs.s() *
i();
971 q0 += inRhs.i() *
s();
972 q0 -= inRhs.j() *
k();
973 q0 += inRhs.k() *
j();
975 double q1 = inRhs.s() *
j();
976 q1 += inRhs.i() *
k();
977 q1 += inRhs.j() *
s();
978 q1 -= inRhs.k() *
i();
980 double q2 = inRhs.s() *
k();
981 q2 -= inRhs.i() *
j();
982 q2 += inRhs.j() *
i();
983 q2 += inRhs.k() *
s();
985 double q3 = inRhs.s() *
s();
986 q3 -= inRhs.i() *
i();
987 q3 -= inRhs.j() *
j();
988 q3 -= inRhs.k() *
k();
1012 [inScalar](
double& component) { component *= inScalar; });
1053 if (inVec.
size() != 3)
1058 const auto vecNorm =
norm(inVec).
item();
1064 const auto p =
Quaternion(inVec[0], inVec[1], inVec[2], 0.);
1065 const auto pPrime = *
this * p * this->
inverse();
1068 rotatedVec *= vecNorm;
1093 return *
this *= inRhs.conjugate();
1118 inOStream << inQuat.
str();
1124 std::array<double, 4> components_{ { 0., 0., 0., 1. } };
1130 void normalize() noexcept
1132 double sumOfSquares = 0.;
1133 std::for_each(components_.begin(),
1135 [&sumOfSquares](
double component) noexcept ->
void
1136 { sumOfSquares += utils::sqr(component); });
1138 const double norm = std::sqrt(sumOfSquares);
1141 [
norm](
double& component) noexcept ->
void { component /= norm; });
1152 void eulerToQuat(
double roll,
double pitch,
double yaw)
noexcept
1154 const auto halfPhi =
roll / 2.;
1155 const auto halfTheta =
pitch / 2.;
1156 const auto halfPsi =
yaw / 2.;
1158 const auto sinHalfPhi = std::sin(halfPhi);
1159 const auto cosHalfPhi = std::cos(halfPhi);
1161 const auto sinHalfTheta = std::sin(halfTheta);
1162 const auto cosHalfTheta = std::cos(halfTheta);
1164 const auto sinHalfPsi = std::sin(halfPsi);
1165 const auto cosHalfPsi = std::cos(halfPsi);
1167 components_[0] = sinHalfPhi * cosHalfTheta * cosHalfPsi;
1168 components_[0] -= cosHalfPhi * sinHalfTheta * sinHalfPsi;
1170 components_[1] = cosHalfPhi * sinHalfTheta * cosHalfPsi;
1171 components_[1] += sinHalfPhi * cosHalfTheta * sinHalfPsi;
1173 components_[2] = cosHalfPhi * cosHalfTheta * sinHalfPsi;
1174 components_[2] -= sinHalfPhi * sinHalfTheta * cosHalfPsi;
1176 components_[3] = cosHalfPhi * cosHalfTheta * cosHalfPsi;
1177 components_[3] += sinHalfPhi * sinHalfTheta * sinHalfPsi;
1186 void dcmToQuat(
const NdArray<double>& dcm)
1188 const Shape inShape = dcm.shape();
1189 if (!(inShape.rows == 3 && inShape.cols == 3))
1194 NdArray<double> checks(1, 4);
1195 checks[0] = 1 + dcm(0, 0) + dcm(1, 1) + dcm(2, 2);
1196 checks[1] = 1 + dcm(0, 0) - dcm(1, 1) - dcm(2, 2);
1197 checks[2] = 1 - dcm(0, 0) + dcm(1, 1) - dcm(2, 2);
1198 checks[3] = 1 - dcm(0, 0) - dcm(1, 1) + dcm(2, 2);
1206 components_[3] = 0.5 * std::sqrt(1 + dcm(0, 0) + dcm(1, 1) + dcm(2, 2));
1207 components_[0] = (dcm(2, 1) - dcm(1, 2)) / (4 * components_[3]);
1208 components_[1] = (dcm(0, 2) - dcm(2, 0)) / (4 * components_[3]);
1209 components_[2] = (dcm(1, 0) - dcm(0, 1)) / (4 * components_[3]);
1215 components_[0] = 0.5 * std::sqrt(1 + dcm(0, 0) - dcm(1, 1) - dcm(2, 2));
1216 components_[1] = (dcm(1, 0) + dcm(0, 1)) / (4 * components_[0]);
1217 components_[2] = (dcm(2, 0) + dcm(0, 2)) / (4 * components_[0]);
1218 components_[3] = (dcm(2, 1) - dcm(1, 2)) / (4 * components_[0]);
1224 components_[1] = 0.5 * std::sqrt(1 - dcm(0, 0) + dcm(1, 1) - dcm(2, 2));
1225 components_[0] = (dcm(1, 0) + dcm(0, 1)) / (4 * components_[1]);
1226 components_[2] = (dcm(2, 1) + dcm(1, 2)) / (4 * components_[1]);
1227 components_[3] = (dcm(0, 2) - dcm(2, 0)) / (4 * components_[1]);
1233 components_[2] = 0.5 * std::sqrt(1 - dcm(0, 0) - dcm(1, 1) + dcm(2, 2));
1234 components_[0] = (dcm(2, 0) + dcm(0, 2)) / (4 * components_[2]);
1235 components_[1] = (dcm(2, 1) + dcm(1, 2)) / (4 * components_[2]);
1236 components_[3] = (dcm(1, 0) - dcm(0, 1)) / (4 * components_[2]);
1251 void propagate(
const Vec3& inAngularVelocity,
double inDeltaT,
const NdArray<double>& inOmegaOperator)
1258 const auto angularVelocityNorm = inAngularVelocity.norm();
1264 const auto halfDeltaT = inDeltaT / 2.;
1265 const auto halfAngle = angularVelocityNorm * halfDeltaT;
1266 const auto sinHalfAngle = std::sin(halfAngle) / angularVelocityNorm;
1267 const auto cosHalfAngle = std::cos(halfAngle);
1270 const auto rhs = sinHalfAngle * inOmegaOperator;
1274 components_[0] = qDeltaT[0];
1275 components_[1] = qDeltaT[1];
1276 components_[2] = qDeltaT[2];
1277 components_[3] = qDeltaT[3];
1288 NdArray<double> getBodyOmegaOperator(
const Vec3& inAngularVelocity)
const
1290 return NdArray<double>({ { 0., inAngularVelocity.z, -inAngularVelocity.y, inAngularVelocity.x },
1291 { -inAngularVelocity.z, 0., inAngularVelocity.x, inAngularVelocity.y },
1292 { inAngularVelocity.y, -inAngularVelocity.x, 0., inAngularVelocity.z },
1293 { -inAngularVelocity.x, -inAngularVelocity.y, -inAngularVelocity.z, 0. } });
1302 NdArray<double> getInertialOmegaOperator(
const Vec3& inAngularVelocity)
const
1304 return NdArray<double>({ { 0., -inAngularVelocity.z, inAngularVelocity.y, inAngularVelocity.x },
1305 { inAngularVelocity.z, 0., -inAngularVelocity.x, inAngularVelocity.y },
1306 { -inAngularVelocity.y, inAngularVelocity.x, 0., inAngularVelocity.z },
1307 { -inAngularVelocity.x, -inAngularVelocity.y, -inAngularVelocity.z, 0. } });
#define THROW_INVALID_ARGUMENT_ERROR(msg)
Definition Error.hpp:37
Holds 1D and 2D arrays, the main work horse of the NumCpp library.
Definition NdArrayCore.hpp:139
size_type size() const noexcept
Definition NdArrayCore.hpp:4604
self_type & zeros() noexcept
Definition NdArrayCore.hpp:4981
const_iterator cbegin() const noexcept
Definition NdArrayCore.hpp:1365
self_type transpose() const
Definition NdArrayCore.hpp:4963
self_type dot(const self_type &inOtherArray) const
Definition NdArrayCore.hpp:2795
const_iterator cend() const noexcept
Definition NdArrayCore.hpp:1673
value_type item() const
Definition NdArrayCore.hpp:3102
self_type & put(index_type inIndex, const value_type &inValue)
Definition NdArrayCore.hpp:3773
A Class for slicing into NdArrays.
Definition Slice.hpp:45
Holds a 3D vector.
Definition Vec3.hpp:51
double z
Definition Vec3.hpp:56
Vec3 normalize() const noexcept
Definition Vec3.hpp:289
double x
Definition Vec3.hpp:54
double y
Definition Vec3.hpp:55
NdArray< double > toNdArray() const
Definition Vec3.hpp:337
void propagateInertialPitch(double pitchRate, double inDeltaT)
Definition Quaternion.hpp:560
double s() const noexcept
Definition Quaternion.hpp:663
std::string str() const
Definition Quaternion.hpp:744
double angleOfRotation() const noexcept
Definition Quaternion.hpp:177
friend std::ostream & operator<<(std::ostream &inOStream, const Quaternion &inQuat)
Definition Quaternion.hpp:1116
double roll() const noexcept
Definition Quaternion.hpp:611
static Quaternion xRotation(double inAngle) noexcept
Definition Quaternion.hpp:804
static Quaternion nlerp(const Quaternion &inQuat1, const Quaternion &inQuat2, double inPercent)
Definition Quaternion.hpp:323
static Quaternion propagateInertialPitch(Quaternion inQuaternion, double pitchRate, double inDeltaT)
Definition Quaternion.hpp:573
static Quaternion rollRotation(double inAngle) noexcept
Definition Quaternion.hpp:623
Vec3 rotate(const Vec3 &inVec3) const
Definition Quaternion.hpp:652
Quaternion(double inI, double inJ, double inK, double inS) noexcept
Definition Quaternion.hpp:87
NdArray< double > angularVelocity(const Quaternion &inQuat2, double inTime) const
Definition Quaternion.hpp:226
Quaternion operator-() const noexcept
Definition Quaternion.hpp:956
static Quaternion propagateBody(Quaternion inQuaternion, const Vec3 &inAngularVelocity, double inDeltaT)
Definition Quaternion.hpp:417
NdArray< double > operator*(const NdArray< double > &inVec) const
Definition Quaternion.hpp:1051
Quaternion(const std::array< double, 4 > &components) noexcept
Definition Quaternion.hpp:99
static Quaternion propagateBodyRoll(Quaternion inQuaternion, double rollRate, double inDeltaT)
Definition Quaternion.hpp:443
Quaternion operator+(const Quaternion &inRhs) const noexcept
Definition Quaternion.hpp:913
void propagateBodyYaw(double yawRate, double inDeltaT)
Definition Quaternion.hpp:482
double i() const noexcept
Definition Quaternion.hpp:264
double yaw() const noexcept
Definition Quaternion.hpp:816
double pitch() const noexcept
Definition Quaternion.hpp:371
Quaternion slerp(const Quaternion &inQuat2, double inPercent) const
Definition Quaternion.hpp:733
NdArray< double > toNdArray() const
Definition Quaternion.hpp:791
Quaternion & operator/=(const Quaternion &inRhs) noexcept
Definition Quaternion.hpp:1091
void propagateInertialRoll(double rollRate, double inDeltaT)
Definition Quaternion.hpp:534
static Quaternion slerp(const Quaternion &inQuat1, const Quaternion &inQuat2, double inPercent)
Definition Quaternion.hpp:677
static Quaternion yawRotation(double inAngle) noexcept
Definition Quaternion.hpp:828
void print() const
Definition Quaternion.hpp:392
Quaternion(const NdArray< double > &inAxis, double inAngle)
Definition Quaternion.hpp:166
bool operator==(const Quaternion &inRhs) const noexcept
Definition Quaternion.hpp:866
NdArray< double > rotate(const NdArray< double > &inVector) const
Definition Quaternion.hpp:635
static Quaternion propagateInertialRoll(Quaternion inQuaternion, double rollRate, double inDeltaT)
Definition Quaternion.hpp:547
Quaternion(double roll, double pitch, double yaw) noexcept
Definition Quaternion.hpp:73
static Quaternion propagateInertial(Quaternion inQuaternion, const Vec3 &inAngularVelocity, double inDeltaT)
Definition Quaternion.hpp:521
void propagateInertial(const Vec3 &inAngularVelocity, double inDeltaT)
Definition Quaternion.hpp:508
Vec3 operator*(const Vec3 &inVec3) const
Definition Quaternion.hpp:1079
Quaternion inverse() const noexcept
Definition Quaternion.hpp:286
void propagateBodyPitch(double pitchRate, double inDeltaT)
Definition Quaternion.hpp:456
double k() const noexcept
Definition Quaternion.hpp:309
static Quaternion zRotation(double inAngle) noexcept
Definition Quaternion.hpp:853
NdArray< double > toDCM() const
Definition Quaternion.hpp:758
Quaternion operator/(const Quaternion &inRhs) const noexcept
Definition Quaternion.hpp:1103
Quaternion nlerp(const Quaternion &inQuat2, double inPercent) const
Definition Quaternion.hpp:360
static Quaternion propagateInertialYaw(Quaternion inQuaternion, double yawRate, double inDeltaT)
Definition Quaternion.hpp:599
void propagateBodyRoll(double rollRate, double inDeltaT)
Definition Quaternion.hpp:430
static Quaternion yRotation(double inAngle) noexcept
Definition Quaternion.hpp:840
void propagateBody(const Vec3 &inAngularVelocity, double inDeltaT)
Definition Quaternion.hpp:404
Quaternion(const Vec3 &inAxis, double inAngle) noexcept
Definition Quaternion.hpp:145
void propagateInertialYaw(double yawRate, double inDeltaT)
Definition Quaternion.hpp:586
Quaternion & operator*=(double inScalar) noexcept
Definition Quaternion.hpp:1008
double j() const noexcept
Definition Quaternion.hpp:298
Quaternion & operator+=(const Quaternion &inRhs) noexcept
Definition Quaternion.hpp:893
static Quaternion propagateBodyYaw(Quaternion inQuaternion, double yawRate, double inDeltaT)
Definition Quaternion.hpp:495
Quaternion operator*(double inScalar) const noexcept
Definition Quaternion.hpp:1039
Quaternion operator-(const Quaternion &inRhs) const noexcept
Definition Quaternion.hpp:945
Quaternion operator*(const Quaternion &inRhs) const noexcept
Definition Quaternion.hpp:1026
bool operator!=(const Quaternion &inRhs) const noexcept
Definition Quaternion.hpp:881
Quaternion(const NdArray< double > &inArray)
Definition Quaternion.hpp:113
Quaternion conjugate() const noexcept
Definition Quaternion.hpp:253
static Quaternion propagateBodyPitch(Quaternion inQuaternion, double pitchRate, double inDeltaT)
Definition Quaternion.hpp:469
static Quaternion identity() noexcept
Definition Quaternion.hpp:275
Vec3 axisOfRotation() const noexcept
Definition Quaternion.hpp:237
static NdArray< double > angularVelocity(const Quaternion &inQuat1, const Quaternion &inQuat2, double inTime)
Definition Quaternion.hpp:192
Quaternion & operator-=(const Quaternion &inRhs) noexcept
Definition Quaternion.hpp:925
Quaternion & operator*=(const Quaternion &inRhs) noexcept
Definition Quaternion.hpp:968
static Quaternion pitchRotation(double inAngle) noexcept
Definition Quaternion.hpp:383
NdArray< dtype > hat(dtype inX, dtype inY, dtype inZ)
Definition hat.hpp:49
OutputIt transform(InputIt first, InputIt last, OutputIt destination, UnaryOperation unaryFunction)
Definition StlAlgorithms.hpp:776
void for_each(InputIt first, InputIt last, UnaryFunction f)
Definition StlAlgorithms.hpp:226
bool equal(InputIt1 first1, InputIt1 last1, InputIt2 first2) noexcept
Definition StlAlgorithms.hpp:141
OutputIt copy(InputIt first, InputIt last, OutputIt destination) noexcept
Definition StlAlgorithms.hpp:98
std::string num2str(dtype inNumber)
Definition num2str.hpp:44
bool essentiallyEqual(dtype inValue1, dtype inValue2) noexcept
Definition essentiallyEqual.hpp:49
constexpr dtype sqr(dtype inValue) noexcept
Definition sqr.hpp:42
NdArray< double > norm(const NdArray< dtype > &inArray, Axis inAxis=Axis::NONE)
Definition norm.hpp:51
NdArray< dtype > dot(const NdArray< dtype > &inArray1, const NdArray< dtype > &inArray2)
Definition dot.hpp:48
dtype clip(dtype inValue, dtype inMinValue, dtype inMaxValue)
Definition clip.hpp:50
NdArray< uint32 > argmax(const NdArray< dtype > &inArray, Axis inAxis=Axis::NONE)
Definition argmax.hpp:46
NdArray< dtype > eye(uint32 inN, uint32 inM, int32 inK=0)
Definition eye.hpp:51
NdArray< double > normalize(const NdArray< dtype > &inArray, Axis inAxis=Axis::NONE)
Definition normalize.hpp:52
std::uint32_t uint32
Definition Types.hpp:40
NdArray< dtype > transpose(const NdArray< dtype > &inArray)
Definition transpose.hpp:45