Thanks. We're getting closer.
What I'm trying to do:
The SE(3) group has a very simple and elegant jacobian for point motion w.r.t. pose motion. It's literally just a 3x6 matrix that looks like this
J_pose = (I_3x3 , -1 * p-hat)
where p-hat is the cross product matrix of the 3D point in camera coordinates.
SE(3) is also very stable under interpolation and offers better convergence vs. Quaternion-Euclidean or axis-angle-euclidean assemblys esp. with poor initial values for the problem at hand.
The jacobian is 3x6 so it is in tangent space.
My issue is that I'd like to make use of that fine jacobian but I don't see how.
As I see it, It would not make a lot sense for me (or an AutoDiffCostFunction) to compute Jacobians in ambient space since they would have none of those fine properties.
I also do not see how it would be possible for the Manifold to take my full ambient-space-Jacobian, perform some calculations on it and get an (elegant) tangent-space-y Jacobian as a result.
This is because J_pose may only be a part of the entire Jacobian chain. The whole reprojection function might look like this
p_repr =
camIntr(proj(pose * p_3d))
so the full jacobian chain would be J_camIntr * J_proj * J_pose thruogh the chain rule.
Even if I (or an AutoDiffCostFunction) came up with a full ambient-space Jacobian of size 2x12 (12 because 3x3 rotation matrix + a 3vector for translation), it would be entangled with the jacobians of camIntr() (2x2) and proj() (2x3) through the chain rule. And Ceres would not know anything about
camIntr() and proj(), so no way to disentangle either.
I guess my understanding of the purpose of ceres::Manifolds is wrong then. I thought the purpose was to leverage their elegant tangent space jacobians but it seems that's not the case, at least not directly (it would totally be possible if my original assumptions of Jacobian sizes in CostFunction::Evaluate() were true but that's not the case).
For a more concrete example, take SnavelyReprojectionErrorWithQuaternions:
The operator() is templated and a function of several T*s which means it'll be used with ceres::Jets for autodiff.
Inside
operator() it is doing the entire camera transform and projection chain, which means that the Jets will diff through the entire thing and produce an ambient-space jacobian that will (by definition) not be as good as if the quaternion manifold's native tangent-space jacobian had been used for the pose transformation part.
So TLDR it looks like what you're saying is that Manifolds somehow take an ugly ambient-space jacobian, perform some tricks on it and output something better that's tangent-space-y.
And I don't see how that is possible or even desirable.
Sorry, long email. Does this make sense?