Skip to content
Open
Show file tree
Hide file tree
Changes from 32 commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
17a7660
feat: added the math and setup of the ESKF, need some changes
Talhanc Feb 9, 2025
dff90b7
feat: added in the IMU msg and DVL msg, pluss ros2 setup
Talhanc Feb 10, 2025
d428dfb
feat: added ES-UKF filter
Talhanc Feb 21, 2025
382b079
feat: added UKF fix injection step
Talhanc Feb 27, 2025
52bdaeb
feat: working ukf filter is added, some issue in the ESUKF
Talhanc Mar 9, 2025
2a3daba
added in some changes to eskf and the ukf algorithm
Talhanc Mar 14, 2025
007c240
added test script
Talhanc Mar 14, 2025
1fb496b
fixed some errors, code runs from eskf_test now
Talhanc Mar 14, 2025
e110152
added changes to ukf
Talhanc Mar 20, 2025
1e02ea2
feat: Added ESKF in cpp using .hpp and .cpp, current implementation u…
Talhanc Mar 28, 2025
1ea9e56
fix: Added correction for the IMU measurements
Talhanc Apr 2, 2025
4cef60d
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Apr 3, 2025
9b44fce
refactor: remove python eskf
Talhanc Apr 3, 2025
ab42232
Merge branch 'main' into feeterror-state-kalman-filter
Talhanc Apr 3, 2025
31c3da2
Merge branch 'main' into feeterror-state-kalman-filter
Andeshog Apr 3, 2025
ea29da3
fix: added errorstate and nominalstate variables into the eskf class
Talhanc Apr 5, 2025
f007908
feat: modified imu correction and added in tested imu noise
Talhanc Apr 17, 2025
20280c2
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Apr 17, 2025
65e8467
feat: added NIS plots
Talhanc May 8, 2025
dd0f97a
fix: issues in innovation and jacobian of the measurement
Talhanc May 13, 2025
103a057
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] May 13, 2025
124f337
feat: Adding in the TUKF and the UKF
Talhanc May 14, 2025
3da7c44
fix: added tukf and simulation
Talhanc May 18, 2025
025410a
fix:added in some minor fixes
Talhanc May 20, 2025
0475154
added the cpp code
Talhanc May 30, 2025
72d13a2
Merge branch 'main' into eskf-and-tukf-test
Talhanc Oct 5, 2025
334519d
fix: removing tukf and some errors in eskf
Talhanc Oct 5, 2025
7d112b8
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Oct 5, 2025
ccc834b
ci: add node test for eskf
Andeshog Oct 7, 2025
b0e115d
Merge branch 'main' into dev/auv-navigation-eskf
Andeshog Oct 7, 2025
916fe46
feat: Added fancy text for starting filter
Talhanc Oct 7, 2025
c6f948e
fix: moved the fancy text variable outside the initiation
Talhanc Oct 7, 2025
80cbd2d
We do a little bit of refactoring
chrstrom Oct 19, 2025
3a1b03c
refactor(eskf): vortex-utils enjoyer
Andeshog Oct 19, 2025
2e78156
merge main
Andeshog Oct 19, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/workflows/ros-node-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ jobs:
matrix:
test_script:
- "tests/ros_node_tests/dp_node_test.sh"
- "tests/ros_node_tests/eskf_node_test.sh"
uses: vortexntnu/vortex-ci/.github/workflows/reusable-ros2-simulator-test.yml@main
with:
vcs_repos_file: "tests/dependencies.repos"
Expand Down
77 changes: 77 additions & 0 deletions navigation/eskf/CMakeLists.txt
Comment thread
Talhanc marked this conversation as resolved.
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
cmake_minimum_required(VERSION 3.8)
project(eskf)

if(NOT CMAKE_CXX_STANDARD)
set(CMAKE_CXX_STANDARD 20)
endif()

if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang")
add_compile_options(-Wall -Wextra -Wpedantic)
endif()

find_package(ament_cmake REQUIRED)
find_package(rclcpp REQUIRED)
find_package(rclcpp_components REQUIRED)
find_package(nav_msgs REQUIRED)
find_package(geometry_msgs REQUIRED)
find_package(Eigen3 REQUIRED)
find_package(tf2 REQUIRED)
find_package(vortex_msgs REQUIRED)
find_package(spdlog REQUIRED)
find_package(fmt REQUIRED)

if(NOT DEFINED EIGEN3_INCLUDE_DIR)
set(EIGEN3_INCLUDE_DIR ${EIGEN3_INCLUDE_DIRS})
endif()

include_directories(${EIGEN3_INCLUDE_DIR})

include_directories(include)

set(LIB_NAME "${PROJECT_NAME}_component")

