|  | // Ceres Solver - A fast non-linear least squares minimizer | 
|  | // Copyright 2010, 2011, 2012 Google Inc. All rights reserved. | 
|  | // http://code.google.com/p/ceres-solver/ | 
|  | // | 
|  | // 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 Google Inc. 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 OWNER 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: sameeragarwal@google.com (Sameer Agarwal) | 
|  |  | 
|  | #include "ceres/local_parameterization.h" | 
|  |  | 
|  | #include "ceres/internal/eigen.h" | 
|  | #include "ceres/rotation.h" | 
|  | #include "glog/logging.h" | 
|  |  | 
|  | namespace ceres { | 
|  |  | 
|  | IdentityParameterization::IdentityParameterization(const int size) | 
|  | : size_(size) { | 
|  | CHECK_GT(size, 0); | 
|  | } | 
|  |  | 
|  | bool IdentityParameterization::Plus(const double* x, | 
|  | const double* delta, | 
|  | double* x_plus_delta) const { | 
|  | VectorRef(x_plus_delta, size_) = | 
|  | ConstVectorRef(x, size_) + ConstVectorRef(delta, size_); | 
|  | return true; | 
|  | } | 
|  |  | 
|  | bool IdentityParameterization::ComputeJacobian(const double* x, | 
|  | double* jacobian) const { | 
|  | MatrixRef(jacobian, size_, size_) = Matrix::Identity(size_, size_); | 
|  | return true; | 
|  | } | 
|  |  | 
|  | SubsetParameterization::SubsetParameterization( | 
|  | int size, | 
|  | const vector<int>& constant_parameters) | 
|  | : local_size_(size - constant_parameters.size()), | 
|  | constancy_mask_(size, 0) { | 
|  | CHECK_GT(constant_parameters.size(), 0) | 
|  | << "The set of constant parameters should contain at least " | 
|  | << "one element. If you do not wish to hold any parameters " | 
|  | << "constant, then do not use a SubsetParameterization"; | 
|  |  | 
|  | vector<int> constant = constant_parameters; | 
|  | sort(constant.begin(), constant.end()); | 
|  | CHECK(unique(constant.begin(), constant.end()) == constant.end()) | 
|  | << "The set of constant parameters cannot contain duplicates"; | 
|  | CHECK_LT(constant_parameters.size(), size) | 
|  | << "Number of parameters held constant should be less " | 
|  | << "than the size of the parameter block. If you wish " | 
|  | << "to hold the entire parameter block constant, then a " | 
|  | << "efficient way is to directly mark it as constant " | 
|  | << "instead of using a LocalParameterization to do so."; | 
|  | CHECK_GE(*min_element(constant.begin(), constant.end()), 0); | 
|  | CHECK_LT(*max_element(constant.begin(), constant.end()), size); | 
|  |  | 
|  | for (int i = 0; i < constant_parameters.size(); ++i) { | 
|  | constancy_mask_[constant_parameters[i]] = 1; | 
|  | } | 
|  | } | 
|  |  | 
|  | bool SubsetParameterization::Plus(const double* x, | 
|  | const double* delta, | 
|  | double* x_plus_delta) const { | 
|  | for (int i = 0, j = 0; i < constancy_mask_.size(); ++i) { | 
|  | if (constancy_mask_[i]) { | 
|  | x_plus_delta[i] = x[i]; | 
|  | } else { | 
|  | x_plus_delta[i] = x[i] + delta[j++]; | 
|  | } | 
|  | } | 
|  | return true; | 
|  | } | 
|  |  | 
|  | bool SubsetParameterization::ComputeJacobian(const double* x, | 
|  | double* jacobian) const { | 
|  | MatrixRef m(jacobian, constancy_mask_.size(), local_size_); | 
|  | m.setZero(); | 
|  | for (int i = 0, j = 0; i < constancy_mask_.size(); ++i) { | 
|  | if (!constancy_mask_[i]) { | 
|  | m(i, j++) = 1.0; | 
|  | } | 
|  | } | 
|  | return true; | 
|  | } | 
|  |  | 
|  | bool QuaternionParameterization::Plus(const double* x, | 
|  | const double* delta, | 
|  | double* x_plus_delta) const { | 
|  | const double norm_delta = | 
|  | sqrt(delta[0] * delta[0] + delta[1] * delta[1] + delta[2] * delta[2]); | 
|  | if (norm_delta > 0.0) { | 
|  | const double sin_delta_by_delta = (sin(norm_delta) / norm_delta); | 
|  | double q_delta[4]; | 
|  | q_delta[0] = cos(norm_delta); | 
|  | q_delta[1] = sin_delta_by_delta * delta[0]; | 
|  | q_delta[2] = sin_delta_by_delta * delta[1]; | 
|  | q_delta[3] = sin_delta_by_delta * delta[2]; | 
|  | QuaternionProduct(q_delta, x, x_plus_delta); | 
|  | } else { | 
|  | for (int i = 0; i < 4; ++i) { | 
|  | x_plus_delta[i] = x[i]; | 
|  | } | 
|  | } | 
|  | return true; | 
|  | } | 
|  |  | 
|  | bool QuaternionParameterization::ComputeJacobian(const double* x, | 
|  | double* jacobian) const { | 
|  | jacobian[0] = -x[1]; jacobian[1]  = -x[2]; jacobian[2]  = -x[3];  // NOLINT | 
|  | jacobian[3] =  x[0]; jacobian[4]  =  x[3]; jacobian[5]  = -x[2];  // NOLINT | 
|  | jacobian[6] = -x[3]; jacobian[7]  =  x[0]; jacobian[8]  =  x[1];  // NOLINT | 
|  | jacobian[9] =  x[2]; jacobian[10] = -x[1]; jacobian[11] =  x[0];  // NOLINT | 
|  | return true; | 
|  | } | 
|  |  | 
|  | }  // namespace ceres |