X ~ N(\hat X, P)
meaning a perturbation \xi is drawn from a zero-mean Gaussian and
\xi ~ N(0,P), X = \hat X \exp(\xi)
This is for all manifold and groups in GTSAM. If X is Pose 3 or NavState, and represents the state of a vehicle in the navigation/world frame, then \xi above is indeed in the body frame already (as it appears on the right side of X).
That being said, in NavState, the velocity is the “velocity in world coordinates”, even though its uncertainty is represented as above.
To convert velocity to the body frame, you’d use
b_v= bRn n_v = nRb' n_v
which is implemented in NavState::bodyVelocity:
```
Vector3
NavState::bodyVelocity(OptionalJacobian<3,
9>
H)
const {
const Rot3& nRb = R_;
const Vector3 n_v =
t_.col(1);
Matrix3 D_bv_nRb;
Vector3 b_v = nRb.unrotate(n_v, H ? &D_bv_nRb :
0);
if (H)
*H << D_bv_nRb, Z_3x3, I_3x3;
return b_v;
}
```
As you can see, that has a 3x9 Jacobian H, so if your NavState has 9x9 covariance P, then the body velocity uncertainty is H*P*H’.
Note that the last block of H = I_3x3, so indeed the uncertainty on n_v is already in body frame,
but there is a contribution from the rotation uncertainty which is non-zero.
Best
Frank