Blame include/ceres/local_parameterization.h

Packit ea1746
// Ceres Solver - A fast non-linear least squares minimizer
Packit ea1746
// Copyright 2015 Google Inc. All rights reserved.
Packit ea1746
// http://ceres-solver.org/
Packit ea1746
//
Packit ea1746
// Redistribution and use in source and binary forms, with or without
Packit ea1746
// modification, are permitted provided that the following conditions are met:
Packit ea1746
//
Packit ea1746
// * Redistributions of source code must retain the above copyright notice,
Packit ea1746
//   this list of conditions and the following disclaimer.
Packit ea1746
// * Redistributions in binary form must reproduce the above copyright notice,
Packit ea1746
//   this list of conditions and the following disclaimer in the documentation
Packit ea1746
//   and/or other materials provided with the distribution.
Packit ea1746
// * Neither the name of Google Inc. nor the names of its contributors may be
Packit ea1746
//   used to endorse or promote products derived from this software without
Packit ea1746
//   specific prior written permission.
Packit ea1746
//
Packit ea1746
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
Packit ea1746
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
Packit ea1746
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
Packit ea1746
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
Packit ea1746
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
Packit ea1746
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
Packit ea1746
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
Packit ea1746
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
Packit ea1746
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
Packit ea1746
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
Packit ea1746
// POSSIBILITY OF SUCH DAMAGE.
Packit ea1746
//
Packit ea1746
// Author: keir@google.com (Keir Mierle)
Packit ea1746
//         sameeragarwal@google.com (Sameer Agarwal)
Packit ea1746
Packit ea1746
#ifndef CERES_PUBLIC_LOCAL_PARAMETERIZATION_H_
Packit ea1746
#define CERES_PUBLIC_LOCAL_PARAMETERIZATION_H_
Packit ea1746
Packit ea1746
#include <vector>
Packit ea1746
#include "ceres/internal/port.h"
Packit ea1746
#include "ceres/internal/scoped_ptr.h"
Packit ea1746
#include "ceres/internal/disable_warnings.h"
Packit ea1746
Packit ea1746
namespace ceres {
Packit ea1746
Packit ea1746
// Purpose: Sometimes parameter blocks x can overparameterize a problem
Packit ea1746
//
Packit ea1746
//   min f(x)
Packit ea1746
//    x
Packit ea1746
//
Packit ea1746
// In that case it is desirable to choose a parameterization for the
Packit ea1746
// block itself to remove the null directions of the cost. More
Packit ea1746
// generally, if x lies on a manifold of a smaller dimension than the
Packit ea1746
// ambient space that it is embedded in, then it is numerically and
Packit ea1746
// computationally more effective to optimize it using a
Packit ea1746
// parameterization that lives in the tangent space of that manifold
Packit ea1746
// at each point.
Packit ea1746
//
Packit ea1746
// For example, a sphere in three dimensions is a 2 dimensional
Packit ea1746
// manifold, embedded in a three dimensional space. At each point on
Packit ea1746
// the sphere, the plane tangent to it defines a two dimensional
Packit ea1746
// tangent space. For a cost function defined on this sphere, given a
Packit ea1746
// point x, moving in the direction normal to the sphere at that point
Packit ea1746
// is not useful. Thus a better way to do a local optimization is to
Packit ea1746
// optimize over two dimensional vector delta in the tangent space at
Packit ea1746
// that point and then "move" to the point x + delta, where the move
Packit ea1746
// operation involves projecting back onto the sphere. Doing so
Packit ea1746
// removes a redundent dimension from the optimization, making it
Packit ea1746
// numerically more robust and efficient.
Packit ea1746
//
Packit ea1746
// More generally we can define a function
Packit ea1746
//
Packit ea1746
//   x_plus_delta = Plus(x, delta),
Packit ea1746
//
Packit ea1746
// where x_plus_delta has the same size as x, and delta is of size
Packit ea1746
// less than or equal to x. The function Plus, generalizes the
Packit ea1746
// definition of vector addition. Thus it satisfies the identify
Packit ea1746
//
Packit ea1746
//   Plus(x, 0) = x, for all x.
Packit ea1746
//
Packit ea1746
// A trivial version of Plus is when delta is of the same size as x
Packit ea1746
// and
Packit ea1746
//
Packit ea1746
//   Plus(x, delta) = x + delta
Packit ea1746
//
Packit ea1746
// A more interesting case if x is two dimensional vector, and the
Packit ea1746
// user wishes to hold the first coordinate constant. Then, delta is a
Packit ea1746
// scalar and Plus is defined as
Packit ea1746
//
Packit ea1746
//   Plus(x, delta) = x + [0] * delta
Packit ea1746
//                        [1]
Packit ea1746
//
Packit ea1746
// An example that occurs commonly in Structure from Motion problems
Packit ea1746
// is when camera rotations are parameterized using Quaternion. There,
Packit ea1746
// it is useful only make updates orthogonal to that 4-vector defining
Packit ea1746
// the quaternion. One way to do this is to let delta be a 3
Packit ea1746
// dimensional vector and define Plus to be
Packit ea1746
//
Packit ea1746
//   Plus(x, delta) = [cos(|delta|), sin(|delta|) delta / |delta|] * x
Packit ea1746
//
Packit ea1746
// The multiplication between the two 4-vectors on the RHS is the
Packit ea1746
// standard quaternion product.
Packit ea1746
//
Packit ea1746
// Given g and a point x, optimizing f can now be restated as
Packit ea1746
//
Packit ea1746
//     min  f(Plus(x, delta))
Packit ea1746
//    delta
Packit ea1746
//
Packit ea1746
// Given a solution delta to this problem, the optimal value is then
Packit ea1746
// given by
Packit ea1746
//
Packit ea1746
//   x* = Plus(x, delta)
Packit ea1746
//
Packit ea1746
// The class LocalParameterization defines the function Plus and its
Packit ea1746
// Jacobian which is needed to compute the Jacobian of f w.r.t delta.
Packit ea1746
class CERES_EXPORT LocalParameterization {
Packit ea1746
 public:
Packit ea1746
  virtual ~LocalParameterization();
Packit ea1746
Packit ea1746
  // Generalization of the addition operation,
Packit ea1746
  //
Packit ea1746
  //   x_plus_delta = Plus(x, delta)
Packit ea1746
  //
Packit ea1746
  // with the condition that Plus(x, 0) = x.
Packit ea1746
  virtual bool Plus(const double* x,
Packit ea1746
                    const double* delta,
Packit ea1746
                    double* x_plus_delta) const = 0;
Packit ea1746
Packit ea1746
  // The jacobian of Plus(x, delta) w.r.t delta at delta = 0.
Packit ea1746
  //
Packit ea1746
  // jacobian is a row-major GlobalSize() x LocalSize() matrix.
Packit ea1746
  virtual bool ComputeJacobian(const double* x, double* jacobian) const = 0;
Packit ea1746
Packit ea1746
  // local_matrix = global_matrix * jacobian
Packit ea1746
  //
Packit ea1746
  // global_matrix is a num_rows x GlobalSize  row major matrix.
Packit ea1746
  // local_matrix is a num_rows x LocalSize row major matrix.
Packit ea1746
  // jacobian(x) is the matrix returned by ComputeJacobian at x.
Packit ea1746
  //
Packit ea1746
  // This is only used by GradientProblem. For most normal uses, it is
Packit ea1746
  // okay to use the default implementation.
Packit ea1746
  virtual bool MultiplyByJacobian(const double* x,
Packit ea1746
                                  const int num_rows,
Packit ea1746
                                  const double* global_matrix,
Packit ea1746
                                  double* local_matrix) const;
Packit ea1746
Packit ea1746
  // Size of x.
Packit ea1746
  virtual int GlobalSize() const = 0;
Packit ea1746
Packit ea1746
  // Size of delta.
Packit ea1746
  virtual int LocalSize() const = 0;
Packit ea1746
};
Packit ea1746
Packit ea1746
// Some basic parameterizations
Packit ea1746
Packit ea1746
// Identity Parameterization: Plus(x, delta) = x + delta
Packit ea1746
class CERES_EXPORT IdentityParameterization : public LocalParameterization {
Packit ea1746
 public:
Packit ea1746
  explicit IdentityParameterization(int size);
Packit ea1746
  virtual ~IdentityParameterization() {}
Packit ea1746
  virtual bool Plus(const double* x,
Packit ea1746
                    const double* delta,
Packit ea1746
                    double* x_plus_delta) const;
Packit ea1746
  virtual bool ComputeJacobian(const double* x,
Packit ea1746
                               double* jacobian) const;
Packit ea1746
  virtual bool MultiplyByJacobian(const double* x,
Packit ea1746
                                  const int num_cols,
Packit ea1746
                                  const double* global_matrix,
Packit ea1746
                                  double* local_matrix) const;
Packit ea1746
  virtual int GlobalSize() const { return size_; }
Packit ea1746
  virtual int LocalSize() const { return size_; }
Packit ea1746
Packit ea1746
 private:
Packit ea1746
  const int size_;
Packit ea1746
};
Packit ea1746
Packit ea1746
// Hold a subset of the parameters inside a parameter block constant.
Packit ea1746
class CERES_EXPORT SubsetParameterization : public LocalParameterization {
Packit ea1746
 public:
Packit ea1746
  explicit SubsetParameterization(int size,
Packit ea1746
                                  const std::vector<int>& constant_parameters);
Packit ea1746
  virtual ~SubsetParameterization() {}
Packit ea1746
  virtual bool Plus(const double* x,
Packit ea1746
                    const double* delta,
Packit ea1746
                    double* x_plus_delta) const;
Packit ea1746
  virtual bool ComputeJacobian(const double* x,
Packit ea1746
                               double* jacobian) const;
Packit ea1746
  virtual bool MultiplyByJacobian(const double* x,
Packit ea1746
                                  const int num_cols,
Packit ea1746
                                  const double* global_matrix,
Packit ea1746
                                  double* local_matrix) const;
Packit ea1746
  virtual int GlobalSize() const {
Packit ea1746
    return static_cast<int>(constancy_mask_.size());
Packit ea1746
  }
Packit ea1746
  virtual int LocalSize() const { return local_size_; }
Packit ea1746
Packit ea1746
 private:
Packit ea1746
  const int local_size_;
Packit ea1746
  std::vector<char> constancy_mask_;
Packit ea1746
};
Packit ea1746
Packit ea1746
// Plus(x, delta) = [cos(|delta|), sin(|delta|) delta / |delta|] * x
Packit ea1746
// with * being the quaternion multiplication operator. Here we assume
Packit ea1746
// that the first element of the quaternion vector is the real (cos
Packit ea1746
// theta) part.
Packit ea1746
class CERES_EXPORT QuaternionParameterization : public LocalParameterization {
Packit ea1746
 public:
Packit ea1746
  virtual ~QuaternionParameterization() {}
Packit ea1746
  virtual bool Plus(const double* x,
Packit ea1746
                    const double* delta,
Packit ea1746
                    double* x_plus_delta) const;
Packit ea1746
  virtual bool ComputeJacobian(const double* x,
Packit ea1746
                               double* jacobian) const;
Packit ea1746
  virtual int GlobalSize() const { return 4; }
Packit ea1746
  virtual int LocalSize() const { return 3; }
Packit ea1746
};
Packit ea1746
Packit ea1746
// Implements the quaternion local parameterization for Eigen's representation
Packit ea1746
// of the quaternion. Eigen uses a different internal memory layout for the
Packit ea1746
// elements of the quaternion than what is commonly used. Specifically, Eigen
Packit ea1746
// stores the elements in memory as [x, y, z, w] where the real part is last
Packit ea1746
// whereas it is typically stored first. Note, when creating an Eigen quaternion
Packit ea1746
// through the constructor the elements are accepted in w, x, y, z order. Since
Packit ea1746
// Ceres operates on parameter blocks which are raw double pointers this
Packit ea1746
// difference is important and requires a different parameterization.
Packit ea1746
//
Packit ea1746
// Plus(x, delta) = [sin(|delta|) delta / |delta|, cos(|delta|)] * x
Packit ea1746
// with * being the quaternion multiplication operator.
Packit ea1746
class CERES_EXPORT EigenQuaternionParameterization
Packit ea1746
    : public ceres::LocalParameterization {
Packit ea1746
 public:
Packit ea1746
  virtual ~EigenQuaternionParameterization() {}
Packit ea1746
  virtual bool Plus(const double* x,
Packit ea1746
                    const double* delta,
Packit ea1746
                    double* x_plus_delta) const;
Packit ea1746
  virtual bool ComputeJacobian(const double* x, double* jacobian) const;
Packit ea1746
  virtual int GlobalSize() const { return 4; }
Packit ea1746
  virtual int LocalSize() const { return 3; }
Packit ea1746
};
Packit ea1746
Packit ea1746
// This provides a parameterization for homogeneous vectors which are commonly
Packit ea1746
// used in Structure for Motion problems.  One example where they are used is
Packit ea1746
// in representing points whose triangulation is ill-conditioned. Here
Packit ea1746
// it is advantageous to use an over-parameterization since homogeneous vectors
Packit ea1746
// can represent points at infinity.
Packit ea1746
//
Packit ea1746
// The plus operator is defined as
Packit ea1746
// Plus(x, delta) =
Packit ea1746
//    [sin(0.5 * |delta|) * delta / |delta|, cos(0.5 * |delta|)] * x
Packit ea1746
// with * defined as an operator which applies the update orthogonal to x to
Packit ea1746
// remain on the sphere. We assume that the last element of x is the scalar
Packit ea1746
// component. The size of the homogeneous vector is required to be greater than
Packit ea1746
// 1.
Packit ea1746
class CERES_EXPORT HomogeneousVectorParameterization :
Packit ea1746
      public LocalParameterization {
Packit ea1746
 public:
Packit ea1746
  explicit HomogeneousVectorParameterization(int size);
Packit ea1746
  virtual ~HomogeneousVectorParameterization() {}
Packit ea1746
  virtual bool Plus(const double* x,
Packit ea1746
                    const double* delta,
Packit ea1746
                    double* x_plus_delta) const;
Packit ea1746
  virtual bool ComputeJacobian(const double* x,
Packit ea1746
                               double* jacobian) const;
Packit ea1746
  virtual int GlobalSize() const { return size_; }
Packit ea1746
  virtual int LocalSize() const { return size_ - 1; }
Packit ea1746
Packit ea1746
 private:
Packit ea1746
  const int size_;
Packit ea1746
};
Packit ea1746
Packit ea1746
// Construct a local parameterization by taking the Cartesian product
Packit ea1746
// of a number of other local parameterizations. This is useful, when
Packit ea1746
// a parameter block is the cartesian product of two or more
Packit ea1746
// manifolds. For example the parameters of a camera consist of a
Packit ea1746
// rotation and a translation, i.e., SO(3) x R^3.
Packit ea1746
//
Packit ea1746
// Currently this class supports taking the cartesian product of up to
Packit ea1746
// four local parameterizations.
Packit ea1746
//
Packit ea1746
// Example usage:
Packit ea1746
//
Packit ea1746
// ProductParameterization product_param(new QuaterionionParameterization(),
Packit ea1746
//                                       new IdentityParameterization(3));
Packit ea1746
//
Packit ea1746
// is the local parameterization for a rigid transformation, where the
Packit ea1746
// rotation is represented using a quaternion.
Packit ea1746
class CERES_EXPORT ProductParameterization : public LocalParameterization {
Packit ea1746
 public:
Packit ea1746
  //
Packit ea1746
  // NOTE: All the constructors take ownership of the input local
Packit ea1746
  // parameterizations.
Packit ea1746
  //
Packit ea1746
  ProductParameterization(LocalParameterization* local_param1,
Packit ea1746
                          LocalParameterization* local_param2);
Packit ea1746
Packit ea1746
  ProductParameterization(LocalParameterization* local_param1,
Packit ea1746
                          LocalParameterization* local_param2,
Packit ea1746
                          LocalParameterization* local_param3);
Packit ea1746
Packit ea1746
  ProductParameterization(LocalParameterization* local_param1,
Packit ea1746
                          LocalParameterization* local_param2,
Packit ea1746
                          LocalParameterization* local_param3,
Packit ea1746
                          LocalParameterization* local_param4);
Packit ea1746
Packit ea1746
  virtual ~ProductParameterization();
Packit ea1746
  virtual bool Plus(const double* x,
Packit ea1746
                    const double* delta,
Packit ea1746
                    double* x_plus_delta) const;
Packit ea1746
  virtual bool ComputeJacobian(const double* x,
Packit ea1746
                               double* jacobian) const;
Packit ea1746
  virtual int GlobalSize() const { return global_size_; }
Packit ea1746
  virtual int LocalSize() const { return local_size_; }
Packit ea1746
Packit ea1746
 private:
Packit ea1746
  void Init();
Packit ea1746
Packit ea1746
  std::vector<LocalParameterization*> local_params_;
Packit ea1746
  int local_size_;
Packit ea1746
  int global_size_;
Packit ea1746
  int buffer_size_;
Packit ea1746
};
Packit ea1746
Packit ea1746
}  // namespace ceres
Packit ea1746
Packit ea1746
#include "ceres/internal/reenable_warnings.h"
Packit ea1746
Packit ea1746
#endif  // CERES_PUBLIC_LOCAL_PARAMETERIZATION_H_