| .. _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); |