The two-view geometry between two calibrated cameras can be captured in a five-dimensional object known as the essential matrix. EssentialMatrix represents it as a relative rotation and unit translation direction, discarding the unobservable translation scale.
import gtsam
import numpy as npInitialization¶
Construct directly from Rot3 and Unit3, or use FromPose3() to discard the translation magnitude from a relative pose.
relative_pose = gtsam.Pose3(
gtsam.Rot3.Yaw(0.15), np.array([2.0, 0.5, 0.0])
)
essential = gtsam.EssentialMatrix.FromPose3(relative_pose)
print("rotation:")
print(essential.rotation().matrix())
print("translation direction:", essential.direction().unitVector())Matrix and epipolar error¶
matrix() returns the rank-two matrix [t]×R. For corresponding normalized homogeneous points xa and xb, the epipolar constraint is xa.T @ E @ xb = 0. error() provides GTSAM’s two-dimensional geometric residual for a correspondence.
E = essential.matrix()
print("singular values:", np.linalg.svd(E, compute_uv=False))
assert np.linalg.matrix_rank(E, tol=1e-9) == 2Manifold operations¶
The tangent vector has three rotation coordinates and two coordinates on the translation-direction sphere. retract() applies an increment and localCoordinates() recovers it locally.
delta = np.array([0.01, -0.02, 0.01, 0.005, -0.004])
perturbed = essential.retract(delta)
np.testing.assert_allclose(
essential.localCoordinates(perturbed), delta, atol=1e-8
)