pub struct PoseGraph { /* private fields */ }Expand description
Nodes, edges, and the optimisation over them.
Implementations§
Source§impl PoseGraph
impl PoseGraph
Sourcepub fn push(&mut self, edge: Edge) -> Result<(), GraphError>
pub fn push(&mut self, edge: Edge) -> Result<(), GraphError>
Adds an edge, refusing one that names a node that is not there.
Sourcepub fn shape(&self, anchor: usize) -> Shape
pub fn shape(&self, anchor: usize) -> Shape
What shape the edges make, which decides what a solve can do.
Reported rather than discovered by failing: a survey with a node
nothing joins to the anchor is one the normal equations cannot
factorise, and finding that out from GraphError::Singular after the
solve is a worse way to learn it than being told before.
Sourcepub fn residual(&self, edge: &Edge) -> Vector6<f64>
pub fn residual(&self, edge: &Edge) -> Vector6<f64>
The disagreement on one edge: log(T_i⁻¹·T_j·Z⁻¹).
Zero when the two nodes sit exactly as the measurement says. The ordering — the measurement inverted on the right — is what puts the residual in the same frame and the same left-perturbation convention as the information matrix beside it.
Sourcepub fn optimise(
&mut self,
params: &OptimiseParams,
) -> Result<Report, GraphError>
pub fn optimise( &mut self, params: &OptimiseParams, ) -> Result<Report, GraphError>
Levenberg-damped Gauss–Newton until the steps stop mattering.
Source§impl PoseGraph
impl PoseGraph
Sourcepub fn diagnose(&self, anchor: usize) -> Result<Diagnosis, GraphError>
pub fn diagnose(&self, anchor: usize) -> Result<Diagnosis, GraphError>
What the survey looks like from above, at the poses it currently has.
Node spreads come from the pseudo-inverse of H = ΣJᵀΛJ, whose
diagonal blocks are each station’s marginal covariance relative to
the anchor. Pseudo- rather than plain inverse, and that is the whole
point: a survey with a direction nothing constrains has a singular
H, which is not an error to be damped away but the finding. A
damped inverse would answer “this station is known to a centimetre”
where the truth is that nothing in the survey knows where it is.
The null space is left out of the sum rather than inverted into
infinities. Building V·diag(∞)·Vᵀ and reading blocks out of it does
not give infinity where it should — an eigenvector component that is
exactly zero turns ∞·0 into NaN, and the NaNs spread into the
blocks of stations the survey determines perfectly well. Which
coordinates are unconstrained is asked separately, of how much of
each lies in the null space.
The cutoff is relative, at 1e-12 of the largest eigenvalue — the
same shape of judgement the conditioning report makes about a single
registration, one level up.
Trait Implementations§
Auto Trait Implementations§
impl Freeze for PoseGraph
impl RefUnwindSafe for PoseGraph
impl Send for PoseGraph
impl Sync for PoseGraph
impl Unpin for PoseGraph
impl UnsafeUnpin for PoseGraph
impl UnwindSafe for PoseGraph
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§impl<T> Pointable for T
impl<T> Pointable for T
Source§impl<SS, SP> SupersetOf<SS> for SPwhere
SS: SubsetOf<SP>,
impl<SS, SP> SupersetOf<SS> for SPwhere
SS: SubsetOf<SP>,
Source§fn to_subset(&self) -> Option<SS>
fn to_subset(&self) -> Option<SS>
self from the equivalent element of its
superset. Read moreSource§fn is_in_subset(&self) -> bool
fn is_in_subset(&self) -> bool
self is actually part of its subset T (and can be converted to it).Source§fn to_subset_unchecked(&self) -> SS
fn to_subset_unchecked(&self) -> SS
self.to_subset but without any property checks. Always succeeds.Source§fn from_subset(element: &SS) -> SP
fn from_subset(element: &SS) -> SP
self to the equivalent element of its superset.