ceres-solver / ceres-solver / 79bbf95103672fa4b5485e055ff7692ee4a1f9da / . / docs / source / modeling_faqs.rst

.. _chapter-modeling_faqs: | |

.. default-domain:: cpp | |

.. cpp:namespace:: ceres | |

======== | |

Modeling | |

======== | |

#. Use analytical/automatic derivatives. | |

This is the single most important piece of advice we can give to | |

you. It is tempting to take the easy way out and use numeric | |

differentiation. This is a bad idea. Numeric differentiation is | |

slow, ill-behaved, hard to get right, and results in poor | |

convergence behaviour. | |

Ceres allows the user to define templated functors which will | |

be automatically differentiated. For most situations this is enough | |

and we recommend using this facility. In some cases the derivatives | |

are simple enough or the performance considerations are such that | |

the overhead of automatic differentiation is too much. In such | |

cases, analytic derivatives are recommended. | |

The use of numerical derivatives should be a measure of last | |

resort, where it is simply not possible to write a templated | |

implementation of the cost function. | |

In many cases it is not possible to do analytic or automatic | |

differentiation of the entire cost function, but it is generally | |

the case that it is possible to decompose the cost function into | |

parts that need to be numerically differentiated and parts that can | |

be automatically or analytically differentiated. | |

To this end, Ceres has extensive support for mixing analytic, | |

automatic and numeric differentiation. See | |

:class:`CostFunctionToFunctor`. | |

#. When using Quaternions, consider using :class:`QuaternionParameterization`. | |

`Quaternions <https://en.wikipedia.org/wiki/Quaternion>`_ are a | |

four dimensional parameterization of the space of three dimensional | |

rotations :math:`SO(3)`. However, the :math:`SO(3)` is a three | |

dimensional set, and so is the tangent space of a | |

Quaternion. Therefore, it is sometimes (not always) beneficial to | |

associate a local parameterization with parameter blocks | |

representing a Quaternion. Assuming that the order of entries in | |

your parameter block is :math:`w,x,y,z`, you can use | |

:class:`QuaternionParameterization`. | |

.. NOTE:: | |

If you are using `Eigen's Quaternion | |

<http://eigen.tuxfamily.org/dox/classEigen_1_1Quaternion.html>`_ | |

object, whose layout is :math:`x,y,z,w`, then you should use | |

:class:`EigenQuaternionParameterization`. | |

#. How do I solve problems with general linear & non-linear | |

**inequality** constraints with Ceres Solver? | |

Currently, Ceres Solver only supports upper and lower bounds | |

constraints on the parameter blocks. | |

A crude way of dealing with inequality constraints is have one or | |

more of your cost functions check if the inequalities you are | |

interested in are satisfied, and if not return false instead of | |

true. This will prevent the solver from ever stepping into an | |

infeasible region. | |

This requires that the starting point for the optimization be a | |

feasible point. You also risk pre-mature convergence using this | |

method. | |

#. How do I solve problems with general linear & non-linear **equality** | |

constraints with Ceres Solver? | |

There is no built in support in ceres for solving problems with | |

equality constraints. Currently, Ceres Solver only supports upper | |

and lower bounds constraints on the parameter blocks. | |

The trick described above for dealing with inequality | |

constraints will **not** work for equality constraints. | |

#. How do I set one or more components of a parameter block constant? | |

Using :class:`SubsetParameterization`. | |

#. Putting `Inverse Function Theorem | |

<http://en.wikipedia.org/wiki/Inverse_function_theorem>`_ to use. | |

Every now and then we have to deal with functions which cannot be | |

evaluated analytically. Computing the Jacobian in such cases is | |

tricky. A particularly interesting case is where the inverse of the | |

function is easy to compute analytically. An example of such a | |

function is the Coordinate transformation between the `ECEF | |

<http://en.wikipedia.org/wiki/ECEF>`_ and the `WGS84 | |

<http://en.wikipedia.org/wiki/World_Geodetic_System>`_ where the | |

conversion from WGS84 to ECEF is analytic, but the conversion | |

back to WGS84 uses an iterative algorithm. So how do you compute the | |

derivative of the ECEF to WGS84 transformation? | |

One obvious approach would be to numerically | |

differentiate the conversion function. This is not a good idea. For | |

one, it will be slow, but it will also be numerically quite | |

bad. | |

Turns out you can use the `Inverse Function Theorem | |

<http://en.wikipedia.org/wiki/Inverse_function_theorem>`_ in this | |

case to compute the derivatives more or less analytically. | |

The key result here is. If :math:`x = f^{-1}(y)`, and :math:`Df(x)` | |

is the invertible Jacobian of :math:`f` at :math:`x`. Then the | |

Jacobian :math:`Df^{-1}(y) = [Df(x)]^{-1}`, i.e., the Jacobian of | |

the :math:`f^{-1}` is the inverse of the Jacobian of :math:`f`. | |

Algorithmically this means that given :math:`y`, compute :math:`x = | |

f^{-1}(y)` by whatever means you can. Evaluate the Jacobian of | |

:math:`f` at :math:`x`. If the Jacobian matrix is invertible, then | |

its inverse is the Jacobian of :math:`f^{-1}(y)` at :math:`y`. | |

One can put this into practice with the following code fragment. | |

.. code-block:: c++ | |

Eigen::Vector3d ecef; // Fill some values | |

// Iterative computation. | |

Eigen::Vector3d lla = ECEFToLLA(ecef); | |

// Analytic derivatives | |

Eigen::Matrix3d lla_to_ecef_jacobian = LLAToECEFJacobian(lla); | |

bool invertible; | |

Eigen::Matrix3d ecef_to_lla_jacobian; | |

lla_to_ecef_jacobian.computeInverseWithCheck(ecef_to_lla_jacobian, invertible); |