// Copyright (c) 2022, ETH Zurich and UNC Chapel Hill. | |
// All rights reserved. | |
// | |
// Redistribution and use in source and binary forms, with or without | |
// modification, are permitted provided that the following conditions are met: | |
// | |
// * Redistributions of source code must retain the above copyright | |
// notice, this list of conditions and the following disclaimer. | |
// | |
// * Redistributions in binary form must reproduce the above copyright | |
// notice, this list of conditions and the following disclaimer in the | |
// documentation and/or other materials provided with the distribution. | |
// | |
// * Neither the name of ETH Zurich and UNC Chapel Hill nor the names of | |
// its contributors may be used to endorse or promote products derived | |
// from this software without specific prior written permission. | |
// | |
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | |
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | |
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE | |
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | |
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | |
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | |
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | |
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | |
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | |
// POSSIBILITY OF SUCH DAMAGE. | |
// | |
// Author: Johannes L. Schoenberger (jsch-at-demuc-dot-de) | |
namespace colmap { | |
// Compose the skew symmetric cross product matrix from a vector. | |
Eigen::Matrix3d CrossProductMatrix(const Eigen::Vector3d& vector); | |
// Convert 3D rotation matrix to Euler angles. | |
// | |
// The convention `R = Rx * Ry * Rz` is used, | |
// using a right-handed coordinate system. | |
// | |
// @param R 3x3 rotation matrix. | |
// @param rx, ry, rz Euler angles in radians. | |
void RotationMatrixToEulerAngles(const Eigen::Matrix3d& R, double* rx, | |
double* ry, double* rz); | |
// Convert Euler angles to 3D rotation matrix. | |
// | |
// The convention `R = Rz * Ry * Rx` is used, | |
// using a right-handed coordinate system. | |
// | |
// @param rx, ry, rz Euler angles in radians. | |
// | |
// @return 3x3 rotation matrix. | |
Eigen::Matrix3d EulerAnglesToRotationMatrix(const double rx, const double ry, | |
const double rz); | |
// Convert 3D rotation matrix to Quaternion representation. | |
// | |
// @param rot_mat 3x3 rotation matrix. | |
// | |
// @return Unit Quaternion rotation coefficients (w, x, y, z). | |
Eigen::Vector4d RotationMatrixToQuaternion(const Eigen::Matrix3d& rot_mat); | |
// Convert Quaternion representation to 3D rotation matrix. | |
// | |
// @param qvec Unit Quaternion rotation coefficients (w, x, y, z). | |
// | |
// @return 3x3 rotation matrix. | |
Eigen::Matrix3d QuaternionToRotationMatrix(const Eigen::Vector4d& qvec); | |
// Compose the Quaternion vector corresponding to a identity transformation. | |
inline Eigen::Vector4d ComposeIdentityQuaternion(); | |
// Normalize Quaternion vector. | |
// | |
// @param qvec Quaternion rotation coefficients (w, x, y, z). | |
// | |
// @return Unit Quaternion rotation coefficients (w, x, y, z). | |
Eigen::Vector4d NormalizeQuaternion(const Eigen::Vector4d& qvec); | |
// Invert Quaternion vector to return Quaternion of inverse rotation. | |
// | |
// @param qvec Quaternion rotation coefficients (w, x, y, z). | |
// | |
// @return Inverse Quaternion rotation coefficients (w, x, y, z). | |
Eigen::Vector4d InvertQuaternion(const Eigen::Vector4d& qvec); | |
// Concatenate Quaternion rotations such that the rotation of `qvec1` is applied | |
// before the rotation of `qvec2`. | |
// | |
// @param qvec1 Quaternion rotation coefficients (w, x, y, z). | |
// @param qvec2 Quaternion rotation coefficients (w, x, y, z). | |
// | |
// @return Concatenated Quaternion coefficients (w, x, y, z). | |
Eigen::Vector4d ConcatenateQuaternions(const Eigen::Vector4d& qvec1, | |
const Eigen::Vector4d& qvec2); | |
// Transform point by quaternion rotation. | |
// | |
// @param qvec Quaternion rotation coefficients (w, x, y, z). | |
// @param point Point to rotate. | |
// | |
// @return Rotated point. | |
Eigen::Vector3d QuaternionRotatePoint(const Eigen::Vector4d& qvec, | |
const Eigen::Vector3d& point); | |
// Compute the weighted average of multiple Quaternions according to: | |
// | |
// Markley, F. Landis, et al. "Averaging quaternions." | |
// Journal of Guidance, Control, and Dynamics 30.4 (2007): 1193-1197. | |
// | |
// @param qvecs The Quaternions to be averaged. | |
// @param weights Non-negative weights. | |
// | |
// @return The average Quaternion. | |
Eigen::Vector4d AverageQuaternions(const std::vector<Eigen::Vector4d>& qvecs, | |
const std::vector<double>& weights); | |
// Compose rotation matrix that rotates unit vector 1 to unit vector 2. | |
// Note that when vector 1 points into the opposite direction of vector 2, | |
// the function returns an identity rotation. | |
Eigen::Matrix3d RotationFromUnitVectors(const Eigen::Vector3d& vec1, | |
const Eigen::Vector3d& vec2); | |
// Extract camera projection center from projection matrix, i.e. the projection | |
// center in world coordinates `-R^T t`. | |
Eigen::Vector3d ProjectionCenterFromMatrix( | |
const Eigen::Matrix3x4d& proj_matrix); | |
// Extract camera projection center from projection parameters. | |
// | |
// @param qvec Unit Quaternion rotation coefficients (w, x, y, z). | |
// @param tvec 3x1 translation vector. | |
// | |
// @return 3x1 camera projection center. | |
Eigen::Vector3d ProjectionCenterFromPose(const Eigen::Vector4d& qvec, | |
const Eigen::Vector3d& tvec); | |
// Compute the relative transformation from pose 1 to 2. | |
// | |
// @param qvec1, tvec1 First camera pose. | |
// @param qvec2, tvec2 Second camera pose. | |
// @param qvec12, tvec12 Relative pose. | |
void ComputeRelativePose(const Eigen::Vector4d& qvec1, | |
const Eigen::Vector3d& tvec1, | |
const Eigen::Vector4d& qvec2, | |
const Eigen::Vector3d& tvec2, Eigen::Vector4d* qvec12, | |
Eigen::Vector3d* tvec12); | |
// Concatenate the transformations of the two poses. | |
// | |
// @param qvec1, tvec1 First camera pose. | |
// @param qvec2, tvec2 Second camera pose. | |
// @param qvec12, tvec12 Concatenated pose. | |
void ConcatenatePoses(const Eigen::Vector4d& qvec1, | |
const Eigen::Vector3d& tvec1, | |
const Eigen::Vector4d& qvec2, | |
const Eigen::Vector3d& tvec2, Eigen::Vector4d* qvec12, | |
Eigen::Vector3d* tvec12); | |
// Invert transformation of the pose. | |
// @param qvec, tvec Input camera pose. | |
// @param inv_qvec, inv_tvec Inverse camera pose. | |
void InvertPose(const Eigen::Vector4d& qvec, const Eigen::Vector3d& tvec, | |
Eigen::Vector4d* inv_qvec, Eigen::Vector3d* inv_tvec); | |
// Linearly interpolate camera pose. | |
// | |
// @param qvec1, tvec1 Camera pose at t0 = 0. | |
// @param qvec2, tvec2 Camera pose at t1 = 1. | |
// @param t Interpolation time. | |
// @param qveci, tveci Camera pose at time t. | |
void InterpolatePose(const Eigen::Vector4d& qvec1, const Eigen::Vector3d& tvec1, | |
const Eigen::Vector4d& qvec2, const Eigen::Vector3d& tvec2, | |
const double t, Eigen::Vector4d* qveci, | |
Eigen::Vector3d* tveci); | |
// Calculate baseline vector from first to second pose. | |
// | |
// The given rotation and orientation is expected as the | |
// world to camera transformation. | |
// | |
// @param qvec1 Unit Quaternion rotation coefficients (w, x, y, z). | |
// @param tvec1 3x1 translation vector. | |
// @param qvec2 Unit Quaternion rotation coefficients (w, x, y, z). | |
// @param tvec2 3x1 translation vector. | |
// | |
// @return Baseline vector from 1 to 2. | |
Eigen::Vector3d CalculateBaseline(const Eigen::Vector4d& qvec1, | |
const Eigen::Vector3d& tvec1, | |
const Eigen::Vector4d& qvec2, | |
const Eigen::Vector3d& tvec2); | |
// Perform cheirality constraint test, i.e., determine which of the triangulated | |
// correspondences lie in front of of both cameras. The first camera has the | |
// projection matrix P1 = [I | 0] and the second camera has the projection | |
// matrix P2 = [R | t]. | |
// | |
// @param R 3x3 rotation matrix of second projection matrix. | |
// @param t 3x1 translation vector of second projection matrix. | |
// @param points1 First set of corresponding points. | |
// @param points2 Second set of corresponding points. | |
// @param points3D Points that lie in front of both cameras. | |
bool CheckCheirality(const Eigen::Matrix3d& R, const Eigen::Vector3d& t, | |
const std::vector<Eigen::Vector2d>& points1, | |
const std::vector<Eigen::Vector2d>& points2, | |
std::vector<Eigen::Vector3d>* points3D); | |
//////////////////////////////////////////////////////////////////////////////// | |
// Implementation | |
//////////////////////////////////////////////////////////////////////////////// | |
Eigen::Vector4d ComposeIdentityQuaternion() { | |
return Eigen::Vector4d(1, 0, 0, 0); | |
} | |
} // namespace colmap | |