Skip to content

Conversation

@jenniferoum
Copy link
Contributor

Updates to template equivariant filter on group and manifold

  • Also template on geometry structure to allow functions to be called in EquivariantFilter.h
  • Reorganize files:
    • ABC.h contains geometry specific definitions
    • EquivariantFilter.h contains fitler specific functions
    • Renamed ABC_EQF_Demo to AbbcEquivariantFilterExample.cpp

Copy link
Member

@dellaert dellaert left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice progress! Some initial comments.

…equire for template, change EqF to take in initial state, use traits for group
@jenniferoum jenniferoum force-pushed the feature/equivariant-filter branch from 73215df to 4ee2efe Compare July 30, 2025 17:20
Matrix Q = Geometry::processNoise(u); // Replaces blockDiag(...)

X_hat = traits<G>::Compose(X_hat, traits<G>::Expmap(L * dt));
Sigma = Phi * Sigma * Phi.transpose() + Bt * Q * Bt.transpose() * dt;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is already done in the ManifoldEKF, specialized to groups in the LieGroupEKF, which is the main reason to derive form that class.

Vector3 delta_vec = Rot3::Hat(y.d.unitVector()) * action_result;
Matrix Dt = Geometry::outputMatrixDt(y.cal_idx, X_hat);

Matrix S = Ct * Sigma * Ct.transpose() + Dt * y.Sigma * Dt.transpose();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You'll also find this somewhere in the existing hierarchy.

@AlessandroFornasier
Copy link

Nice to see this one in gtsam 👍🏻

@dellaert
Copy link
Member

Thans @AlessandroFornasier !We're going to substantially rewrite and base on LieGroupEKF (or derived), we'll let you know :-)

Copy link
Member

@dellaert dellaert left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good meeting. Trying to give some more feedback here. The goal is whether we can get rid of Geometry altogether.


/// Initialize the symmetry group G
G(const Rot3& A = Rot3::Identity(), const Matrix3& a = Matrix3::Zero(),
static constexpr int numSensors = N;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should also be small n if we are to match the paper.


// Adjoint matrix of this group element (for SE(3) or similar)
Eigen::Matrix<double, dimension, dimension> AdjointMap() const {
// TODO: implement properly for your group structure.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would be nice to implement for your group, or at least figure out the math, as in the invariant filter the A matrix is just $Ad_{U^{-1}}$. Might that be the case as well here, with U the “lifted” dynamics?

*/
template <size_t N>
Input velocityAction(const G<N>& X, const Input& u) {
Input velocityAction(const Group<N>& X, const Input& u) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The Input type is mixing two things I believe: a mathematical object, $(\omega,0)$ where the zeros are that “virtual” input. And then a data structure that is used to store noise parameters and what not. I think the code will be a lot more clear if you separate those concerns, rename Input to InputData, and then redefine Input as simply

Using Input = Vector6

Or even just use Vector6.

return gtsam::numericalDerivative11<Vector, G<N>>(
[&xi](const G<N>& g) { return xi.localCoordinates(g * xi); },
gtsam::traits<G<N>>::Identity());
return gtsam::numericalDerivative11<Vector, Group<N>>(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If this is only used in tests move it there.

#pragma once
#include <gtsam/base/Matrix.h>
#include <gtsam/base/Vector.h>
#include <gtsam/geometry/Rot3.h>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These includes seem out of place when M and G are generic.

void update(const typename Geometry::Measurement& y);

static constexpr int DOF = gtsam::traits<G>::dimension;
static constexpr int n_cal = Geometry::n_cal;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also out of place in a generic filter.

* @return Linearized state matrix
* Uses Matrix zero and Identity functions
*/
static Matrix stateMatrixA(const GType& X_hat, const Input& u) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this actually used in the filter?

Matrix Q = Geometry::processNoise(u);


this->X_ = traits<G>::Compose(this->X_, traits<G>::Expmap(L * dt));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This makes me think $\Phi = Ad_{U^{-1}}$ with $U=L dt$. If so we can then kill it from Geometry - and I bet this holds for any equivariant filter that updates the state this way. Look at the InvariantEKF.

Vector Delta = InnovationLift * K * delta_vec;
this->X_ = traits<G>::Compose(traits<G>::Expmap(Delta), this->X_);
this->P_ = (Matrix::Identity(DOF, DOF) - K * Ct) * this->P_;
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Try to see whether you can do this update by constructing the parameters of update in the base class. It will be informative.


/// Input struct for the Biased Attitude System

struct Input {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would split this file up: ABC.h is pure geometry. All the other data structures (Input, etc) should be moved to the example - there should be zero “infra” code in this geometry code.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants