1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696 |
- // This file is part of OpenCV project.
- // It is subject to the license terms in the LICENSE file found in the top-level directory
- // of this distribution and at http://opencv.org/license.html.
- //
- //
- // License Agreement
- // For Open Source Computer Vision Library
- //
- // Copyright (C) 2020, Huawei Technologies Co., Ltd. All rights reserved.
- // Third party copyrights are property of their respective owners.
- //
- // Licensed under the Apache License, Version 2.0 (the "License");
- // you may not use this file except in compliance with the License.
- // You may obtain a copy of the License at
- //
- // http://www.apache.org/licenses/LICENSE-2.0
- //
- // Unless required by applicable law or agreed to in writing, software
- // distributed under the License is distributed on an "AS IS" BASIS,
- // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- // See the License for the specific language governing permissions and
- // limitations under the License.
- //
- // Author: Liangqian Kong <chargerKong@126.com>
- // Longbu Wang <riskiest@gmail.com>
- #ifndef OPENCV_CORE_QUATERNION_HPP
- #define OPENCV_CORE_QUATERNION_HPP
- #include <opencv2/core.hpp>
- #include <opencv2/core/utils/logger.hpp>
- #include <iostream>
- namespace cv
- {
- //! @addtogroup core
- //! @{
- //! Unit quaternion flag
- enum QuatAssumeType
- {
- /**
- * This flag is specified by default.
- * If this flag is specified, the input quaternions are assumed to be not unit quaternions.
- * It can guarantee the correctness of the calculations,
- * although the calculation speed will be slower than the flag QUAT_ASSUME_UNIT.
- */
- QUAT_ASSUME_NOT_UNIT,
- /**
- * If this flag is specified, the input quaternions are assumed to be unit quaternions which
- * will save some computations. However, if this flag is specified without unit quaternion,
- * the program correctness of the result will not be guaranteed.
- */
- QUAT_ASSUME_UNIT
- };
- class QuatEnum
- {
- public:
- /** @brief Enum of Euler angles type.
- *
- * Without considering the possibility of using two different convertions for the definition of the rotation axes ,
- * there exists twelve possible sequences of rotation axes, divided into two groups:
- * - Proper Euler angles (Z-X-Z, X-Y-X, Y-Z-Y, Z-Y-Z, X-Z-X, Y-X-Y)
- * - Tait–Bryan angles (X-Y-Z, Y-Z-X, Z-X-Y, X-Z-Y, Z-Y-X, Y-X-Z).
- *
- * The three elemental rotations may be [extrinsic](https://en.wikipedia.org/wiki/Euler_angles#Definition_by_extrinsic_rotations)
- * (rotations about the axes *xyz* of the original coordinate system, which is assumed to remain motionless),
- * or [intrinsic](https://en.wikipedia.org/wiki/Euler_angles#Definition_by_intrinsic_rotations)(rotations about the axes of the rotating coordinate system *XYZ*, solidary with the moving body, which changes its orientation after each elemental rotation).
- *
- *
- * Extrinsic and intrinsic rotations are relevant.
- *
- * The definition of the Euler angles is as following,
- * - \f$\theta_1 \f$ represents the first rotation angle,
- * - \f$\theta_2 \f$ represents the second rotation angle,
- * - \f$\theta_3 \f$ represents the third rotation angle.
- *
- * For intrinsic rotations in the order of X-Y-Z, the rotation matrix R can be calculated by:\f[R =X(\theta_1) Y(\theta_2) Z(\theta_3) \f]
- * For extrinsic rotations in the order of X-Y-Z, the rotation matrix R can be calculated by:\f[R =Z({\theta_3}) Y({\theta_2}) X({\theta_1})\f]
- * where
- * \f[X({\theta_1})={\begin{bmatrix}1&0&0\\0&\cos {\theta_1} &-\sin {\theta_1} \\0&\sin {\theta_1} &\cos {\theta_1} \\\end{bmatrix}},
- * Y({\theta_2})={\begin{bmatrix}\cos \theta_{2}&0&\sin \theta_{2}\\0&1 &0 \\\ -sin \theta_2& 0&\cos \theta_{2} \\\end{bmatrix}},
- * Z({\theta_3})={\begin{bmatrix}\cos\theta_{3} &-\sin \theta_3&0\\\sin \theta_3 &\cos \theta_3 &0\\0&0&1\\\end{bmatrix}}.
- * \f]
- *
- * The function is designed according to this set of conventions:
- * - [Right handed](https://en.wikipedia.org/wiki/Right_hand_rule) reference frames are adopted, and the [right hand rule](https://en.wikipedia.org/wiki/Right_hand_rule) is used to determine the sign of angles.
- * - Each matrix is meant to represent an [active rotation](https://en.wikipedia.org/wiki/Active_and_passive_transformation) (the composing and composed matrices
- * are supposed to act on the coordinates of vectors defined in the initial fixed reference frame and give as a result the coordinates of a rotated vector defined in the same reference frame).
- * - For \f$\theta_1\f$ and \f$\theta_3\f$, the valid range is (−π, π].
- *
- * For \f$\theta_2\f$, the valid range is [−π/2, π/2] or [0, π].
- *
- * For Tait–Bryan angles, the valid range of \f$\theta_2\f$ is [−π/2, π/2]. When transforming a quaternion to Euler angles, the solution of Euler angles is unique in condition of \f$ \theta_2 \in (−π/2, π/2)\f$ .
- * If \f$\theta_2 = −π/2 \f$ or \f$ \theta_2 = π/2\f$, there are infinite solutions. The common name for this situation is gimbal lock.
- * For Proper Euler angles,the valid range of \f$\theta_2\f$ is in [0, π]. The solutions of Euler angles are unique in condition of \f$ \theta_2 \in (0, π)\f$ . If \f$\theta_2 =0 \f$ or \f$\theta_2 =π \f$,
- * there are infinite solutions and gimbal lock will occur.
- */
- enum EulerAnglesType
- {
- INT_XYZ, ///< Intrinsic rotations with the Euler angles type X-Y-Z
- INT_XZY, ///< Intrinsic rotations with the Euler angles type X-Z-Y
- INT_YXZ, ///< Intrinsic rotations with the Euler angles type Y-X-Z
- INT_YZX, ///< Intrinsic rotations with the Euler angles type Y-Z-X
- INT_ZXY, ///< Intrinsic rotations with the Euler angles type Z-X-Y
- INT_ZYX, ///< Intrinsic rotations with the Euler angles type Z-Y-X
- INT_XYX, ///< Intrinsic rotations with the Euler angles type X-Y-X
- INT_XZX, ///< Intrinsic rotations with the Euler angles type X-Z-X
- INT_YXY, ///< Intrinsic rotations with the Euler angles type Y-X-Y
- INT_YZY, ///< Intrinsic rotations with the Euler angles type Y-Z-Y
- INT_ZXZ, ///< Intrinsic rotations with the Euler angles type Z-X-Z
- INT_ZYZ, ///< Intrinsic rotations with the Euler angles type Z-Y-Z
- EXT_XYZ, ///< Extrinsic rotations with the Euler angles type X-Y-Z
- EXT_XZY, ///< Extrinsic rotations with the Euler angles type X-Z-Y
- EXT_YXZ, ///< Extrinsic rotations with the Euler angles type Y-X-Z
- EXT_YZX, ///< Extrinsic rotations with the Euler angles type Y-Z-X
- EXT_ZXY, ///< Extrinsic rotations with the Euler angles type Z-X-Y
- EXT_ZYX, ///< Extrinsic rotations with the Euler angles type Z-Y-X
- EXT_XYX, ///< Extrinsic rotations with the Euler angles type X-Y-X
- EXT_XZX, ///< Extrinsic rotations with the Euler angles type X-Z-X
- EXT_YXY, ///< Extrinsic rotations with the Euler angles type Y-X-Y
- EXT_YZY, ///< Extrinsic rotations with the Euler angles type Y-Z-Y
- EXT_ZXZ, ///< Extrinsic rotations with the Euler angles type Z-X-Z
- EXT_ZYZ, ///< Extrinsic rotations with the Euler angles type Z-Y-Z
- #ifndef CV_DOXYGEN
- EULER_ANGLES_MAX_VALUE
- #endif
- };
- };
- template <typename _Tp> class Quat;
- template <typename _Tp> std::ostream& operator<<(std::ostream&, const Quat<_Tp>&);
- /**
- * Quaternion is a number system that extends the complex numbers. It can be expressed as a
- * rotation in three-dimensional space.
- * A quaternion is generally represented in the form:
- * \f[q = w + x\boldsymbol{i} + y\boldsymbol{j} + z\boldsymbol{k}\f]
- * \f[q = [w, x, y, z]\f]
- * \f[q = [w, \boldsymbol{v}] \f]
- * \f[q = ||q||[\cos\psi, u_x\sin\psi,u_y\sin\psi, u_z\sin\psi].\f]
- * \f[q = ||q||[\cos\psi, \boldsymbol{u}\sin\psi]\f]
- * where \f$\psi = \frac{\theta}{2}\f$, \f$\theta\f$ represents rotation angle,
- * \f$\boldsymbol{u} = [u_x, u_y, u_z]\f$ represents normalized rotation axis,
- * and \f$||q||\f$ represents the norm of \f$q\f$.
- *
- * A unit quaternion is usually represents rotation, which has the form:
- * \f[q = [\cos\psi, u_x\sin\psi,u_y\sin\psi, u_z\sin\psi].\f]
- *
- * To create a quaternion representing the rotation around the axis \f$\boldsymbol{u}\f$
- * with angle \f$\theta\f$, you can use
- * ```
- * using namespace cv;
- * double angle = CV_PI;
- * Vec3d axis = {0, 0, 1};
- * Quatd q = Quatd::createFromAngleAxis(angle, axis);
- * ```
- *
- * You can simply use four same type number to create a quaternion
- * ```
- * Quatd q(1, 2, 3, 4);
- * ```
- * Or use a Vec4d or Vec4f vector.
- * ```
- * Vec4d vec{1, 2, 3, 4};
- * Quatd q(vec);
- * ```
- *
- * ```
- * Vec4f vec{1, 2, 3, 4};
- * Quatf q(vec);
- * ```
- *
- * If you already have a 3x3 rotation matrix R, then you can use
- * ```
- * Quatd q = Quatd::createFromRotMat(R);
- * ```
- *
- * If you already have a rotation vector rvec which has the form of `angle * axis`, then you can use
- * ```
- * Quatd q = Quatd::createFromRvec(rvec);
- * ```
- *
- * To extract the rotation matrix from quaternion, see toRotMat3x3()
- *
- * To extract the Vec4d or Vec4f, see toVec()
- *
- * To extract the rotation vector, see toRotVec()
- *
- * If there are two quaternions \f$q_0, q_1\f$ are needed to interpolate, you can use nlerp(), slerp() or spline()
- * ```
- * Quatd::nlerp(q0, q1, t)
- *
- * Quatd::slerp(q0, q1, t)
- *
- * Quatd::spline(q0, q0, q1, q1, t)
- * ```
- * spline can smoothly connect rotations of multiple quaternions
- *
- * Three ways to get an element in Quaternion
- * ```
- * Quatf q(1,2,3,4);
- * std::cout << q.w << std::endl; // w=1, x=2, y=3, z=4
- * std::cout << q[0] << std::endl; // q[0]=1, q[1]=2, q[2]=3, q[3]=4
- * std::cout << q.at(0) << std::endl;
- * ```
- */
- template <typename _Tp>
- class Quat
- {
- static_assert(std::is_floating_point<_Tp>::value, "Quaternion only make sense with type of float or double");
- using value_type = _Tp;
- public:
- static constexpr _Tp CV_QUAT_EPS = (_Tp)1.e-6;
- static constexpr _Tp CV_QUAT_CONVERT_THRESHOLD = (_Tp)1.e-6;
- Quat();
- /**
- * @brief From Vec4d or Vec4f.
- */
- explicit Quat(const Vec<_Tp, 4> &coeff);
- /**
- * @brief from four numbers.
- */
- Quat(_Tp w, _Tp x, _Tp y, _Tp z);
- /**
- * @brief from an angle, axis. Axis will be normalized in this function. And
- * it generates
- * \f[q = [\cos\psi, u_x\sin\psi,u_y\sin\psi, u_z\sin\psi].\f]
- * where \f$\psi = \frac{\theta}{2}\f$, \f$\theta\f$ is the rotation angle.
- */
- static Quat<_Tp> createFromAngleAxis(const _Tp angle, const Vec<_Tp, 3> &axis);
- /**
- * @brief from a 3x3 rotation matrix.
- */
- static Quat<_Tp> createFromRotMat(InputArray R);
- /**
- * @brief from a rotation vector
- * \f$r\f$ has the form \f$\theta \cdot \boldsymbol{u}\f$, where \f$\theta\f$
- * represents rotation angle and \f$\boldsymbol{u}\f$ represents normalized rotation axis.
- *
- * Angle and axis could be easily derived as:
- * \f[
- * \begin{equation}
- * \begin{split}
- * \psi &= ||r||\\
- * \boldsymbol{u} &= \frac{r}{\theta}
- * \end{split}
- * \end{equation}
- * \f]
- * Then a quaternion can be calculated by
- * \f[q = [\cos\psi, \boldsymbol{u}\sin\psi]\f]
- * where \f$\psi = \theta / 2 \f$
- */
- static Quat<_Tp> createFromRvec(InputArray rvec);
- /**
- * @brief
- * from Euler angles
- *
- * A quaternion can be generated from Euler angles by combining the quaternion representations of the Euler rotations.
- *
- * For example, if we use intrinsic rotations in the order of X-Y-Z,\f$\theta_1 \f$ is rotation around the X-axis, \f$\theta_2 \f$ is rotation around the Y-axis,
- * \f$\theta_3 \f$ is rotation around the Z-axis. The final quaternion q can be calculated by
- *
- * \f[ {q} = q_{X, \theta_1} q_{Y, \theta_2} q_{Z, \theta_3}\f]
- * where \f$ q_{X, \theta_1} \f$ is created from @ref createFromXRot, \f$ q_{Y, \theta_2} \f$ is created from @ref createFromYRot,
- * \f$ q_{Z, \theta_3} \f$ is created from @ref createFromZRot.
- * @param angles the Euler angles in a vector of length 3
- * @param eulerAnglesType the convertion Euler angles type
- */
- static Quat<_Tp> createFromEulerAngles(const Vec<_Tp, 3> &angles, QuatEnum::EulerAnglesType eulerAnglesType);
- /**
- * @brief get a quaternion from a rotation about the Y-axis by \f$\theta\f$ .
- * \f[q = \cos(\theta/2)+0 i+ sin(\theta/2) j +0k \f]
- */
- static Quat<_Tp> createFromYRot(const _Tp theta);
- /**
- * @brief get a quaternion from a rotation about the X-axis by \f$\theta\f$ .
- * \f[q = \cos(\theta/2)+sin(\theta/2) i +0 j +0 k \f]
- */
- static Quat<_Tp> createFromXRot(const _Tp theta);
- /**
- * @brief get a quaternion from a rotation about the Z-axis by \f$\theta\f$.
- * \f[q = \cos(\theta/2)+0 i +0 j +sin(\theta/2) k \f]
- */
- static Quat<_Tp> createFromZRot(const _Tp theta);
- /**
- * @brief a way to get element.
- * @param index over a range [0, 3].
- *
- * A quaternion q
- *
- * q.at(0) is equivalent to q.w,
- *
- * q.at(1) is equivalent to q.x,
- *
- * q.at(2) is equivalent to q.y,
- *
- * q.at(3) is equivalent to q.z.
- */
- _Tp at(size_t index) const;
- /**
- * @brief return the conjugate of this quaternion.
- * \f[q.conjugate() = (w, -x, -y, -z).\f]
- */
- Quat<_Tp> conjugate() const;
- /**
- *
- * @brief return the value of exponential value.
- * \f[\exp(q) = e^w (\cos||\boldsymbol{v}||+ \frac{v}{||\boldsymbol{v}||})\sin||\boldsymbol{v}||\f]
- * where \f$\boldsymbol{v} = [x, y, z].\f$
- * @param q a quaternion.
- *
- * For example:
- * ```
- * Quatd q{1,2,3,4};
- * cout << exp(q) << endl;
- * ```
- */
- template <typename T>
- friend Quat<T> exp(const Quat<T> &q);
- /**
- * @brief return the value of exponential value.
- * \f[\exp(q) = e^w (\cos||\boldsymbol{v}||+ \frac{v}{||\boldsymbol{v}||}\sin||\boldsymbol{v}||)\f]
- * where \f$\boldsymbol{v} = [x, y, z].\f$
- *
- * For example
- * ```
- * Quatd q{1,2,3,4};
- * cout << q.exp() << endl;
- * ```
- */
- Quat<_Tp> exp() const;
- /**
- * @brief return the value of logarithm function.
- * \f[\ln(q) = \ln||q|| + \frac{\boldsymbol{v}}{||\boldsymbol{v}||}\arccos\frac{w}{||q||}.\f]
- * where \f$\boldsymbol{v} = [x, y, z].\f$
- * @param q a quaternion.
- * @param assumeUnit if QUAT_ASSUME_UNIT, q assume to be a unit quaternion and this function will save some computations.
- *
- * For example
- * ```
- * Quatd q1{1,2,3,4};
- * cout << log(q1) << endl;
- * ```
- */
- template <typename T>
- friend Quat<T> log(const Quat<T> &q, QuatAssumeType assumeUnit);
- /**
- * @brief return the value of logarithm function.
- * \f[\ln(q) = \ln||q|| + \frac{\boldsymbol{v}}{||\boldsymbol{v}||}\arccos\frac{w}{||q||}\f].
- * where \f$\boldsymbol{v} = [x, y, z].\f$
- * @param assumeUnit if QUAT_ASSUME_UNIT, this quaternion assume to be a unit quaternion and this function will save some computations.
- *
- * For example
- * ```
- * Quatd q(1,2,3,4);
- * q.log();
- *
- * QuatAssumeType assumeUnit = QUAT_ASSUME_UNIT;
- * Quatd q1(1,2,3,4);
- * q1.normalize().log(assumeUnit);
- * ```
- */
- Quat<_Tp> log(QuatAssumeType assumeUnit=QUAT_ASSUME_NOT_UNIT) const;
- /**
- * @brief return the value of power function with index \f$x\f$.
- * \f[q^x = ||q||(cos(x\theta) + \boldsymbol{u}sin(x\theta))).\f]
- * @param q a quaternion.
- * @param x index of exponentiation.
- * @param assumeUnit if QUAT_ASSUME_UNIT, quaternion q assume to be a unit quaternion and this function will save some computations.
- *
- * For example
- * ```
- * Quatd q(1,2,3,4);
- * power(q, 2.0);
- *
- * QuatAssumeType assumeUnit = QUAT_ASSUME_UNIT;
- * double angle = CV_PI;
- * Vec3d axis{0, 0, 1};
- * Quatd q1 = Quatd::createFromAngleAxis(angle, axis); //generate a unit quat by axis and angle
- * power(q1, 2.0, assumeUnit);//This assumeUnit means q1 is a unit quaternion.
- * ```
- * @note the type of the index should be the same as the quaternion.
- */
- template <typename T>
- friend Quat<T> power(const Quat<T> &q, const T x, QuatAssumeType assumeUnit);
- /**
- * @brief return the value of power function with index \f$x\f$.
- * \f[q^x = ||q||(\cos(x\theta) + \boldsymbol{u}\sin(x\theta))).\f]
- * @param x index of exponentiation.
- * @param assumeUnit if QUAT_ASSUME_UNIT, this quaternion assume to be a unit quaternion and this function will save some computations.
- *
- * For example
- * ```
- * Quatd q(1,2,3,4);
- * q.power(2.0);
- *
- * QuatAssumeType assumeUnit = QUAT_ASSUME_UNIT;
- * double angle = CV_PI;
- * Vec3d axis{0, 0, 1};
- * Quatd q1 = Quatd::createFromAngleAxis(angle, axis); //generate a unit quat by axis and angle
- * q1.power(2.0, assumeUnit); //This assumeUnt means q1 is a unit quaternion
- * ```
- */
- Quat<_Tp> power(const _Tp x, QuatAssumeType assumeUnit=QUAT_ASSUME_NOT_UNIT) const;
- /**
- * @brief return \f$\sqrt{q}\f$.
- * @param q a quaternion.
- * @param assumeUnit if QUAT_ASSUME_UNIT, quaternion q assume to be a unit quaternion and this function will save some computations.
- *
- * For example
- * ```
- * Quatf q(1,2,3,4);
- * sqrt(q);
- *
- * QuatAssumeType assumeUnit = QUAT_ASSUME_UNIT;
- * q = {1,0,0,0};
- * sqrt(q, assumeUnit); //This assumeUnit means q is a unit quaternion.
- * ```
- */
- template <typename T>
- friend Quat<T> sqrt(const Quat<T> &q, QuatAssumeType assumeUnit);
- /**
- * @brief return \f$\sqrt{q}\f$.
- * @param assumeUnit if QUAT_ASSUME_UNIT, this quaternion assume to be a unit quaternion and this function will save some computations.
- *
- * For example
- * ```
- * Quatf q(1,2,3,4);
- * q.sqrt();
- *
- * QuatAssumeType assumeUnit = QUAT_ASSUME_UNIT;
- * q = {1,0,0,0};
- * q.sqrt(assumeUnit); //This assumeUnit means q is a unit quaternion
- * ```
- */
- Quat<_Tp> sqrt(QuatAssumeType assumeUnit=QUAT_ASSUME_NOT_UNIT) const;
- /**
- * @brief return the value of power function with quaternion \f$q\f$.
- * \f[p^q = e^{q\ln(p)}.\f]
- * @param p base quaternion of power function.
- * @param q index quaternion of power function.
- * @param assumeUnit if QUAT_ASSUME_UNIT, quaternion \f$p\f$ assume to be a unit quaternion and this function will save some computations.
- *
- * For example
- * ```
- * Quatd p(1,2,3,4);
- * Quatd q(5,6,7,8);
- * power(p, q);
- *
- * QuatAssumeType assumeUnit = QUAT_ASSUME_UNIT;
- * p = p.normalize();
- * power(p, q, assumeUnit); //This assumeUnit means p is a unit quaternion
- * ```
- */
- template <typename T>
- friend Quat<T> power(const Quat<T> &p, const Quat<T> &q, QuatAssumeType assumeUnit);
- /**
- * @brief return the value of power function with quaternion \f$q\f$.
- * \f[p^q = e^{q\ln(p)}.\f]
- * @param q index quaternion of power function.
- * @param assumeUnit if QUAT_ASSUME_UNIT, this quaternion assume to be a unit quaternion and this function will save some computations.
- *
- * For example
- * ```
- * Quatd p(1,2,3,4);
- * Quatd q(5,6,7,8);
- * p.power(q);
- *
- * QuatAssumeType assumeUnit = QUAT_ASSUME_UNIT;
- * p = p.normalize();
- * p.power(q, assumeUnit); //This assumeUnit means p is a unit quaternion
- * ```
- */
- Quat<_Tp> power(const Quat<_Tp> &q, QuatAssumeType assumeUnit=QUAT_ASSUME_NOT_UNIT) const;
- /**
- * @brief return the crossProduct between \f$p = (a, b, c, d) = (a, \boldsymbol{u})\f$ and \f$q = (w, x, y, z) = (w, \boldsymbol{v})\f$.
- * \f[p \times q = \frac{pq- qp}{2}\f]
- * \f[p \times q = \boldsymbol{u} \times \boldsymbol{v}\f]
- * \f[p \times q = (cz-dy)i + (dx-bz)j + (by-xc)k \f]
- *
- * For example
- * ```
- * Quatd q{1,2,3,4};
- * Quatd p{5,6,7,8};
- * crossProduct(p, q);
- * ```
- */
- template <typename T>
- friend Quat<T> crossProduct(const Quat<T> &p, const Quat<T> &q);
- /**
- * @brief return the crossProduct between \f$p = (a, b, c, d) = (a, \boldsymbol{u})\f$ and \f$q = (w, x, y, z) = (w, \boldsymbol{v})\f$.
- * \f[p \times q = \frac{pq- qp}{2}.\f]
- * \f[p \times q = \boldsymbol{u} \times \boldsymbol{v}.\f]
- * \f[p \times q = (cz-dy)i + (dx-bz)j + (by-xc)k. \f]
- *
- * For example
- * ```
- * Quatd q{1,2,3,4};
- * Quatd p{5,6,7,8};
- * p.crossProduct(q)
- * ```
- */
- Quat<_Tp> crossProduct(const Quat<_Tp> &q) const;
- /**
- * @brief return the norm of quaternion.
- * \f[||q|| = \sqrt{w^2 + x^2 + y^2 + z^2}.\f]
- */
- _Tp norm() const;
- /**
- * @brief return a normalized \f$p\f$.
- * \f[p = \frac{q}{||q||}\f]
- * where \f$p\f$ satisfies \f$(p.x)^2 + (p.y)^2 + (p.z)^2 + (p.w)^2 = 1.\f$
- */
- Quat<_Tp> normalize() const;
- /**
- * @brief return \f$q^{-1}\f$ which is an inverse of \f$q\f$
- * which satisfies \f$q * q^{-1} = 1\f$.
- * @param q a quaternion.
- * @param assumeUnit if QUAT_ASSUME_UNIT, quaternion q assume to be a unit quaternion and this function will save some computations.
- *
- * For example
- * ```
- * Quatd q(1,2,3,4);
- * inv(q);
- *
- * QuatAssumeType assumeUnit = QUAT_ASSUME_UNIT;
- * q = q.normalize();
- * inv(q, assumeUnit);//This assumeUnit means p is a unit quaternion
- * ```
- */
- template <typename T>
- friend Quat<T> inv(const Quat<T> &q, QuatAssumeType assumeUnit);
- /**
- * @brief return \f$q^{-1}\f$ which is an inverse of \f$q\f$
- * satisfying \f$q * q^{-1} = 1\f$.
- * @param assumeUnit if QUAT_ASSUME_UNIT, quaternion q assume to be a unit quaternion and this function will save some computations.
- *
- * For example
- * ```
- * Quatd q(1,2,3,4);
- * q.inv();
- *
- * QuatAssumeType assumeUnit = QUAT_ASSUME_UNIT;
- * q = q.normalize();
- * q.inv(assumeUnit); //assumeUnit means p is a unit quaternion
- * ```
- */
- Quat<_Tp> inv(QuatAssumeType assumeUnit=QUAT_ASSUME_NOT_UNIT) const;
- /**
- * @brief return sinh value of quaternion q, sinh could be calculated as:
- * \f[\sinh(p) = \sin(w)\cos(||\boldsymbol{v}||) + \cosh(w)\frac{v}{||\boldsymbol{v}||}\sin||\boldsymbol{v}||\f]
- * where \f$\boldsymbol{v} = [x, y, z].\f$
- * @param q a quaternion.
- *
- * For example
- * ```
- * Quatd q(1,2,3,4);
- * sinh(q);
- * ```
- */
- template <typename T>
- friend Quat<T> sinh(const Quat<T> &q);
- /**
- * @brief return sinh value of this quaternion, sinh could be calculated as:
- * \f$\sinh(p) = \sin(w)\cos(||\boldsymbol{v}||) + \cosh(w)\frac{v}{||\boldsymbol{v}||}\sin||\boldsymbol{v}||\f$
- * where \f$\boldsymbol{v} = [x, y, z].\f$
- *
- * For example
- * ```
- * Quatd q(1,2,3,4);
- * q.sinh();
- * ```
- */
- Quat<_Tp> sinh() const;
- /**
- * @brief return cosh value of quaternion q, cosh could be calculated as:
- * \f[\cosh(p) = \cosh(w) * \cos(||\boldsymbol{v}||) + \sinh(w)\frac{\boldsymbol{v}}{||\boldsymbol{v}||}\sin(||\boldsymbol{v}||)\f]
- * where \f$\boldsymbol{v} = [x, y, z].\f$
- * @param q a quaternion.
- *
- * For example
- * ```
- * Quatd q(1,2,3,4);
- * cosh(q);
- * ```
- */
- template <typename T>
- friend Quat<T> cosh(const Quat<T> &q);
- /**
- * @brief return cosh value of this quaternion, cosh could be calculated as:
- * \f[\cosh(p) = \cosh(w) * \cos(||\boldsymbol{v}||) + \sinh(w)\frac{\boldsymbol{v}}{||\boldsymbol{v}||}sin(||\boldsymbol{v}||)\f]
- * where \f$\boldsymbol{v} = [x, y, z].\f$
- *
- * For example
- * ```
- * Quatd q(1,2,3,4);
- * q.cosh();
- * ```
- */
- Quat<_Tp> cosh() const;
- /**
- * @brief return tanh value of quaternion q, tanh could be calculated as:
- * \f[ \tanh(q) = \frac{\sinh(q)}{\cosh(q)}.\f]
- * @param q a quaternion.
- *
- * For example
- * ```
- * Quatd q(1,2,3,4);
- * tanh(q);
- * ```
- * @sa sinh, cosh
- */
- template <typename T>
- friend Quat<T> tanh(const Quat<T> &q);
- /**
- * @brief return tanh value of this quaternion, tanh could be calculated as:
- * \f[ \tanh(q) = \frac{\sinh(q)}{\cosh(q)}.\f]
- *
- * For example
- * ```
- * Quatd q(1,2,3,4);
- * q.tanh();
- * ```
- * @sa sinh, cosh
- */
- Quat<_Tp> tanh() const;
- /**
- * @brief return tanh value of quaternion q, sin could be calculated as:
- * \f[\sin(p) = \sin(w) * \cosh(||\boldsymbol{v}||) + \cos(w)\frac{\boldsymbol{v}}{||\boldsymbol{v}||}\sinh(||\boldsymbol{v}||)\f]
- * where \f$\boldsymbol{v} = [x, y, z].\f$
- * @param q a quaternion.
- *
- * For example
- * ```
- * Quatd q(1,2,3,4);
- * sin(q);
- * ```
- */
- template <typename T>
- friend Quat<T> sin(const Quat<T> &q);
- /**
- * @brief return sin value of this quaternion, sin could be calculated as:
- * \f[\sin(p) = \sin(w) * \cosh(||\boldsymbol{v}||) + \cos(w)\frac{\boldsymbol{v}}{||\boldsymbol{v}||}\sinh(||\boldsymbol{v}||)\f]
- * where \f$\boldsymbol{v} = [x, y, z].\f$
- *
- * For example
- * ```
- * Quatd q(1,2,3,4);
- * q.sin();
- * ```
- */
- Quat<_Tp> sin() const;
- /**
- * @brief return sin value of quaternion q, cos could be calculated as:
- * \f[\cos(p) = \cos(w) * \cosh(||\boldsymbol{v}||) - \sin(w)\frac{\boldsymbol{v}}{||\boldsymbol{v}||}\sinh(||\boldsymbol{v}||)\f]
- * where \f$\boldsymbol{v} = [x, y, z].\f$
- * @param q a quaternion.
- *
- * For example
- * ```
- * Quatd q(1,2,3,4);
- * cos(q);
- * ```
- */
- template <typename T>
- friend Quat<T> cos(const Quat<T> &q);
- /**
- * @brief return cos value of this quaternion, cos could be calculated as:
- * \f[\cos(p) = \cos(w) * \cosh(||\boldsymbol{v}||) - \sin(w)\frac{\boldsymbol{v}}{||\boldsymbol{v}||}\sinh(||\boldsymbol{v}||)\f]
- * where \f$\boldsymbol{v} = [x, y, z].\f$
- *
- * For example
- * ```
- * Quatd q(1,2,3,4);
- * q.cos();
- * ```
- */
- Quat<_Tp> cos() const;
- /**
- * @brief return tan value of quaternion q, tan could be calculated as:
- * \f[\tan(q) = \frac{\sin(q)}{\cos(q)}.\f]
- * @param q a quaternion.
- *
- * For example
- * ```
- * Quatd q(1,2,3,4);
- * tan(q);
- * ```
- */
- template <typename T>
- friend Quat<T> tan(const Quat<T> &q);
- /**
- * @brief return tan value of this quaternion, tan could be calculated as:
- * \f[\tan(q) = \frac{\sin(q)}{\cos(q)}.\f]
- *
- * For example
- * ```
- * Quatd q(1,2,3,4);
- * q.tan();
- * ```
- */
- Quat<_Tp> tan() const;
- /**
- * @brief return arcsin value of quaternion q, arcsin could be calculated as:
- * \f[\arcsin(q) = -\frac{\boldsymbol{v}}{||\boldsymbol{v}||}arcsinh(q\frac{\boldsymbol{v}}{||\boldsymbol{v}||})\f]
- * where \f$\boldsymbol{v} = [x, y, z].\f$
- * @param q a quaternion.
- *
- * For example
- * ```
- * Quatd q(1,2,3,4);
- * asin(q);
- * ```
- */
- template <typename T>
- friend Quat<T> asin(const Quat<T> &q);
- /**
- * @brief return arcsin value of this quaternion, arcsin could be calculated as:
- * \f[\arcsin(q) = -\frac{\boldsymbol{v}}{||\boldsymbol{v}||}arcsinh(q\frac{\boldsymbol{v}}{||\boldsymbol{v}||})\f]
- * where \f$\boldsymbol{v} = [x, y, z].\f$
- *
- * For example
- * ```
- * Quatd q(1,2,3,4);
- * q.asin();
- * ```
- */
- Quat<_Tp> asin() const;
- /**
- * @brief return arccos value of quaternion q, arccos could be calculated as:
- * \f[\arccos(q) = -\frac{\boldsymbol{v}}{||\boldsymbol{v}||}arccosh(q)\f]
- * where \f$\boldsymbol{v} = [x, y, z].\f$
- * @param q a quaternion.
- *
- * For example
- * ```
- * Quatd q(1,2,3,4);
- * acos(q);
- * ```
- */
- template <typename T>
- friend Quat<T> acos(const Quat<T> &q);
- /**
- * @brief return arccos value of this quaternion, arccos could be calculated as:
- * \f[\arccos(q) = -\frac{\boldsymbol{v}}{||\boldsymbol{v}||}arccosh(q)\f]
- * where \f$\boldsymbol{v} = [x, y, z].\f$
- *
- * For example
- * ```
- * Quatd q(1,2,3,4);
- * q.acos();
- * ```
- */
- Quat<_Tp> acos() const;
- /**
- * @brief return arctan value of quaternion q, arctan could be calculated as:
- * \f[\arctan(q) = -\frac{\boldsymbol{v}}{||\boldsymbol{v}||}arctanh(q\frac{\boldsymbol{v}}{||\boldsymbol{v}||})\f]
- * where \f$\boldsymbol{v} = [x, y, z].\f$
- * @param q a quaternion.
- *
- * For example
- * ```
- * Quatd q(1,2,3,4);
- * atan(q);
- * ```
- */
- template <typename T>
- friend Quat<T> atan(const Quat<T> &q);
- /**
- * @brief return arctan value of this quaternion, arctan could be calculated as:
- * \f[\arctan(q) = -\frac{\boldsymbol{v}}{||\boldsymbol{v}||}arctanh(q\frac{\boldsymbol{v}}{||\boldsymbol{v}||})\f]
- * where \f$\boldsymbol{v} = [x, y, z].\f$
- *
- * For example
- * ```
- * Quatd q(1,2,3,4);
- * q.atan();
- * ```
- */
- Quat<_Tp> atan() const;
- /**
- * @brief return arcsinh value of quaternion q, arcsinh could be calculated as:
- * \f[arcsinh(q) = \ln(q + \sqrt{q^2 + 1})\f].
- * @param q a quaternion.
- *
- * For example
- * ```
- * Quatd q(1,2,3,4);
- * asinh(q);
- * ```
- */
- template <typename T>
- friend Quat<T> asinh(const Quat<T> &q);
- /**
- * @brief return arcsinh value of this quaternion, arcsinh could be calculated as:
- * \f[arcsinh(q) = \ln(q + \sqrt{q^2 + 1})\f].
- *
- * For example
- * ```
- * Quatd q(1,2,3,4);
- * q.asinh();
- * ```
- */
- Quat<_Tp> asinh() const;
- /**
- * @brief return arccosh value of quaternion q, arccosh could be calculated as:
- * \f[arccosh(q) = \ln(q + \sqrt{q^2 - 1})\f].
- * @param q a quaternion.
- *
- * For example
- * ```
- * Quatd q(1,2,3,4);
- * acosh(q);
- * ```
- */
- template <typename T>
- friend Quat<T> acosh(const Quat<T> &q);
- /**
- * @brief return arccosh value of this quaternion, arccosh could be calculated as:
- * \f[arcosh(q) = \ln(q + \sqrt{q^2 - 1})\f].
- *
- * For example
- * ```
- * Quatd q(1,2,3,4);
- * q.acosh();
- * ```
- */
- Quat<_Tp> acosh() const;
- /**
- * @brief return arctanh value of quaternion q, arctanh could be calculated as:
- * \f[arctanh(q) = \frac{\ln(q + 1) - \ln(1 - q)}{2}\f].
- * @param q a quaternion.
- *
- * For example
- * ```
- * Quatd q(1,2,3,4);
- * atanh(q);
- * ```
- */
- template <typename T>
- friend Quat<T> atanh(const Quat<T> &q);
- /**
- * @brief return arctanh value of this quaternion, arctanh could be calculated as:
- * \f[arcsinh(q) = \frac{\ln(q + 1) - \ln(1 - q)}{2}\f].
- *
- * For example
- * ```
- * Quatd q(1,2,3,4);
- * q.atanh();
- * ```
- */
- Quat<_Tp> atanh() const;
- /**
- * @brief return true if this quaternion is a unit quaternion.
- * @param eps tolerance scope of normalization. The eps could be defined as
- *
- * \f[eps = |1 - dotValue|\f] where \f[dotValue = (this.w^2 + this.x^2 + this,y^2 + this.z^2).\f]
- * And this function will consider it is normalized when the dotValue over a range \f$[1-eps, 1+eps]\f$.
- */
- bool isNormal(_Tp eps=CV_QUAT_EPS) const;
- /**
- * @brief to throw an error if this quaternion is not a unit quaternion.
- * @param eps tolerance scope of normalization.
- * @sa isNormal
- */
- void assertNormal(_Tp eps=CV_QUAT_EPS) const;
- /**
- * @brief transform a quaternion to a 3x3 rotation matrix.
- * @param assumeUnit if QUAT_ASSUME_UNIT, this quaternion assume to be a unit quaternion and
- * this function will save some computations. Otherwise, this function will normalize this
- * quaternion at first then do the transformation.
- *
- * @note Matrix A which is to be rotated should have the form
- * \f[\begin{bmatrix}
- * x_0& x_1& x_2&...&x_n\\
- * y_0& y_1& y_2&...&y_n\\
- * z_0& z_1& z_2&...&z_n
- * \end{bmatrix}\f]
- * where the same subscript represents a point. The shape of A assume to be [3, n]
- * The points matrix A can be rotated by toRotMat3x3() * A.
- * The result has 3 rows and n columns too.
- * For example
- * ```
- * double angle = CV_PI;
- * Vec3d axis{0,0,1};
- * Quatd q_unit = Quatd::createFromAngleAxis(angle, axis); //quaternion could also be get by interpolation by two or more quaternions.
- *
- * //assume there is two points (1,0,0) and (1,0,1) to be rotated
- * Mat pointsA = (Mat_<double>(2, 3) << 1,0,0,1,0,1);
- * //change the shape
- * pointsA = pointsA.t();
- * // rotate 180 degrees around the z axis
- * Mat new_point = q_unit.toRotMat3x3() * pointsA;
- * // print two points
- * cout << new_point << endl;
- * ```
- */
- Matx<_Tp, 3, 3> toRotMat3x3(QuatAssumeType assumeUnit=QUAT_ASSUME_NOT_UNIT) const;
- /**
- * @brief transform a quaternion to a 4x4 rotation matrix.
- * @param assumeUnit if QUAT_ASSUME_UNIT, this quaternion assume to be a unit quaternion and
- * this function will save some computations. Otherwise, this function will normalize this
- * quaternion at first then do the transformation.
- *
- * The operations is similar as toRotMat3x3
- * except that the points matrix should have the form
- * \f[\begin{bmatrix}
- * x_0& x_1& x_2&...&x_n\\
- * y_0& y_1& y_2&...&y_n\\
- * z_0& z_1& z_2&...&z_n\\
- * 0&0&0&...&0
- * \end{bmatrix}\f]
- *
- * @sa toRotMat3x3
- */
- Matx<_Tp, 4, 4> toRotMat4x4(QuatAssumeType assumeUnit=QUAT_ASSUME_NOT_UNIT) const;
- /**
- * @brief transform the this quaternion to a Vec<T, 4>.
- *
- * For example
- * ```
- * Quatd q(1,2,3,4);
- * q.toVec();
- * ```
- */
- Vec<_Tp, 4> toVec() const;
- /**
- * @brief transform this quaternion to a Rotation vector.
- * @param assumeUnit if QUAT_ASSUME_UNIT, this quaternion assume to be a unit quaternion and
- * this function will save some computations.
- * Rotation vector rVec is defined as:
- * \f[ rVec = [\theta v_x, \theta v_y, \theta v_z]\f]
- * where \f$\theta\f$ represents rotation angle, and \f$\boldsymbol{v}\f$ represents the normalized rotation axis.
- *
- * For example
- * ```
- * Quatd q(1,2,3,4);
- * q.toRotVec();
- *
- * QuatAssumeType assumeUnit = QUAT_ASSUME_UNIT;
- * q.normalize().toRotVec(assumeUnit); //answer is same as q.toRotVec().
- * ```
- */
- Vec<_Tp, 3> toRotVec(QuatAssumeType assumeUnit=QUAT_ASSUME_NOT_UNIT) const;
- /**
- * @brief get the angle of quaternion, it returns the rotation angle.
- * @param assumeUnit if QUAT_ASSUME_UNIT, this quaternion assume to be a unit quaternion and
- * this function will save some computations.
- * \f[\psi = 2 *arccos(\frac{w}{||q||})\f]
- *
- * For example
- * ```
- * Quatd q(1,2,3,4);
- * q.getAngle();
- *
- * QuatAssumeType assumeUnit = QUAT_ASSUME_UNIT;
- * q.normalize().getAngle(assumeUnit);//same as q.getAngle().
- * ```
- * @note It always return the value between \f$[0, 2\pi]\f$.
- */
- _Tp getAngle(QuatAssumeType assumeUnit=QUAT_ASSUME_NOT_UNIT) const;
- /**
- * @brief get the axis of quaternion, it returns a vector of length 3.
- * @param assumeUnit if QUAT_ASSUME_UNIT, this quaternion assume to be a unit quaternion and
- * this function will save some computations.
- *
- * the unit axis \f$\boldsymbol{u}\f$ is defined by
- * \f[\begin{equation}
- * \begin{split}
- * \boldsymbol{v}
- * &= \boldsymbol{u} ||\boldsymbol{v}||\\
- * &= \boldsymbol{u}||q||sin(\frac{\theta}{2})
- * \end{split}
- * \end{equation}\f]
- * where \f$v=[x, y ,z]\f$ and \f$\theta\f$ represents rotation angle.
- *
- *
- * For example
- * ```
- * Quatd q(1,2,3,4);
- * q.getAxis();
- *
- * QuatAssumeType assumeUnit = QUAT_ASSUME_UNIT;
- * q.normalize().getAxis(assumeUnit);//same as q.getAxis()
- * ```
- */
- Vec<_Tp, 3> getAxis(QuatAssumeType assumeUnit=QUAT_ASSUME_NOT_UNIT) const;
- /**
- * @brief return the dot between quaternion \f$q\f$ and this quaternion.
- *
- * dot(p, q) is a good metric of how close the quaternions are.
- * Indeed, consider the unit quaternion difference \f$p^{-1} * q\f$, its real part is dot(p, q).
- * At the same time its real part is equal to \f$\cos(\beta/2)\f$ where \f$\beta\f$ is
- * an angle of rotation between p and q, i.e.,
- * Therefore, the closer dot(p, q) to 1,
- * the smaller rotation between them.
- * \f[p \cdot q = p.w \cdot q.w + p.x \cdot q.x + p.y \cdot q.y + p.z \cdot q.z\f]
- * @param q the other quaternion.
- *
- * For example
- * ```
- * Quatd q(1,2,3,4);
- * Quatd p(5,6,7,8);
- * p.dot(q);
- * ```
- */
- _Tp dot(Quat<_Tp> q) const;
- /**
- * @brief To calculate the interpolation from \f$q_0\f$ to \f$q_1\f$ by Linear Interpolation(Nlerp)
- * For two quaternions, this interpolation curve can be displayed as:
- * \f[Lerp(q_0, q_1, t) = (1 - t)q_0 + tq_1.\f]
- * Obviously, the lerp will interpolate along a straight line if we think of \f$q_0\f$ and \f$q_1\f$ as a vector
- * in a two-dimensional space. When \f$t = 0\f$, it returns \f$q_0\f$ and when \f$t= 1\f$, it returns \f$q_1\f$.
- * \f$t\f$ should to be ranged in \f$[0, 1]\f$ normally.
- * @param q0 a quaternion used in linear interpolation.
- * @param q1 a quaternion used in linear interpolation.
- * @param t percent of vector \f$\overrightarrow{q_0q_1}\f$ over a range [0, 1].
- * @note it returns a non-unit quaternion.
- */
- static Quat<_Tp> lerp(const Quat<_Tp> &q0, const Quat &q1, const _Tp t);
- /**
- * @brief To calculate the interpolation from \f$q_0\f$ to \f$q_1\f$ by Normalized Linear Interpolation(Nlerp).
- * it returns a normalized quaternion of Linear Interpolation(Lerp).
- * \f[ Nlerp(q_0, q_1, t) = \frac{(1 - t)q_0 + tq_1}{||(1 - t)q_0 + tq_1||}.\f]
- * The interpolation will always choose the shortest path but the constant speed is not guaranteed.
- * @param q0 a quaternion used in normalized linear interpolation.
- * @param q1 a quaternion used in normalized linear interpolation.
- * @param t percent of vector \f$\overrightarrow{q_0q_1}\f$ over a range [0, 1].
- * @param assumeUnit if QUAT_ASSUME_UNIT, all input quaternions assume to be unit quaternion. Otherwise, all inputs
- quaternion will be normalized inside the function.
- * @sa lerp
- */
- static Quat<_Tp> nlerp(const Quat<_Tp> &q0, const Quat &q1, const _Tp t, QuatAssumeType assumeUnit=QUAT_ASSUME_NOT_UNIT);
- /**
- @brief To calculate the interpolation between \f$q_0\f$ and \f$q_1\f$ by Spherical Linear
- Interpolation(Slerp), which can be defined as:
- \f[ Slerp(q_0, q_1, t) = \frac{\sin((1-t)\theta)}{\sin(\theta)}q_0 + \frac{\sin(t\theta)}{\sin(\theta)}q_1\f]
- where \f$\theta\f$ can be calculated as:
- \f[\theta=cos^{-1}(q_0\cdot q_1)\f]
- resulting from the both of their norm is unit.
- @param q0 a quaternion used in Slerp.
- @param q1 a quaternion used in Slerp.
- @param t percent of angle between \f$q_0\f$ and \f$q_1\f$ over a range [0, 1].
- @param assumeUnit if QUAT_ASSUME_UNIT, all input quaternions assume to be unit quaternions. Otherwise, all input
- quaternions will be normalized inside the function.
- @param directChange if QUAT_ASSUME_UNIT, the interpolation will choose the nearest path.
- @note If the interpolation angle is small, the error between Nlerp and Slerp is not so large. To improve efficiency and
- avoid zero division error, we use Nlerp instead of Slerp.
- */
- static Quat<_Tp> slerp(const Quat<_Tp> &q0, const Quat &q1, const _Tp t, QuatAssumeType assumeUnit=QUAT_ASSUME_NOT_UNIT, bool directChange=true);
- /**
- * @brief To calculate the interpolation between \f$q_0\f$,\f$q_1\f$,\f$q_2\f$,\f$q_3\f$ by Spherical and quadrangle(Squad). This could be defined as:
- * \f[Squad(q_i, s_i, s_{i+1}, q_{i+1}, t) = Slerp(Slerp(q_i, q_{i+1}, t), Slerp(s_i, s_{i+1}, t), 2t(1-t))\f]
- * where
- * \f[s_i = q_i\exp(-\frac{\log(q^*_iq_{i+1}) + \log(q^*_iq_{i-1})}{4})\f]
- *
- * The Squad expression is analogous to the \f$B\acute{e}zier\f$ curve, but involves spherical linear
- * interpolation instead of simple linear interpolation. Each \f$s_i\f$ needs to be calculated by three
- * quaternions.
- *
- * @param q0 the first quaternion.
- * @param s0 the second quaternion.
- * @param s1 the third quaternion.
- * @param q1 thr fourth quaternion.
- * @param t interpolation parameter of quadratic and linear interpolation over a range \f$[0, 1]\f$.
- * @param assumeUnit if QUAT_ASSUME_UNIT, all input quaternions assume to be unit quaternion. Otherwise, all input
- * quaternions will be normalized inside the function.
- * @param directChange if QUAT_ASSUME_UNIT, squad will find the nearest path to interpolate.
- * @sa interPoint, spline
- */
- static Quat<_Tp> squad(const Quat<_Tp> &q0, const Quat<_Tp> &s0,
- const Quat<_Tp> &s1, const Quat<_Tp> &q1,
- const _Tp t, QuatAssumeType assumeUnit=QUAT_ASSUME_NOT_UNIT,
- bool directChange=true);
- /**
- * @brief This is the part calculation of squad.
- * To calculate the intermedia quaternion \f$s_i\f$ between each three quaternion
- * \f[s_i = q_i\exp(-\frac{\log(q^*_iq_{i+1}) + \log(q^*_iq_{i-1})}{4}).\f]
- * @param q0 the first quaternion.
- * @param q1 the second quaternion.
- * @param q2 the third quaternion.
- * @param assumeUnit if QUAT_ASSUME_UNIT, all input quaternions assume to be unit quaternion. Otherwise, all input
- * quaternions will be normalized inside the function.
- * @sa squad
- */
- static Quat<_Tp> interPoint(const Quat<_Tp> &q0, const Quat<_Tp> &q1,
- const Quat<_Tp> &q2, QuatAssumeType assumeUnit=QUAT_ASSUME_NOT_UNIT);
- /**
- * @brief to calculate a quaternion which is the result of a \f$C^1\f$ continuous
- * spline curve constructed by squad at the ratio t. Here, the interpolation values are
- * between \f$q_1\f$ and \f$q_2\f$. \f$q_0\f$ and \f$q_2\f$ are used to ensure the \f$C^1\f$
- * continuity. if t = 0, it returns \f$q_1\f$, if t = 1, it returns \f$q_2\f$.
- * @param q0 the first input quaternion to ensure \f$C^1\f$ continuity.
- * @param q1 the second input quaternion.
- * @param q2 the third input quaternion.
- * @param q3 the fourth input quaternion the same use of \f$q1\f$.
- * @param t ratio over a range [0, 1].
- * @param assumeUnit if QUAT_ASSUME_UNIT, \f$q_0, q_1, q_2, q_3\f$ assume to be unit quaternion. Otherwise, all input
- * quaternions will be normalized inside the function.
- *
- * For example:
- *
- * If there are three double quaternions \f$v_0, v_1, v_2\f$ waiting to be interpolated.
- *
- * Interpolation between \f$v_0\f$ and \f$v_1\f$ with a ratio \f$t_0\f$ could be calculated as
- * ```
- * Quatd::spline(v0, v0, v1, v2, t0);
- * ```
- * Interpolation between \f$v_1\f$ and \f$v_2\f$ with a ratio \f$t_0\f$ could be calculated as
- * ```
- * Quatd::spline(v0, v1, v2, v2, t0);
- * ```
- * @sa squad, slerp
- */
- static Quat<_Tp> spline(const Quat<_Tp> &q0, const Quat<_Tp> &q1,
- const Quat<_Tp> &q2, const Quat<_Tp> &q3,
- const _Tp t, QuatAssumeType assumeUnit=QUAT_ASSUME_NOT_UNIT);
- /**
- * @brief Return opposite quaternion \f$-p\f$
- * which satisfies \f$p + (-p) = 0.\f$
- *
- * For example
- * ```
- * Quatd q{1, 2, 3, 4};
- * std::cout << -q << std::endl; // [-1, -2, -3, -4]
- * ```
- */
- Quat<_Tp> operator-() const;
- /**
- * @brief return true if two quaternions p and q are nearly equal, i.e. when the absolute
- * value of each \f$p_i\f$ and \f$q_i\f$ is less than CV_QUAT_EPS.
- */
- bool operator==(const Quat<_Tp>&) const;
- /**
- * @brief Addition operator of two quaternions p and q.
- * It returns a new quaternion that each value is the sum of \f$p_i\f$ and \f$q_i\f$.
- *
- * For example
- * ```
- * Quatd p{1, 2, 3, 4};
- * Quatd q{5, 6, 7, 8};
- * std::cout << p + q << std::endl; //[6, 8, 10, 12]
- * ```
- */
- Quat<_Tp> operator+(const Quat<_Tp>&) const;
- /**
- * @brief Addition assignment operator of two quaternions p and q.
- * It adds right operand to the left operand and assign the result to left operand.
- *
- * For example
- * ```
- * Quatd p{1, 2, 3, 4};
- * Quatd q{5, 6, 7, 8};
- * p += q; // equivalent to p = p + q
- * std::cout << p << std::endl; //[6, 8, 10, 12]
- *
- * ```
- */
- Quat<_Tp>& operator+=(const Quat<_Tp>&);
- /**
- * @brief Subtraction operator of two quaternions p and q.
- * It returns a new quaternion that each value is the sum of \f$p_i\f$ and \f$-q_i\f$.
- *
- * For example
- * ```
- * Quatd p{1, 2, 3, 4};
- * Quatd q{5, 6, 7, 8};
- * std::cout << p - q << std::endl; //[-4, -4, -4, -4]
- * ```
- */
- Quat<_Tp> operator-(const Quat<_Tp>&) const;
- /**
- * @brief Subtraction assignment operator of two quaternions p and q.
- * It subtracts right operand from the left operand and assign the result to left operand.
- *
- * For example
- * ```
- * Quatd p{1, 2, 3, 4};
- * Quatd q{5, 6, 7, 8};
- * p -= q; // equivalent to p = p - q
- * std::cout << p << std::endl; //[-4, -4, -4, -4]
- *
- * ```
- */
- Quat<_Tp>& operator-=(const Quat<_Tp>&);
- /**
- * @brief Multiplication assignment operator of two quaternions q and p.
- * It multiplies right operand with the left operand and assign the result to left operand.
- *
- * Rule of quaternion multiplication:
- * \f[
- * \begin{equation}
- * \begin{split}
- * p * q &= [p_0, \boldsymbol{u}]*[q_0, \boldsymbol{v}]\\
- * &=[p_0q_0 - \boldsymbol{u}\cdot \boldsymbol{v}, p_0\boldsymbol{v} + q_0\boldsymbol{u}+ \boldsymbol{u}\times \boldsymbol{v}].
- * \end{split}
- * \end{equation}
- * \f]
- * where \f$\cdot\f$ means dot product and \f$\times \f$ means cross product.
- *
- * For example
- * ```
- * Quatd p{1, 2, 3, 4};
- * Quatd q{5, 6, 7, 8};
- * p *= q; // equivalent to p = p * q
- * std::cout << p << std::endl; //[-60, 12, 30, 24]
- * ```
- */
- Quat<_Tp>& operator*=(const Quat<_Tp>&);
- /**
- * @brief Multiplication assignment operator of a quaternions and a scalar.
- * It multiplies right operand with the left operand and assign the result to left operand.
- *
- * Rule of quaternion multiplication with a scalar:
- * \f[
- * \begin{equation}
- * \begin{split}
- * p * s &= [w, x, y, z] * s\\
- * &=[w * s, x * s, y * s, z * s].
- * \end{split}
- * \end{equation}
- * \f]
- *
- * For example
- * ```
- * Quatd p{1, 2, 3, 4};
- * double s = 2.0;
- * p *= s; // equivalent to p = p * s
- * std::cout << p << std::endl; //[2.0, 4.0, 6.0, 8.0]
- * ```
- * @note the type of scalar should be equal to the quaternion.
- */
- Quat<_Tp>& operator*=(const _Tp s);
- /**
- * @brief Multiplication operator of two quaternions q and p.
- * Multiplies values on either side of the operator.
- *
- * Rule of quaternion multiplication:
- * \f[
- * \begin{equation}
- * \begin{split}
- * p * q &= [p_0, \boldsymbol{u}]*[q_0, \boldsymbol{v}]\\
- * &=[p_0q_0 - \boldsymbol{u}\cdot \boldsymbol{v}, p_0\boldsymbol{v} + q_0\boldsymbol{u}+ \boldsymbol{u}\times \boldsymbol{v}].
- * \end{split}
- * \end{equation}
- * \f]
- * where \f$\cdot\f$ means dot product and \f$\times \f$ means cross product.
- *
- * For example
- * ```
- * Quatd p{1, 2, 3, 4};
- * Quatd q{5, 6, 7, 8};
- * std::cout << p * q << std::endl; //[-60, 12, 30, 24]
- * ```
- */
- Quat<_Tp> operator*(const Quat<_Tp>&) const;
- /**
- * @brief Division operator of a quaternions and a scalar.
- * It divides left operand with the right operand and assign the result to left operand.
- *
- * Rule of quaternion division with a scalar:
- * \f[
- * \begin{equation}
- * \begin{split}
- * p / s &= [w, x, y, z] / s\\
- * &=[w/s, x/s, y/s, z/s].
- * \end{split}
- * \end{equation}
- * \f]
- *
- * For example
- * ```
- * Quatd p{1, 2, 3, 4};
- * double s = 2.0;
- * p /= s; // equivalent to p = p / s
- * std::cout << p << std::endl; //[0.5, 1, 1.5, 2]
- * ```
- * @note the type of scalar should be equal to this quaternion.
- */
- Quat<_Tp> operator/(const _Tp s) const;
- /**
- * @brief Division operator of two quaternions p and q.
- * Divides left hand operand by right hand operand.
- *
- * Rule of quaternion division with a scalar:
- * \f[
- * \begin{equation}
- * \begin{split}
- * p / q &= p * q.inv()\\
- * \end{split}
- * \end{equation}
- * \f]
- *
- * For example
- * ```
- * Quatd p{1, 2, 3, 4};
- * Quatd q{5, 6, 7, 8};
- * std::cout << p / q << std::endl; // equivalent to p * q.inv()
- * ```
- */
- Quat<_Tp> operator/(const Quat<_Tp>&) const;
- /**
- * @brief Division assignment operator of a quaternions and a scalar.
- * It divides left operand with the right operand and assign the result to left operand.
- *
- * Rule of quaternion division with a scalar:
- * \f[
- * \begin{equation}
- * \begin{split}
- * p / s &= [w, x, y, z] / s\\
- * &=[w / s, x / s, y / s, z / s].
- * \end{split}
- * \end{equation}
- * \f]
- *
- * For example
- * ```
- * Quatd p{1, 2, 3, 4};
- * double s = 2.0;;
- * p /= s; // equivalent to p = p / s
- * std::cout << p << std::endl; //[0.5, 1.0, 1.5, 2.0]
- * ```
- * @note the type of scalar should be equal to the quaternion.
- */
- Quat<_Tp>& operator/=(const _Tp s);
- /**
- * @brief Division assignment operator of two quaternions p and q;
- * It divides left operand with the right operand and assign the result to left operand.
- *
- * Rule of quaternion division with a quaternion:
- * \f[
- * \begin{equation}
- * \begin{split}
- * p / q&= p * q.inv()\\
- * \end{split}
- * \end{equation}
- * \f]
- *
- * For example
- * ```
- * Quatd p{1, 2, 3, 4};
- * Quatd q{5, 6, 7, 8};
- * p /= q; // equivalent to p = p * q.inv()
- * std::cout << p << std::endl;
- * ```
- */
- Quat<_Tp>& operator/=(const Quat<_Tp>&);
- _Tp& operator[](std::size_t n);
- const _Tp& operator[](std::size_t n) const;
- /**
- * @brief Subtraction operator of a scalar and a quaternions.
- * Subtracts right hand operand from left hand operand.
- *
- * For example
- * ```
- * Quatd p{1, 2, 3, 4};
- * double scalar = 2.0;
- * std::cout << scalar - p << std::endl; //[1.0, -2, -3, -4]
- * ```
- * @note the type of scalar should be equal to the quaternion.
- */
- template <typename T>
- friend Quat<T> cv::operator-(const T s, const Quat<T>&);
- /**
- * @brief Subtraction operator of a quaternions and a scalar.
- * Subtracts right hand operand from left hand operand.
- *
- * For example
- * ```
- * Quatd p{1, 2, 3, 4};
- * double scalar = 2.0;
- * std::cout << p - scalar << std::endl; //[-1.0, 2, 3, 4]
- * ```
- * @note the type of scalar should be equal to the quaternion.
- */
- template <typename T>
- friend Quat<T> cv::operator-(const Quat<T>&, const T s);
- /**
- * @brief Addition operator of a quaternions and a scalar.
- * Adds right hand operand from left hand operand.
- *
- * For example
- * ```
- * Quatd p{1, 2, 3, 4};
- * double scalar = 2.0;
- * std::cout << scalar + p << std::endl; //[3.0, 2, 3, 4]
- * ```
- * @note the type of scalar should be equal to the quaternion.
- */
- template <typename T>
- friend Quat<T> cv::operator+(const T s, const Quat<T>&);
- /**
- * @brief Addition operator of a quaternions and a scalar.
- * Adds right hand operand from left hand operand.
- *
- * For example
- * ```
- * Quatd p{1, 2, 3, 4};
- * double scalar = 2.0;
- * std::cout << p + scalar << std::endl; //[3.0, 2, 3, 4]
- * ```
- * @note the type of scalar should be equal to the quaternion.
- */
- template <typename T>
- friend Quat<T> cv::operator+(const Quat<T>&, const T s);
- /**
- * @brief Multiplication operator of a scalar and a quaternions.
- * It multiplies right operand with the left operand and assign the result to left operand.
- *
- * Rule of quaternion multiplication with a scalar:
- * \f[
- * \begin{equation}
- * \begin{split}
- * p * s &= [w, x, y, z] * s\\
- * &=[w * s, x * s, y * s, z * s].
- * \end{split}
- * \end{equation}
- * \f]
- *
- * For example
- * ```
- * Quatd p{1, 2, 3, 4};
- * double s = 2.0;
- * std::cout << s * p << std::endl; //[2.0, 4.0, 6.0, 8.0]
- * ```
- * @note the type of scalar should be equal to the quaternion.
- */
- template <typename T>
- friend Quat<T> cv::operator*(const T s, const Quat<T>&);
- /**
- * @brief Multiplication operator of a quaternion and a scalar.
- * It multiplies right operand with the left operand and assign the result to left operand.
- *
- * Rule of quaternion multiplication with a scalar:
- * \f[
- * \begin{equation}
- * \begin{split}
- * p * s &= [w, x, y, z] * s\\
- * &=[w * s, x * s, y * s, z * s].
- * \end{split}
- * \end{equation}
- * \f]
- *
- * For example
- * ```
- * Quatd p{1, 2, 3, 4};
- * double s = 2.0;
- * std::cout << p * s << std::endl; //[2.0, 4.0, 6.0, 8.0]
- * ```
- * @note the type of scalar should be equal to the quaternion.
- */
- template <typename T>
- friend Quat<T> cv::operator*(const Quat<T>&, const T s);
- template <typename S>
- friend std::ostream& cv::operator<<(std::ostream&, const Quat<S>&);
- /**
- * @brief Transform a quaternion q to Euler angles.
- *
- *
- * When transforming a quaternion \f$q = w + x\boldsymbol{i} + y\boldsymbol{j} + z\boldsymbol{k}\f$ to Euler angles, rotation matrix M can be calculated by:
- * \f[ \begin{aligned} {M} &={\begin{bmatrix}1-2(y^{2}+z^{2})&2(xy-zx)&2(xz+yw)\\2(xy+zw)&1-2(x^{2}+z^{2})&2(yz-xw)\\2(xz-yw)&2(yz+xw)&1-2(x^{2}+y^{2})\end{bmatrix}}\end{aligned}.\f]
- * On the other hand, the rotation matrix can be obtained from Euler angles.
- * Using intrinsic rotations with Euler angles type XYZ as an example,
- * \f$\theta_1 \f$, \f$\theta_2 \f$, \f$\theta_3 \f$ are three angles for Euler angles, the rotation matrix R can be calculated by:\f[R =X(\theta_1)Y(\theta_2)Z(\theta_3)
- * ={\begin{bmatrix}\cos\theta_{2}\cos\theta_{3}&-\cos\theta_{2}\sin\theta_{3}&\sin\theta_{2}\\\cos\theta_{1}\sin\theta_{3}+\cos\theta_{3}\sin\theta_{1}\sin\theta_{2}&\cos\theta_{1}\cos\theta_{3}-\sin\theta_{1}\sin\theta_{2}\sin\theta_{3}&-\cos\theta_{2}\sin\theta_{1}\\\sin\theta_{1}\sin\theta_{3}-\cos\theta_{1}\cos\theta_{3}\sin\theta_{2}&\cos\theta_{3}\sin\theta_{1}+\cos\theta_{1}\sin\theta_{2}\sin\theta_{3}&\cos\theta_{1}\cos_{2}\end{bmatrix}}\f]
- * Rotation matrix M and R are equal. As long as \f$ s_{2} \neq 1 \f$, by comparing each element of two matrices ,the solution is\f$\begin{cases} \theta_1 = \arctan2(-m_{23},m_{33})\\\theta_2 = arcsin(m_{13}) \\\theta_3 = \arctan2(-m_{12},m_{11}) \end{cases}\f$.
- *
- * When \f$ s_{2}=1\f$ or \f$ s_{2}=-1\f$, the gimbal lock occurs. The function will prompt "WARNING: Gimbal Lock will occur. Euler angles is non-unique. For intrinsic rotations, we set the third angle to 0, and for external rotation, we set the first angle to 0.".
- *
- * When \f$ s_{2}=1\f$ ,
- * The rotation matrix R is \f$R = {\begin{bmatrix}0&0&1\\\sin(\theta_1+\theta_3)&\cos(\theta_1+\theta_3)&0\\-\cos(\theta_1+\theta_3)&\sin(\theta_1+\theta_3)&0\end{bmatrix}}\f$.
- *
- * The number of solutions is infinite with the condition \f$\begin{cases} \theta_1+\theta_3 = \arctan2(m_{21},m_{22})\\ \theta_2=\pi/2 \end{cases}\ \f$.
- *
- * We set \f$ \theta_3 = 0\f$, the solution is \f$\begin{cases} \theta_1=\arctan2(m_{21},m_{22})\\ \theta_2=\pi/2\\ \theta_3=0 \end{cases}\f$.
- *
- * When \f$ s_{2}=-1\f$,
- * The rotation matrix R is \f$X_{1}Y_{2}Z_{3}={\begin{bmatrix}0&0&-1\\-\sin(\theta_1-\theta_3)&\cos(\theta_1-\theta_3)&0\\\cos(\theta_1-\theta_3)&\sin(\theta_1-\theta_3)&0\end{bmatrix}}\f$.
- *
- * The number of solutions is infinite with the condition \f$\begin{cases} \theta_1+\theta_3 = \arctan2(m_{32},m_{22})\\ \theta_2=\pi/2 \end{cases}\ \f$.
- *
- * We set \f$ \theta_3 = 0\f$, the solution is \f$ \begin{cases}\theta_1=\arctan2(m_{32},m_{22}) \\ \theta_2=-\pi/2\\ \theta_3=0\end{cases}\f$.
- *
- * Since \f$ sin \theta\in [-1,1] \f$ and \f$ cos \theta \in [-1,1] \f$, the unnormalized quaternion will cause computational troubles. For this reason, this function will normalize the quaternion at first and @ref QuatAssumeType is not needed.
- *
- * When the gimbal lock occurs, we set \f$\theta_3 = 0\f$ for intrinsic rotations or \f$\theta_1 = 0\f$ for extrinsic rotations.
- *
- * As a result, for every Euler angles type, we can get solution as shown in the following table.
- * EulerAnglesType | Ordinary | \f$\theta_2 = π/2\f$ | \f$\theta_2 = -π/2\f$
- * ------------- | -------------| -------------| -------------
- * INT_XYZ|\f$ \theta_1 = \arctan2(-m_{23},m_{33})\\\theta_2 = \arcsin(m_{13}) \\\theta_3= \arctan2(-m_{12},m_{11}) \f$|\f$ \theta_1=\arctan2(m_{21},m_{22})\\ \theta_2=\pi/2\\ \theta_3=0 \f$|\f$ \theta_1=\arctan2(m_{32},m_{22})\\ \theta_2=-\pi/2\\ \theta_3=0 \f$
- * INT_XZY|\f$ \theta_1 = \arctan2(m_{32},m_{22})\\\theta_2 = -\arcsin(m_{12}) \\\theta_3= \arctan2(m_{13},m_{11}) \f$|\f$ \theta_1=\arctan2(m_{31},m_{33})\\ \theta_2=\pi/2\\ \theta_3=0 \f$|\f$ \theta_1=\arctan2(-m_{23},m_{33})\\ \theta_2=-\pi/2\\ \theta_3=0 \f$
- * INT_YXZ|\f$ \theta_1 = \arctan2(m_{13},m_{33})\\\theta_2 = -\arcsin(m_{23}) \\\theta_3= \arctan2(m_{21},m_{22}) \f$|\f$ \theta_1=\arctan2(m_{12},m_{11})\\ \theta_2=\pi/2\\ \theta_3=0 \f$|\f$ \theta_1=\arctan2(-m_{12},m_{11})\\ \theta_2=-\pi/2\\ \theta_3=0 \f$
- * INT_YZX|\f$ \theta_1 = \arctan2(-m_{31},m_{11})\\\theta_2 = \arcsin(m_{21}) \\\theta_3= \arctan2(-m_{23},m_{22}) \f$|\f$ \theta_1=\arctan2(m_{13},m_{33})\\ \theta_2=\pi/2\\ \theta_3=0 \f$|\f$ \theta_1=\arctan2(m_{13},m_{12})\\ \theta_2=-\pi/2\\ \theta_3=0 \f$
- * INT_ZXY|\f$ \theta_1 = \arctan2(-m_{12},m_{22})\\\theta_2 = \arcsin(m_{32}) \\\theta_3= \arctan2(-m_{31},m_{33}) \f$|\f$ \theta_1=\arctan2(m_{21},m_{11})\\ \theta_2=\pi/2\\ \theta_3=0 \f$|\f$ \theta_1=\arctan2(m_{21},m_{11})\\ \theta_2=-\pi/2\\ \theta_3=0 \f$
- * INT_ZYX|\f$ \theta_1 = \arctan2(m_{21},m_{11})\\\theta_2 = \arcsin(-m_{31}) \\\theta_3= \arctan2(m_{32},m_{33}) \f$|\f$ \theta_1=\arctan2(m_{23},m_{22})\\ \theta_2=\pi/2\\ \theta_3=0 \f$|\f$ \theta_1=\arctan2(-m_{12},m_{22})\\ \theta_2=-\pi/2\\ \theta_3=0 \f$
- * EXT_XYZ|\f$ \theta_1 = \arctan2(m_{32},m_{33})\\\theta_2 = \arcsin(-m_{31}) \\\ \theta_3 = \arctan2(m_{21},m_{11})\f$|\f$ \theta_1= 0\\ \theta_2=\pi/2\\ \theta_3=\arctan2(m_{23},m_{22}) \f$|\f$ \theta_1=0\\ \theta_2=-\pi/2\\ \theta_3=\arctan2(-m_{12},m_{22}) \f$
- * EXT_XZY|\f$ \theta_1 = \arctan2(-m_{23},m_{22})\\\theta_2 = \arcsin(m_{21}) \\\theta_3= \arctan2(-m_{31},m_{11})\f$|\f$ \theta_1= 0\\ \theta_2=\pi/2\\ \theta_3=\arctan2(m_{13},m_{33}) \f$|\f$ \theta_1=0\\ \theta_2=-\pi/2\\ \theta_3=\arctan2(m_{13},m_{12}) \f$
- * EXT_YXZ|\f$ \theta_1 = \arctan2(-m_{31},m_{33}) \\\theta_2 = \arcsin(m_{32}) \\\theta_3= \arctan2(-m_{12},m_{22})\f$|\f$ \theta_1= 0\\ \theta_2=\pi/2\\ \theta_3=\arctan2(m_{21},m_{11}) \f$|\f$ \theta_1=0\\ \theta_2=-\pi/2\\ \theta_3=\arctan2(m_{21},m_{11}) \f$
- * EXT_YZX|\f$ \theta_1 = \arctan2(m_{13},m_{11})\\\theta_2 = -\arcsin(m_{12}) \\\theta_3= \arctan2(m_{32},m_{22})\f$|\f$ \theta_1= 0\\ \theta_2=\pi/2\\ \theta_3=\arctan2(m_{31},m_{33}) \f$|\f$ \theta_1=0\\ \theta_2=-\pi/2\\ \theta_3=\arctan2(-m_{23},m_{33}) \f$
- * EXT_ZXY|\f$ \theta_1 = \arctan2(m_{21},m_{22})\\\theta_2 = -\arcsin(m_{23}) \\\theta_3= \arctan2(m_{13},m_{33})\f$|\f$ \theta_1= 0\\ \theta_2=\pi/2\\ \theta_3=\arctan2(m_{12},m_{11}) \f$|\f$ \theta_1= 0\\ \theta_2=-\pi/2\\ \theta_3=\arctan2(-m_{12},m_{11}) \f$
- * EXT_ZYX|\f$ \theta_1 = \arctan2(-m_{12},m_{11})\\\theta_2 = \arcsin(m_{13}) \\\theta_3= \arctan2(-m_{23},m_{33})\f$|\f$ \theta_1=0\\ \theta_2=\pi/2\\ \theta_3=\arctan2(m_{21},m_{22}) \f$|\f$ \theta_1=0\\ \theta_2=-\pi/2\\ \theta_3=\arctan2(m_{32},m_{22}) \f$
- *
- * EulerAnglesType | Ordinary | \f$\theta_2 = 0\f$ | \f$\theta_2 = π\f$
- * ------------- | -------------| -------------| -------------
- * INT_XYX| \f$ \theta_1 = \arctan2(m_{21},-m_{31})\\\theta_2 =\arccos(m_{11}) \\\theta_3 = \arctan2(m_{12},m_{13}) \f$| \f$ \theta_1=\arctan2(m_{32},m_{33})\\ \theta_2=0\\ \theta_3=0 \f$| \f$ \theta_1=\arctan2(m_{23},m_{22})\\ \theta_2=\pi\\ \theta_3=0 \f$
- * INT_XZX| \f$ \theta_1 = \arctan2(m_{31},m_{21})\\\theta_2 = \arccos(m_{11}) \\\theta_3 = \arctan2(m_{13},-m_{12}) \f$| \f$ \theta_1=\arctan2(m_{32},m_{33})\\ \theta_2=0\\ \theta_3=0 \f$| \f$ \theta_1=\arctan2(-m_{32},m_{33})\\ \theta_2=\pi\\ \theta_3=0 \f$
- * INT_YXY| \f$ \theta_1 = \arctan2(m_{12},m_{32})\\\theta_2 = \arccos(m_{22}) \\\theta_3 = \arctan2(m_{21},-m_{23}) \f$| \f$ \theta_1=\arctan2(m_{13},m_{11})\\ \theta_2=0\\ \theta_3=0 \f$| \f$ \theta_1=\arctan2(-m_{31},m_{11})\\ \theta_2=\pi\\ \theta_3=0 \f$
- * INT_YZY| \f$ \theta_1 = \arctan2(m_{32},-m_{12})\\\theta_2 = \arccos(m_{22}) \\\theta_3 =\arctan2(m_{23},m_{21}) \f$| \f$ \theta_1=\arctan2(m_{13},m_{11})\\ \theta_2=0\\ \theta_3=0 \f$| \f$ \theta_1=\arctan2(m_{13},-m_{11})\\ \theta_2=\pi\\ \theta_3=0 \f$
- * INT_ZXZ| \f$ \theta_1 = \arctan2(-m_{13},m_{23})\\\theta_2 = \arccos(m_{33}) \\\theta_3 =\arctan2(m_{31},m_{32}) \f$| \f$ \theta_1=\arctan2(m_{21},m_{22})\\ \theta_2=0\\ \theta_3=0 \f$| \f$ \theta_1=\arctan2(m_{21},m_{11})\\ \theta_2=\pi\\ \theta_3=0 \f$
- * INT_ZYZ| \f$ \theta_1 = \arctan2(m_{23},m_{13})\\\theta_2 = \arccos(m_{33}) \\\theta_3 = \arctan2(m_{32},-m_{31}) \f$| \f$ \theta_1=\arctan2(m_{21},m_{11})\\ \theta_2=0\\ \theta_3=0 \f$| \f$ \theta_1=\arctan2(m_{21},m_{11})\\ \theta_2=\pi\\ \theta_3=0 \f$
- * EXT_XYX| \f$ \theta_1 = \arctan2(m_{12},m_{13}) \\\theta_2 = \arccos(m_{11}) \\\theta_3 = \arctan2(m_{21},-m_{31})\f$| \f$ \theta_1=0\\ \theta_2=0\\ \theta_3=\arctan2(m_{32},m_{33}) \f$| \f$ \theta_1= 0\\ \theta_2=\pi\\ \theta_3= \arctan2(m_{23},m_{22}) \f$
- * EXT_XZX| \f$ \theta_1 = \arctan2(m_{13},-m_{12})\\\theta_2 = \arccos(m_{11}) \\\theta_3 = \arctan2(m_{31},m_{21})\f$| \f$ \theta_1= 0\\ \theta_2=0\\ \theta_3=\arctan2(m_{32},m_{33}) \f$| \f$ \theta_1= 0\\ \theta_2=\pi\\ \theta_3=\arctan2(-m_{32},m_{33}) \f$
- * EXT_YXY| \f$ \theta_1 = \arctan2(m_{21},-m_{23})\\\theta_2 = \arccos(m_{22}) \\\theta_3 = \arctan2(m_{12},m_{32}) \f$| \f$ \theta_1= 0\\ \theta_2=0\\ \theta_3=\arctan2(m_{13},m_{11}) \f$| \f$ \theta_1= 0\\ \theta_2=\pi\\ \theta_3=\arctan2(-m_{31},m_{11}) \f$
- * EXT_YZY| \f$ \theta_1 = \arctan2(m_{23},m_{21}) \\\theta_2 = \arccos(m_{22}) \\\theta_3 = \arctan2(m_{32},-m_{12}) \f$| \f$ \theta_1= 0\\ \theta_2=0\\ \theta_3=\arctan2(m_{13},m_{11}) \f$| \f$ \theta_1=0\\ \theta_2=\pi\\ \theta_3=\arctan2(m_{13},-m_{11}) \f$
- * EXT_ZXZ| \f$ \theta_1 = \arctan2(m_{31},m_{32}) \\\theta_2 = \arccos(m_{33}) \\\theta_3 = \arctan2(-m_{13},m_{23})\f$| \f$ \theta_1=0\\ \theta_2=0\\ \theta_3=\arctan2(m_{21},m_{22}) \f$| \f$ \theta_1= 0\\ \theta_2=\pi\\ \theta_3=\arctan2(m_{21},m_{11}) \f$
- * EXT_ZYZ| \f$ \theta_1 = \arctan2(m_{32},-m_{31})\\\theta_2 = \arccos(m_{33}) \\\theta_3 = \arctan2(m_{23},m_{13}) \f$| \f$ \theta_1=0\\ \theta_2=0\\ \theta_3=\arctan2(m_{21},m_{11}) \f$| \f$ \theta_1= 0\\ \theta_2=\pi\\ \theta_3=\arctan2(m_{21},m_{11}) \f$
- *
- * @param eulerAnglesType the convertion Euler angles type
- */
- Vec<_Tp, 3> toEulerAngles(QuatEnum::EulerAnglesType eulerAnglesType);
- _Tp w, x, y, z;
- };
- template <typename T>
- Quat<T> inv(const Quat<T> &q, QuatAssumeType assumeUnit=QUAT_ASSUME_NOT_UNIT);
- template <typename T>
- Quat<T> sinh(const Quat<T> &q);
- template <typename T>
- Quat<T> cosh(const Quat<T> &q);
- template <typename T>
- Quat<T> tanh(const Quat<T> &q);
- template <typename T>
- Quat<T> sin(const Quat<T> &q);
- template <typename T>
- Quat<T> cos(const Quat<T> &q);
- template <typename T>
- Quat<T> tan(const Quat<T> &q);
- template <typename T>
- Quat<T> asinh(const Quat<T> &q);
- template <typename T>
- Quat<T> acosh(const Quat<T> &q);
- template <typename T>
- Quat<T> atanh(const Quat<T> &q);
- template <typename T>
- Quat<T> asin(const Quat<T> &q);
- template <typename T>
- Quat<T> acos(const Quat<T> &q);
- template <typename T>
- Quat<T> atan(const Quat<T> &q);
- template <typename T>
- Quat<T> power(const Quat<T> &q, const Quat<T> &p, QuatAssumeType assumeUnit=QUAT_ASSUME_NOT_UNIT);
- template <typename T>
- Quat<T> exp(const Quat<T> &q);
- template <typename T>
- Quat<T> log(const Quat<T> &q, QuatAssumeType assumeUnit=QUAT_ASSUME_NOT_UNIT);
- template <typename T>
- Quat<T> power(const Quat<T>& q, const T x, QuatAssumeType assumeUnit=QUAT_ASSUME_NOT_UNIT);
- template <typename T>
- Quat<T> crossProduct(const Quat<T> &p, const Quat<T> &q);
- template <typename S>
- Quat<S> sqrt(const Quat<S> &q, QuatAssumeType assumeUnit=QUAT_ASSUME_NOT_UNIT);
- template <typename T>
- Quat<T> operator*(const T, const Quat<T>&);
- template <typename T>
- Quat<T> operator*(const Quat<T>&, const T);
- template <typename S>
- std::ostream& operator<<(std::ostream&, const Quat<S>&);
- using Quatd = Quat<double>;
- using Quatf = Quat<float>;
- //! @} core
- }
- #include "opencv2/core/quaternion.inl.hpp"
- #endif /* OPENCV_CORE_QUATERNION_HPP */
|