add_library(${LIB_NAME} SHARED
src/eskf.cpp
src/eskf_ros.cpp
src/eskf_utils.cpp
)

ament_target_dependencies(${LIB_NAME} PUBLIC
rclcpp
rclcpp_components
geometry_msgs
nav_msgs
Eigen3
tf2
vortex_msgs
spdlog
fmt
)

rclcpp_components_register_node(
${LIB_NAME}
PLUGIN "ESKFNode"
EXECUTABLE ${PROJECT_NAME}_node
)

ament_export_targets(export_${LIB_NAME})

install(TARGETS ${LIB_NAME}
EXPORT export_${LIB_NAME}
ARCHIVE DESTINATION lib
LIBRARY DESTINATION lib
RUNTIME DESTINATION bin
)

install(
DIRECTORY include/
DESTINATION include
)

install(DIRECTORY
launch
config
DESTINATION share/${PROJECT_NAME}/
)

ament_package()
8 changes: 8 additions & 0 deletions navigation/eskf/config/eskf_params.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
eskf_node:
ros__parameters:
imu_topic: /imu/data_raw
dvl_topic: /orca/twist
odom_topic: odom
Comment on lines +3 to +5

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

These can go to orca.yaml in auv_setup

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

newdrone.yaml 👀 name not decided yet

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Let this be a thing we do semi last

diag_Q_std: [0.0124, 0.0124, 0.0124, 0.0026, 0.0026, 0.0026, 0.000392, 0.000392, 0.000392, 0.00001145, 0.0000145, 0.0000145]
diag_p_init: [1.0, 1.0, 1.0, 0.5, 0.5, 0.5, 0.1, 0.1, 0.1, 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, 0.001]
imu_frame: [0.0, 0.0, -1.0, 0.0, -1.0, 0.0, -1.0, 0.0, 0.0]
88 changes: 88 additions & 0 deletions navigation/eskf/include/eskf/eskf.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
#ifndef ESKF_HPP
#define ESKF_HPP

#include <eigen3/Eigen/Dense>
#include <utility>
#include "eskf/typedefs.hpp"
#include "typedefs.hpp"

class ESKF {
public:
ESKF(const eskf_params& params);

// @brief Update the nominal state and error state
// @param imu_meas: IMU measurement
// @param dt: Time step
// @return Updated nominal state and error state
std::pair<state_quat, state_euler> imu_update(
const imu_measurement& imu_meas,
const double dt);

// @brief Update the nominal state and error state
// @param dvl_meas: DVL measurement
// @return Updated nominal state and error state
std::pair<state_quat, state_euler> dvl_update(
const dvl_measurement& dvl_meas);

// Normalized Innovation Squared
double NIS_{};

private:
// @brief Predict the nominal state
// @param imu_meas: IMU measurement
// @param dt: Time step
// @return Predicted nominal state
void nominal_state_discrete(const imu_measurement& imu_meas,
const double dt);

// @brief Predict the error state
// @param imu_meas: IMU measurement
// @param dt: Time step
// @return Predicted error state
void error_state_prediction(const imu_measurement& imu_meas,
const double dt);

// @brief Calculate the NIS
// @param innovation: Innovation vector
// @param S: Innovation covariance matrix
void NIS(const Eigen::Vector3d& innovation, const Eigen::Matrix3d& S);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I suggest thinking about visualization from the start. Don't know if you want to implement it seperately or inside this library e.g calculate ANIS function, print covariance elipse function ... , but you should not neglect it. Would be nice to have some nice visuals on propagation of error state and maybe when / how covariances blow up.

"I've probably spent 80% of my time on visualization and understanding and 20% of my time doing math and programming" -Edmund

Probably helps with debugging later if you have put thought into testing from the start. But then again i am no expert on this (yet, give me 4 weeks ¯_(ツ)_/¯ )

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I think we need to look a this later on, but yes a good way to plot would be nice. The issue though is that i would like to have a plot of the estimates with there uncertainty, NEES and NIS given that we have ground truth. This will make it easier for you to test. The issue is that NIS upper and lower bounds depends on the amount of measurements, which can become a problem ( i feel so ) if we have different dimensions and different measurements.


// @brief Update the error state
// @param dvl_meas: DVL measurement
void measurement_update(const dvl_measurement& dvl_meas);

// @brief Inject the error state into the nominal state and reset the error
void injection_and_reset();

// @brief Van Loan discretization
// @param A_c: Continuous state transition matrix
// @param G_c: Continuous input matrix
// @return Discrete state transition matrix and discrete input matrix
std::pair<Eigen::Matrix18d, Eigen::Matrix18d> van_loan_discretization(
const Eigen::Matrix18d& A_c,
const Eigen::Matrix18x12d& G_c,
const double dt);

// @brief Calculate the measurement matrix jakobian
// @return Measurement matrix
Eigen::Matrix3x19d calculate_hx();

// @brief Calculate the full measurement matrix
// @return Measurement matrix
Eigen::Matrix3x18d calculate_h_jacobian();

// @brief Calculate the measurement
// @return Measurement
Eigen::Vector3d calculate_h();

// Process noise covariance matrix
Eigen::Matrix12d Q_{};

// Member variable for the current error state
state_euler current_error_state_{};

// Member variable for the current nominal state
state_quat current_nom_state_{};
};

