use apex_manifolds::LieGroup;
use apex_manifolds::se23::SE23;
use faer::prelude::ReborrowMut;
use crate::core::variable::ManifoldVariable;
use crate::factors::Factor;
use crate::factors::common::math::skew;
use crate::factors::common::validate::expect_block_sizes;
#[derive(Debug, Clone, Default)]
pub struct NonholonomicFactor;
impl NonholonomicFactor {
pub fn new() -> Self {
Self
}
}
impl Factor for NonholonomicFactor {
fn linearize(
&self,
params: &[&[f64]],
residual: &mut [f64],
jacobian: Option<faer::mat::MatMut<'_, f64>>,
) {
let state = SE23::from_param_slice(params[0]);
let rotation = state.rotation_matrix();
let v_body = rotation.transpose() * state.velocity();
residual[0] = v_body.y;
residual[1] = v_body.z;
let Some(mut jac) = jacobian else { return };
let d_theta = skew(&v_body);
for (row, component) in [1usize, 2].iter().enumerate() {
for col in 0..9 {
*jac.rb_mut().get_mut(row, col) = 0.0;
}
for col in 0..3 {
*jac.rb_mut().get_mut(row, 3 + col) = d_theta[(*component, col)];
}
*jac.rb_mut().get_mut(row, 6 + *component) = 1.0;
}
}
fn residual_dim(&self) -> usize {
2
}
fn jacobian_shape(&self) -> (usize, usize) {
(2, 9)
}
fn validate_variables(&self, variables: &[&dyn ManifoldVariable]) -> Result<(), String> {
expect_block_sizes(
variables,
&[SE23::REP_SIZE],
"NonholonomicFactor expects [SE23 state]",
)
}
}