Automatic differentiation by directly calling AutoDiff::Differentiate does not work

499 views
Skip to first unread message

Stefan R

unread,
Aug 16, 2016, 4:34:45 PM8/16/16
to Ceres Solver
Hi all,

I am stuck at the following problem: I am trying to compute the derivative of a projection function (R^3 -> R^2) with automatic differentiation.
As far as I understand I cannot formulate my function in terms of a residual as it is itself only a part of a larger residual block. Thus, I suppose I cannot use an AutoDiffCostFunction object to compute the derivative.

For that reason I am trying to compute the Jacobian of my projection function by directly calling ceres::internal::AutoDiff::Differentiate (see the following snippet).
However, it only gives me parts of the Jacobian, i.e., the partial derivatives with respect to one output value. That is, the 2nd columns is empty or filled with invalid values. According to the values I get by numerical differentiation the first row is correct though. 

I suppose I have a mistake in the memory layout of the parameter that I am passing to ceres::internal::AutoDiff::Differentiate:
What is wrong here? I appreciate any help or ideas. 

Thanks in advance!
Stefan


Computed Output:

  -------------- manual numerical differentiation ------------------
  J = | 156.697 4.40611 25.0147 |
      | 4.37202 152.994 -37.5199 |

  -------------- autoDiff ------------------
  Y = (    1950.11    2190.52 )
  jacobians = |    156.697    4.40611    25.0147 |
              |          0          0          0 |


Code: For clarity condensed:

/**
 * Computes the function `Y = f(X)` with `X = [x, y, z]` and `Y = [u, v]`.
 *
 * This function also computes the Jacobian `J` of `[u, v] = f(x, y, z)` as
 *  J = | du/dx  du/dy  du/dz|
 *      | dv/dx  dv/dy  dv/dz|.
 */
template<class Functor>
inline bool autoDiff(const Functor& func,
                     const Eigen::Vector3d& X,
                     Eigen::Vector2d& Y,
                     Eigen::Matrix<double, 2, 3>& J)
{
    // Wrap input point double** as required by AutoDiff<> class
    const double* parametersX = &X[0];
    const double** parameters = &parametersX;

    // Init memory for Jacobian
    double** jacobians = new double*[2];
    for(size_t i=0; i<2; i++)
    {
        jacobians[i] = new double[3];
        for(size_t j=0; j<3; j++) {
            jacobians[i][j] = 0;
        }
    }
    
    ceres::internal::AutoDiff<Functor, double, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0>
    ::Differentiate(func, parameters,
                    2*3, Y.data(), (double**) jacobians);

    // Copy to output variable J
    for(size_t i=0; i<2; i++)
        for(size_t j=0; j<3; j++)
            J(i, j) = jacobians[i][j];

    for(size_t i=0; i<2; i++)
        delete[] jacobians[i];
    delete[] jacobians;

    return true;
}

/**
 * Functor to wrap the project() function.
 */
struct CameraProjectionModel
{
    CameraProjectionModel(){}

    CameraProjectionModel(const OCamModelParams* params)
          : params_(params){}

    template <typename T>
    bool operator()(const T point3D[3], T point2D[2]) const
    {
        project(point3D, point2D, this->params_);
        return true;
    }

  const CameraProjectionModelParams* params_;
};



Sameer Agarwal

unread,
Aug 29, 2016, 6:52:44 PM8/29/16
to ceres-...@googlegroups.com
Stefan,
Sorry for the delayed reply. I was traveling. Before we dive into the code I would like to understand better as to what prevents you from using AutoDiffCostFunction?
Sameer



--
You received this message because you are subscribed to the Google Groups "Ceres Solver" group.
To unsubscribe from this group and stop receiving emails from it, send an email to ceres-solver...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/ceres-solver/1b9cdb6b-cb67-4b2f-b8e2-4aa08b57ce72%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
Reply all
Reply to author
Forward
0 new messages