#endif // ESKF_HPP
74 changes: 74 additions & 0 deletions navigation/eskf/include/eskf/eskf_ros.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
#ifndef ESKF_ROS_HPP
#define ESKF_ROS_HPP

#include <chrono>
#include <geometry_msgs/msg/pose_with_covariance_stamped.hpp>
#include <geometry_msgs/msg/twist_with_covariance_stamped.hpp>
#include <nav_msgs/msg/odometry.hpp>
#include <rclcpp/rclcpp.hpp>
#include <sensor_msgs/msg/imu.hpp>
#include <std_msgs/msg/bool.hpp>
#include <std_msgs/msg/float64.hpp>
#include <std_msgs/msg/float64_multi_array.hpp>
#include <std_msgs/msg/string.hpp>
#include "eskf/eskf.hpp"
#include "eskf/typedefs.hpp"
#include "spdlog/spdlog.h"

class ESKFNode : public rclcpp::Node {
public:
explicit ESKFNode(
const rclcpp::NodeOptions& options = rclcpp::NodeOptions());

private:
// @brief Callback function for the imu topic
// @param msg: Imu message containing the imu data
void imu_callback(const sensor_msgs::msg::Imu::SharedPtr msg);

// @brief Callback function for the dvl topic
// @param msg: TwistWithCovarianceStamped message containing the dvl data
void dvl_callback(
const geometry_msgs::msg::TwistWithCovarianceStamped::SharedPtr msg);

// @brief Publish the odometry message
void publish_odom();

// @brief Set the subscriber and publisher for the node
void set_subscribers_and_publisher();

// @brief Set the parameters for the eskf
void set_parameters();

rclcpp::Subscription<sensor_msgs::msg::Imu>::SharedPtr imu_sub_;

rclcpp::Subscription<
geometry_msgs::msg::TwistWithCovarianceStamped>::SharedPtr dvl_sub_;

rclcpp::Publisher<nav_msgs::msg::Odometry>::SharedPtr odom_pub_;

rclcpp::Publisher<std_msgs::msg::Float64>::SharedPtr nis_pub_;

std::chrono::milliseconds time_step;

rclcpp::TimerBase::SharedPtr odom_pub_timer_;

state_quat nom_state_{};

state_euler error_state_{};

imu_measurement imu_meas_{};

dvl_measurement dvl_meas_{};

eskf_params eskf_params_{};

std::unique_ptr<ESKF> eskf_;

bool first_imu_msg_received_ = false;

Eigen::Matrix3d R_imu_eskf_{};

rclcpp::Time last_imu_time_{};
};

#endif // ESKF_ROS_HPP
38 changes: 38 additions & 0 deletions navigation/eskf/include/eskf/eskf_utils.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
#ifndef ESKF_UTILS_HPP
#define ESKF_UTILS_HPP

#include <cmath>
#include "eigen3/Eigen/Dense"
#include "eskf/typedefs.hpp"

// @brief Compute the skew-symmetric matrix of a vector
// @param v: Input vector
// @return Skew-symmetric matrix
Eigen::Matrix3d skew(const Eigen::Vector3d& v);

// @brief Square a value
Comment thread
chrstrom marked this conversation as resolved.
Outdated
// @param value: Input value
// @return Squared value
double sq(double value);

// @brief Normalize an angle to the range [-pi, pi]
// @param angle: Input angle in radians
// @return Normalized angle in radians
double ssa(double angle);

// @brief Calculate the transformation matrix using a quaternion
// @param quat: Input quaternion
// @return Transformation matrix
Eigen::Matrix4x3d calculate_T_q(const Eigen::Quaterniond& quat);

// @brief Convert a rotation vector to a quaternion
// @param vector: Input rotation vector
// @return Corresponding quaternion
Eigen::Quaterniond vector3d_to_quaternion(const Eigen::Vector3d& vector);

// @brief Convert Euler angles to a quaternion
// @param euler: Input Euler angles (roll, pitch, yaw) in radians
// @return Corresponding quaternion
Eigen::Quaterniond euler_to_quaternion(const Eigen::Vector3d& euler);

#endif // ESKF_UTILS_HPP
Loading
Loading