i_fusion_policy.hpp¶
IFusionPolicy — the swap point that lets a complementary filter ship NOW and a 5-state SE(2) EKF drop in LATER behind the same seam.
This header declares 1 type (7 members).
Extracted from include/shulib/localization/i_fusion_policy.hpp — this page is that header's documentation, reformatted, so it cannot disagree with the code. Prose about how to think about the API lives in the user guide; worked recipes live in the cookbook; this page is the complete, mechanical list of what exists.
Contents¶
class IFusionPolicy~IFusionPolicyIFusionPolicyIFusionPolicy (overload 2)IFusionPolicy (overload 3)operator=operator= (overload 2)fuse
class IFusionPolicy¶
The seam a fusion MECHANISM plugs into: how hard to move the estimate toward the absolute fixes that arrived this tick. TWO tiers ship behind it: ComplementaryFusion (the gated, rate-limited nudge, still the default) and EkfFusion (a 5-state SE(2) Kalman update with Mahalanobis gating). Picking one is a single constructor argument to the Localizer, with ICorrector, the Localizer API and every caller unchanged across the swap — which is the only reason this is an interface and not a function. An implementation MAY be stateful and may equally be pure, so callers must assume the worse of the two: EkfFusion carries the filter state (x, P) across ticks, while ComplementaryFusion holds nothing but its config and that tier's cross-tick memory lives in the Localizer instead (fusedX_/fusedY_ and the heading bias). So fuse() is not guaranteed to be a function of its arguments alone, and one policy object must not be shared between two Localizers. The Localizer calls fuse() exactly once per update(), UNCONDITIONALLY — during the boot/settle window it is still called, with an empty span of proposals.
class, declared at include/shulib/localization/i_fusion_policy.hpp:31.
IFusionPolicy::~IFusionPolicy¶
Virtual so an owner holding a policy polymorphically can destroy it — the Localizer is not that owner: it takes IFusionPolicy& and never deletes it, so the policy must outlive the Localizer that was handed it. The copy/move members are re-defaulted (a user-declared destructor suppresses the implicit MOVEs and deprecates the implicit copies) only so this base imposes no policy of its own. Copying a real one is tier-dependent and rarely what you want: ComplementaryFusion is pure config, but an EkfFusion copy clones a live BELIEF (state and covariance), which then ages independently of the original.
function, declared at include/shulib/localization/i_fusion_policy.hpp:40.
IFusionPolicy::IFusionPolicy¶
Covered by the comment on ~IFusionPolicy — one comment documents this run of special members.
function, declared at include/shulib/localization/i_fusion_policy.hpp:41.
IFusionPolicy::IFusionPolicy (overload 2)¶
Covered by the comment on ~IFusionPolicy — one comment documents this run of special members.
function, declared at include/shulib/localization/i_fusion_policy.hpp:42.
IFusionPolicy::IFusionPolicy (overload 3)¶
Covered by the comment on ~IFusionPolicy — one comment documents this run of special members.
function, declared at include/shulib/localization/i_fusion_policy.hpp:43.
IFusionPolicy::operator=¶
Covered by the comment on ~IFusionPolicy — one comment documents this run of special members.
function, declared at include/shulib/localization/i_fusion_policy.hpp:44.
IFusionPolicy::operator= (overload 2)¶
Covered by the comment on ~IFusionPolicy — one comment documents this run of special members.
function, declared at include/shulib/localization/i_fusion_policy.hpp:45.
IFusionPolicy::fuse¶
[[nodiscard]] virtual FusionResult fuse(const math::Pose2d& predicted, std::span<const CorrectionProposal> valid, units::Time dt) = 0
Fold the valid proposals into the predicted position and return the corrected (x, y), the bounded heading INCREMENT added at E3 (headingNudge and its three flags, which the Localizer folds into a persistent heading bias), and the audit flags. valid holds only already-screened proposals (valid && confidence>0 && positionStdDev>0 && finite). dt is the tick duration (for a rate-based per-tick clamp).
function, declared at include/shulib/localization/i_fusion_policy.hpp:51.
Design commentary, from the header¶
The header opens with the reasoning behind these shapes. It is reproduced here in full because a reference that only lists signatures teaches nobody why.
The header’s own reasoning — 7 lines
IFusionPolicy — the swap point that lets a complementary filter ship NOW and a 5-state SE(2) EKF
drop in LATER behind the same seam (master plan §8: "complementary → EKF"). Given the predicted
pose and the valid proposals, it returns the corrected position AND, since E3, a bounded heading INCREMENT (FusionResult's headingNudge/headingApplied/headingGated/headingClamped, which localizer.hpp folds into a persistent heading bias). The pre-E3 wording said "POSITION only" and was left behind by that chunk — heading is re-stamped from
the IMU by the Localizer afterward, so a policy can never own heading at M2. ComplementaryFusion
(the gated nudge) implements this now; EkfFusion (Kalman update + Mahalanobis gating) drops in at
M3+ without changing ICorrector, the Localizer API, or a single caller.
Last updated 2026-08-15 — published from the main release branch, commit fa545ff. This site tracks releases, so between them it can lag the repository — that lag is deliberate, and it is what keeps the development log off the public site. For the current state of the code, see the repository.