#![allow(unused_imports)]
use factrs::{
assign_symbols,
core::{BetweenResidual, GaussNewton, Graph, Values},
dtype, fac,
linalg::{Const, ForwardProp, Numeric, NumericalDiff, VectorX},
residuals::Residual1,
traits::*,
variables::{SE2, VectorVar2},
};
#[derive(Clone, Debug)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct GpsResidual {
meas: VectorVar2,
}
impl GpsResidual {
pub fn new(x: dtype, y: dtype) -> Self {
Self {
meas: VectorVar2::new(x, y),
}
}
}
#[factrs::mark]
impl Residual1 for GpsResidual {
type Differ = ForwardProp<<Self as Residual1>::DimIn>;
type V1 = SE2;
type DimIn = Const<3>;
type DimOut = Const<2>;
fn residual1<T: Numeric>(&self, v: SE2<T>) -> VectorX<T> {
let p_meas = self.meas.cast();
let p = VectorVar2::from(v.xy().into_owned());
p.ominus(&p_meas)
}
}
assign_symbols!(X: SE2);
fn main() {
let mut graph = Graph::new();
let res = BetweenResidual::new(SE2::new(0.0, 2.0, 0.0));
let odometry_01 = fac![res.clone(), (X(0), X(1)), (0.1, 0.2) as cov];
let odometry_12 = fac![res, (X(1), X(2)), (0.1, 0.2) as cov];
graph.add_factor(odometry_01);
graph.add_factor(odometry_12);
let g0 = fac![GpsResidual::new(0.0, 0.0), X(0), 1.0 as std];
let g1 = fac![GpsResidual::new(2.0, 0.0), X(1), 1.0 as std];
let g2 = fac![GpsResidual::new(4.0, 0.0), X(2), 1.0 as std];
graph.add_factor(g0);
graph.add_factor(g1);
graph.add_factor(g2);
let mut values = Values::new();
values.insert(X(0), SE2::new(1.0, 2.0, 3.0));
values.insert(X(1), SE2::identity());
values.insert(X(2), SE2::identity());
let mut opt: GaussNewton = GaussNewton::new_default(graph);
let result = opt.optimize(values).expect("Optimization failed");
println!("Final Result: {result:#?}");
}