This guide explains how to use KnownLandmarkFactor and KnownLandmarkFactor2 for localization against fixed landmarks. Prefer KnownLandmarkFactor for normal GTSAM use. It follows the conventional pose direction used throughout GTSAM. KnownLandmarkFactor2 accepts the same physical measurement in the opposite state direction and is intended specifically for exact QCQP and certifiable optimization.
import numpy as np
import gtsamChoose the pose convention first¶
We use the convention that transforms coordinates from frame into frame . A conventional GTSAM pose maps frame into the world. Its inverse maps world coordinates into frame . A fixed landmark is , and its Cartesian measurement in frame is .
| Use case | Factor | State stored in Values | Prediction |
|---|---|---|---|
| Ordinary GTSAM localization (preferred) | KnownLandmarkFactor | wTk.transformTo(wL) | |
| Exact QCQP/certifiable formulation only | KnownLandmarkFactor2 | kTw.transformFrom(wL) |
KnownLandmarkFactor should be the default choice. It uses the standard convention and therefore combines naturally with conventional PriorFactor<Pose3>, BetweenFactor<Pose3>, initial values, plotting utilities, and other GTSAM APIs.
Use KnownLandmarkFactor2 only when building an exact QCQP or certifiable optimization in which the rest of the graph also optimizes . The second variant is not a more accurate measurement model; its only advantage is the algebraic form required by those solvers. It also requires explicit inversion whenever data enter from, or results return to, conventional GTSAM code. Do not insert a value under a key expected to hold , or vice versa.
Both C++ templates support Pose2 and Pose3. Python exposes KnownLandmarkFactorPose2, KnownLandmarkFactorPose3, KnownLandmarkFactor2Pose2, and KnownLandmarkFactor2Pose3.
Prepare one Cartesian landmark measurement¶
Each factor needs four inputs:
the pose key
k;a fixed world landmark
wL;the observed Cartesian point
measured_kP; anda noise model for errors expressed in frame .
The residual is a Cartesian vector, so a Pose3 factor requires a three-dimensional noise model and a Pose2 factor requires a two-dimensional model. A full Gaussian model is appropriate when the observation has anisotropic or correlated uncertainty. In mathematical notation, the covariance below is .
k = 0
wL = np.array([4.0, 1.0, 2.0])
measured_kP = np.array([3.1, 0.8, 1.7])
kPCovariance = np.array(
[
[0.0100, 0.0015, 0.0005],
[0.0015, 0.0040, 0.0008],
[0.0005, 0.0008, 0.0060],
]
)
model = gtsam.noiseModel.Gaussian.Covariance(kPCovariance)Conventional localization with KnownLandmarkFactor¶
For a conventional pose , the predicted frame- point is
implemented by wTk.transformTo(wL). The factor residual is . Add the factor to an ordinary nonlinear graph and insert a conventional wTk initial value under the same key.
graph = gtsam.NonlinearFactorGraph()
graph.add(
gtsam.KnownLandmarkFactorPose3(k, wL, measured_kP, model)
)
wTk_initial = gtsam.Pose3(
gtsam.Rot3.RzRyRx(0.05, -0.02, 0.10),
np.array([0.2, -0.1, 0.3]),
)
initial_wTks = gtsam.Values()
initial_wTks.insert(k, wTk_initial)Build a well-constrained graph¶
One point observation does not determine all six Pose3 degrees of freedom. In a real localization graph, add factors for several geometrically distinct known landmarks and, where appropriate, pose priors or odometry factors. Each observation should carry its own measured_kP and noise model. Reusing the same pose key connects all observations made from that pose.
A known landmark is fixed factor data, not a variable in Values. If the landmark itself must be estimated, use a binary measurement factor such as BearingRangeFactor<Pose3, Point3> instead.
Inverse-state localization with KnownLandmarkFactor2¶
The inverse-state factor predicts the same measured point from :
In code this is kTw.transformFrom(wL). Writing , the prediction is
which is affine in the entries of the homogeneous matrix . After whitening, its squared residual is therefore an exact quadratic cost, so KnownLandmarkFactor2 can contribute directly to a D=1 QcqpProblem.
The preferred conventional prediction uses the inverse action of :
When parameterized by the entries of , the term is bilinear. The residual is therefore not affine in those matrix entries, and its squared norm does not give the exact quadratic cost required by the current QCQP conversion. This algebraic limitation—not a difference in the physical observation—is the reason the second factor exists.
Use this variant only when every factor sharing the pose key expects the inverse convention. For relative measurements, FrobeniusLeftBetweenFactor uses the compatible relation . For ordinary nonlinear optimization, return to the preferred KnownLandmarkFactor.
certifiable_graph = gtsam.NonlinearFactorGraph()
certifiable_graph.add(
gtsam.KnownLandmarkFactor2Pose3(k, wL, measured_kP, model)
)
kTw_initial = wTk_initial.inverse()
initial_kTws = gtsam.Values()
initial_kTws.insert(k, kTw_initial)
# The factor contributes its exact quadratic cost and Pose3 constraints.
qcqp = gtsam.QcqpProblem(certifiable_graph, 1)Practical checklist¶
Prefer
KnownLandmarkFactorPose2/Pose3with conventionalwTkstates.Use
KnownLandmarkFactor2Pose2/Pose3only for QCQP or certifiable optimization over inversekTwstates.Express
wLin the world frame andmeasured_kPin the observing frame .Supply a Cartesian noise model with dimension two for Pose2 or three for Pose3.
Add enough non-degenerate observations or other factors to constrain the pose.
Use a binary landmark factor when the landmark is unknown rather than fixed.
Convert optimized
kTwresults back towTkbefore combining them with conventional GTSAM pose values.
Related documentation¶
KnownLandmarkLocalizationExample is the complete conventional localization tutorial.
CertifiableLocalizationExample combines
KnownLandmarkFactor2withFrobeniusLeftBetweenFactorand SDP solvers.Frobenius factors document the compatible inverse-state relative-pose factor.
WahbaFactor is the rotation-only direction-correspondence analogue.
Dataset utilities document g2o/TORO loading and writing, including 3D landmark observations.