Different values between shared and local computations

44 views

Georgios

Feb 20, 2023, 11:48:48 AMFeb 20
to Ceres Solver
Hi!

I've been using ceres with AutoDiffCostFunction for optimizing a 3D scene problem for a while ad it works great. Basically, I take points from the image plane, project them onto a surface in the 3D world and compute the distance to the ground truth point. My next step is to optimize this and an obvious pain point is that I use the axis angle rotation of the camera for every single point I project (i.e. for every single cost functor) and this means computing the same sin() and cos() a lot of times in every iteration. So I thought; Enter EvaluationCallback!

All I do in my evaluation callback functor's PrepareForEvaluation() is to convert the axis-angle parameters to a 3x3 double matrix (using ceres::AngleAxisToRotationMatrix()). A ref to this matrix is passed to my cost functor and when it's called to evaluate it will ignore the rotation parameter block and just use the pre-computed matrix instead after convering it form Mat<double> to Mat<T>.

Now, when I ran this it didn't perform as well as before. If I go back to using the passed parameter block it works as expected, even though I simply convert it to a matrix in-place the same way I do it in the callback.

Since I now have both the "prepared" rotation matrix and the locally computed one available I tried subtracting them to output the difference and I see that about half the time they're identical, but other times they will differ by small values ~1e-16. What could cause this? Is it because the cos() and sin() isn't done with Jets? Could this be the source of my troubles in that case?

Best regards,
Georgios

Dmitriy Korchemkin

Feb 20, 2023, 2:59:44 PMFeb 20
Hi, Georgios

Creating ceres::Jet from double scalar results into vector part (derivatives) being set to zero.

Thus, point projections will have zero entries in Jacobians, corresponding to derivatives by rotation parameterization.

If the only performance concern is speed of trigonometric operations, one possible solution is to use quaternions for rotation parameterization, since that makes group action on points expressible in multiplications and additions (with trigonometry being "moved" to Manifold::Plus or LocalParameterization::Plus, depending on ceres version, which are being called "almost" once per iteration for each corresponding parameter block).

Keep in mind that caching matrix of ceres::Jet might also result into problems, if vector parts of the Jets are inconsistent with function that is being auto-differentiated.

--
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.