Skip to content

Commit

Permalink
[compatibility] mp-units support test
Browse files Browse the repository at this point in the history
  • Loading branch information
FrancoisCarouge committed Nov 28, 2024
1 parent dcec735 commit 15ea2a2
Show file tree
Hide file tree
Showing 14 changed files with 925 additions and 26 deletions.
2 changes: 2 additions & 0 deletions .github/workflows/cppcheck.yml
Original file line number Diff line number Diff line change
Expand Up @@ -46,5 +46,7 @@ jobs:
-I support/eigen \
-I support/generator \
-I support/lazy \
-I support/mp_units \
-I support/naive \
-I support/physical \
.
8 changes: 5 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -292,6 +292,7 @@ Design, development, and testing uncovered unexpected facets of the projects:
- The filter's state, output, and input column vectors should be type template parameters to allow the filter to participate in full compile-time verification of unit- and index-type safeties for input parameters and characteristics.
- There exist Kalman filters with hundreds of state variables.
- The `float` data type has about seven significant digits. Floating point error is a loss of information to account for in design.
- The units of useful matrices are factorizable, i.e. the unit of an element is expressed as the product of the row and column units. The deduced units result type of a matrix product collapses and folds the inner units merely returning the outer units.

## Performance

Expand All @@ -312,16 +313,16 @@ The [benchmarks](https://github.com/FrancoisCarouge/Kalman/tree/master/benchmark

Further terms should be defined and demonstrated for completeness: CKF, EKF-IMM, EnKF, Euler-KF, Fading-Memory, Finite/Fixed-Memory, Forward-Backward, FKF, IEKF, Joseph, KF, Linearized, MEKF, MRP-EKF, MRP-UKF, MSCKF, SKF, Smoother, UKF-GSF, UKF-IMM, USQUE, UDU, and UT.

## Articles

Resources to learn about Kalman filters:
## Related Resources

- [A New Approach to Linear Filtering and Prediction Problems](https://www.cs.unc.edu/~welch/kalman/kalmanPaper.html) by Kalman, Rudolph Emil in Transactions of the ASME - Journal of Basic Engineering, Volume 82, Series D, pp 35-45, 1960 - Transcription by John Lukesh.
- [KalmanFilter.NET](https://www.kalmanfilter.net) by Alex Becker.
- [Kalman and Bayesian Filters in Python](https://github.com/rlabbe/Kalman-and-Bayesian-Filters-in-Python) by Roger Labbe.
- [How Kalman Filters Work](https://www.anuncommonlab.com/articles/how-kalman-filters-work) by Tucker McClure of An Uncommon Lab.
- [Wikipedia Kalman filter](https://en.wikipedia.org/wiki/Kalman_filter) by Wikipedia, the free encyclopedia.
- [Applications of Kalman Filtering in Aerospace 1960 to the Present](https://ieeexplore.ieee.org/stamp/stamp.jsp?tp=&arnumber=5466132) by Mohinder S. Grewal and Angus P. Andrews. IEEE 2010.
- [Taking Static Type-Safety to the Next Level - Physical Units for Matrices](https://www.youtube.com/watch?v=aF3samjRzD4) by Daniel Withopf at CppCon 2022 [slides](https://meetingcpp.com/mcpp/slides/2021/Physical-units-for-matrices6397.pdf).
- [Units Libraries and Autonomous Vehicles: Lessons from the Trenches](https://www.youtube.com/watch?v=5dhFtSu3wCo) by Chip Hogg at CppCon 2021.

## Projects

Expand All @@ -347,6 +348,7 @@ The library is designed, developed, and tested with the help of third-party tool
- [GCC](https://gcc.gnu.org) for compilation and code sanitizers.
- [Google Benchmark](https://github.com/google/benchmark) to implement the benchmarks.
- [lcov](http://ltp.sourceforge.net/coverage/lcov.php) to process coverage information.
- [mp-units](https://github.com/mpusz/mp-units) the quantities and units library for C++.
- [MSVC](https://docs.microsoft.com/en-US/cpp/windows/latest-supported-vc-redist) for compilation and code sanitizers.
- [Valgrind](https://valgrind.org) to check for correct memory management.

Expand Down
26 changes: 24 additions & 2 deletions include/fcarouge/internal/type.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,8 @@ namespace fcarouge::internal {
//! @todo Provide the ::type member access and _t shorthand for simplifying
//! syntax?
template <typename Type> struct state {
using type = Type;

Type value;

constexpr explicit state(Type v) : value{v} {}
Expand All @@ -64,6 +66,8 @@ state(Types... elements)
-> state<std::remove_cvref_t<first_t<Types...>>[sizeof...(Types)]>;

template <typename Type> struct estimate_uncertainty {
using type = Type;

Type value;

template <typename Element>
Expand All @@ -84,6 +88,8 @@ estimate_uncertainty(std::initializer_list<std::initializer_list<Element>>)
std::initializer_list<std::initializer_list<Element>>>;

template <typename Type> struct output_uncertainty {
using type = Type;

Type value;

template <typename Element>
Expand All @@ -104,6 +110,8 @@ output_uncertainty(std::initializer_list<std::initializer_list<Element>>)
std::initializer_list<std::initializer_list<Element>>>;

template <typename Type> struct process_uncertainty {
using type = Type;

Type value;

template <typename Element>
Expand All @@ -123,15 +131,21 @@ process_uncertainty(std::initializer_list<std::initializer_list<Element>>)
-> process_uncertainty<
std::initializer_list<std::initializer_list<Element>>>;

template <typename Type> struct input_t {};
template <typename Type> struct input_t {
using type = Type;
};

template <typename Type> inline input_t<Type> input{};

template <typename Type> struct output_t {};
template <typename Type> struct output_t {
using type = Type;
};

template <typename Type> inline output_t<Type> output{};

template <typename Type> struct output_model {
using type = Type;

Type value;

template <typename Element>
Expand All @@ -150,6 +164,8 @@ output_model(std::initializer_list<std::initializer_list<Element>>)
-> output_model<std::initializer_list<std::initializer_list<Element>>>;

template <typename Type> struct state_transition {
using type = Type;

Type value;

template <typename Element>
Expand All @@ -169,6 +185,8 @@ state_transition(std::initializer_list<std::initializer_list<Element>>)
-> state_transition<std::initializer_list<std::initializer_list<Element>>>;

template <typename Type> struct input_control {
using type = Type;

Type value;

template <typename Element>
Expand All @@ -188,6 +206,8 @@ input_control(std::initializer_list<std::initializer_list<Element>>)

//! @todo Simplify?
template <typename Type> struct transition {
using type = Type;

Type value;

template <typename Element>
Expand All @@ -197,6 +217,8 @@ template <typename Type> struct transition {
template <typename Element> transition(Element) -> transition<Element>;

template <typename Type> struct observation {
using type = Type;

Type value;

template <typename Element>
Expand Down
35 changes: 26 additions & 9 deletions include/fcarouge/internal/utility.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,19 +45,19 @@ For more information, please refer to <https://unlicense.org> */
#include <type_traits>

namespace fcarouge::internal {
//! @todo What should be a better concept of the Kalman filter of this library?
template <typename Type>
concept kalman_filter = requires(Type value) {
//! @todo What should be a better concept of the Kalman filter of this
//! library?
typename Type::state;
typename Type::output;
};

template <typename Type>
concept arithmetic = std::integral<Type> || std::floating_point<Type>;

//! @todo What should be a better concept of an algebraic type?
template <typename Type>
concept algebraic = not arithmetic<Type>;
concept algebraic = requires(Type value) { value(0, 0); };

template <typename Type>
concept eigen = requires { typename Type::PlainMatrix; };
Expand Down Expand Up @@ -259,17 +259,24 @@ struct transposer final {
return value;
}

template <typename Matrix>
requires requires(Matrix value) { value.transpose(); }
[[nodiscard]] inline constexpr auto operator()(const Matrix &value) const {
template <typename Type>
requires requires(Type value) { value.transpose(); }
[[nodiscard]] inline constexpr auto operator()(const Type &value) const {
return value.transpose();
}

template <typename Matrix>
requires requires(Matrix value) { transpose(value); }
[[nodiscard]] inline constexpr auto operator()(const Matrix &value) const {
template <typename Type>
requires requires(Type value) { transpose(value); }
[[nodiscard]] inline constexpr auto operator()(const Type &value) const {
return transpose(value);
}

// How to, should we force external type to provide a transposition
// implementation if the type needs to, should be transposed?
template <typename Type>
[[nodiscard]] inline constexpr auto operator()(const Type &value) const {
return value;
}
};

struct matrix_deducer;
Expand All @@ -287,6 +294,16 @@ struct matrix_deducer final {
requires(eigen<Lhs> or eigen<Rhs>)
[[nodiscard]] inline constexpr auto operator()(Lhs lhs, Rhs rhs) const ->
typename decltype(lhs * transposer{}(rhs))::PlainMatrix;

template <template <typename, typename, typename> typename PhysicalMatrix,
typename Matrix1, typename RowIndexes1, typename Matrix2,
typename RowIndexes2, typename ColumnIndexes>
requires(eigen<Matrix1> or eigen<Matrix2>)
[[nodiscard]] inline constexpr auto
operator()(PhysicalMatrix<Matrix1, RowIndexes1, ColumnIndexes> lhs,
PhysicalMatrix<Matrix2, RowIndexes2, ColumnIndexes> rhs) const
-> PhysicalMatrix<deduce_matrix<Matrix1, Matrix2>, RowIndexes1,
RowIndexes2>;
};

using empty_tuple = std::tuple<>;
Expand Down
7 changes: 5 additions & 2 deletions include/fcarouge/internal/x_z_p_r_f.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -48,11 +48,14 @@ template <typename State, typename Output> struct x_z_p_r_f {
using estimate_uncertainty = deduce_matrix<state, state>;
using output_uncertainty = deduce_matrix<output, output>;
using state_transition = deduce_matrix<state, state>;
using gain = deduce_matrix<state, output>;
using innovation = output;
using innovation_uncertainty = output_uncertainty;
// Internalize gain type deduction as a quotient deducer?
using gain =
std::remove_cvref_t<decltype(std::declval<estimate_uncertainty>() /
std::declval<innovation_uncertainty>())>;

static inline const auto i{identity_v<deduce_matrix<state, state>>};
static inline const auto i{identity_v<gain>};

state x{zero_v<state>};
estimate_uncertainty p{identity_v<estimate_uncertainty>};
Expand Down
2 changes: 2 additions & 0 deletions support/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,9 @@ For more information, please refer to <https://unlicense.org> ]]

add_subdirectory("eigen")
add_subdirectory("main")
add_subdirectory("mp_units")
add_subdirectory("naive")
add_subdirectory("physical")

add_library(kalman_options INTERFACE)

Expand Down
18 changes: 8 additions & 10 deletions support/eigen/fcarouge/linalg.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ For more information, please refer to <https://unlicense.org> */
//! @file
//! @brief Linear algebra facade for Eigen3 third party implementation.
//!
//! @details Matrix, vectors, and named algebraic values.
//! @details Supporting matrix, vectors, and named algebraic values.
//!
//! @note The Eigen3 linear algebra is not constexpr-compatible as of July 2023.

Expand Down Expand Up @@ -95,15 +95,15 @@ constexpr auto operator/(const Numerator &lhs, const Denominator &rhs)
} // namespace fcarouge

//! @brief Specialization of the standard formatter for the Eigen matrix.
template <typename Type, auto Row, auto Column, typename Char>
struct std::formatter<fcarouge::matrix<Type, Row, Column>, Char> {
template <fcarouge::eigen Matrix, typename Char>
struct std::formatter<Matrix, Char> {
constexpr auto parse(std::basic_format_parse_context<Char> &parse_context) {
return parse_context.begin();
}

template <typename OutputIterator>
constexpr auto
format(const fcarouge::matrix<Type, Row, Column> &value,
format(const Matrix &value,
std::basic_format_context<OutputIterator, Char> &format_context) const
-> OutputIterator {
const Eigen::IOFormat output_format{Eigen::StreamPrecision,
Expand All @@ -123,11 +123,10 @@ struct std::formatter<fcarouge::matrix<Type, Row, Column>, Char> {

template <typename OutputIterator>
constexpr auto
format(const fcarouge::matrix<Type, Row, Column> &value,
format(const Matrix &value,
std::basic_format_context<OutputIterator, Char> &format_context) const
-> OutputIterator
requires(fcarouge::matrix<Type, Row, Column>::RowsAtCompileTime == 1 &&
fcarouge::matrix<Type, Row, Column>::ColsAtCompileTime != 1)
requires(Matrix::RowsAtCompileTime == 1 && Matrix::ColsAtCompileTime != 1)
{
const Eigen::IOFormat output_format{Eigen::StreamPrecision,
Eigen::DontAlignCols,
Expand All @@ -146,11 +145,10 @@ struct std::formatter<fcarouge::matrix<Type, Row, Column>, Char> {

template <typename OutputIterator>
constexpr auto
format(const fcarouge::matrix<Type, Row, Column> &value,
format(const Matrix &value,
std::basic_format_context<OutputIterator, Char> &format_context) const
-> OutputIterator
requires(fcarouge::matrix<Type, Row, Column>::RowsAtCompileTime == 1 &&
fcarouge::matrix<Type, Row, Column>::ColsAtCompileTime == 1)
requires(Matrix::RowsAtCompileTime == 1 && Matrix::ColsAtCompileTime == 1)
{
return std::format_to(format_context.out(), "{}", value.value());
}
Expand Down
71 changes: 71 additions & 0 deletions support/mp_units/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
#[[ __ _ __ __ _ _
| |/ / /\ | | | \/ | /\ | \ | |
| ' / / \ | | | \ / | / \ | \| |
| < / /\ \ | | | |\/| | / /\ \ | . ` |
| . \ / ____ \| |____| | | |/ ____ \| |\ |
|_|\_\/_/ \_\______|_| |_/_/ \_\_| \_|
Kalman Filter
Version 0.4.0
https://github.com/FrancoisCarouge/Kalman
SPDX-License-Identifier: Unlicense
This is free and unencumbered software released into the public domain.
Anyone is free to copy, modify, publish, use, compile, sell, or
distribute this software, either in source code form or as a compiled
binary, for any purpose, commercial or non-commercial, and by any
means.
In jurisdictions that recognize copyright laws, the author or authors
of this software dedicate any and all copyright interest in the
software to the public domain. We make this dedication for the benefit
of the public at large and to the detriment of our heirs and
successors. We intend this dedication to be an overt act of
relinquishment in perpetuity of all present and future rights to this
software under copyright law.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
For more information, please refer to <https://unlicense.org> ]]

include(FetchContent)

FetchContent_Declare(
fmt
GIT_REPOSITORY "https://github.com/fmtlib/fmt"
GIT_SHALLOW TRUE
FIND_PACKAGE_ARGS NAMES fmt)
FetchContent_MakeAvailable(fmt)

FetchContent_Declare(
gsl-lite
GIT_REPOSITORY "https://github.com/gsl-lite/gsl-lite"
GIT_SHALLOW TRUE
FIND_PACKAGE_ARGS NAMES gsl-lite)
FetchContent_MakeAvailable(gsl-lite)

FetchContent_Declare(
mp-units
GIT_REPOSITORY "https://github.com/mpusz/mp-units"
GIT_SHALLOW TRUE
SOURCE_SUBDIR "src" FIND_PACKAGE_ARGS NAMES mp-units)
FetchContent_MakeAvailable(mp-units)

target_compile_options(mp-units INTERFACE $<IF:$<CXX_COMPILER_ID:MSVC>, ,
-Wno-double-promotion>)
target_compile_options(mp-units INTERFACE $<IF:$<CXX_COMPILER_ID:MSVC>, ,
-Wno-undef>)

add_library(kalman_unit_mp_units INTERFACE)
target_sources(
kalman_unit_mp_units INTERFACE FILE_SET "unit_headers" TYPE "HEADERS" FILES
"fcarouge/unit.hpp")
target_link_libraries(kalman_unit_mp_units INTERFACE mp-units::mp-units)
Loading

0 comments on commit 15ea2a2

Please sign in to comment.