Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[cpo] support divides customization point object #31

Merged
merged 1 commit into from
May 11, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
4 changes: 3 additions & 1 deletion .clang-tidy
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,6 @@ Checks: '*,
-fuchsia-overloaded-operator,
-misc-non-private-member-variables-in-classes,
-llvmlibc-*,
-modernize-use-trailing-return-type'
-modernize-use-trailing-return-type,
-altera-struct-pack-align,
-fuchsia-trailing-return'
20 changes: 7 additions & 13 deletions include/fcarouge/internal/kalman.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ namespace fcarouge::internal
template <typename State, typename Output = State, typename Input = State,
template <typename> typename Transpose = transpose,
template <typename> typename Symmetrize = symmetrize,
template <typename, typename> typename Divide = divide,
typename Divide = std::divides<void>,
template <typename> typename Identity = identity,
typename... PredictionArguments>
struct kalman {
Expand All @@ -74,34 +74,28 @@ struct kalman {
//! @brief Type of the estimated covariance matrix P.
//!
//! @details Also known as Σ.
using estimate_uncertainty =
std::invoke_result_t<Divide<State, State>, State, State>;
using estimate_uncertainty = std::invoke_result_t<Divide, State, State>;

//! @brief Type of the process noise covariance matrix Q.
using process_uncertainty =
std::invoke_result_t<Divide<State, State>, State, State>;
using process_uncertainty = std::invoke_result_t<Divide, State, State>;

//! @brief Type of the observation, measurement noise covariance matrix R.
using output_uncertainty =
std::invoke_result_t<Divide<Output, Output>, Output, Output>;
using output_uncertainty = std::invoke_result_t<Divide, Output, Output>;

//! @brief Type of the state transition matrix F.
//!
//! @details Also known as Φ or A.
using state_transition =
std::invoke_result_t<Divide<State, State>, State, State>;
using state_transition = std::invoke_result_t<Divide, State, State>;

//! @brief Type of the observation transition matrix H.
//!
//! @details Also known as C.
using output_model =
std::invoke_result_t<Divide<Output, State>, Output, State>;
using output_model = std::invoke_result_t<Divide, Output, State>;

//! @brief Type of the control transition matrix G.
//!
//! @details Also known as B.
using input_control =
std::invoke_result_t<Divide<State, Input>, State, Input>;
using input_control = std::invoke_result_t<Divide, State, Input>;

//! @}

Expand Down
20 changes: 12 additions & 8 deletions include/fcarouge/internal/kalman_eigen_operator.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@ For more information, please refer to <https://unlicense.org> */

#include <Eigen/Eigen>

#include <type_traits>

namespace fcarouge::eigen::internal
{
//! @brief Function object for performing Eigen matrix transposition.
Expand Down Expand Up @@ -93,20 +95,22 @@ template <typename Type> struct symmetrize {
//!
//! @details Implemented with the Eigen linear algebra library matrices with
//! sizes fixed at compile-time.
//!
//! @tparam Numerator The type template parameter of the dividend.
//! @tparam Denominator The type template parameter of the divisor.
template <typename Numerator, typename Denominator> struct divide {
struct divide {
//! @brief Returns the quotient of `numerator` and `denominator`.
//!
//! @param numerator The dividend of the division.
//! @param denominator The divisor of the division.
//!
//! @exception May throw implementation-defined exceptions.
[[nodiscard]] inline constexpr Eigen::Matrix<typename Numerator::Scalar,
Numerator::RowsAtCompileTime,
Denominator::RowsAtCompileTime>
operator()(const Numerator &numerator, const Denominator &denominator) const
//!
//! @todo Why compilation fails if we specifcy the return type in the body of
//! the function?
[[nodiscard]] inline constexpr auto operator()(const auto &numerator,
const auto &denominator) const
-> typename Eigen::Matrix<
typename std::decay_t<decltype(numerator)>::Scalar,
std::decay_t<decltype(numerator)>::RowsAtCompileTime,
std::decay_t<decltype(denominator)>::RowsAtCompileTime>
{
return denominator.transpose()
.fullPivHouseholderQr()
Expand Down
47 changes: 18 additions & 29 deletions include/fcarouge/internal/kalman_equation.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ For more information, please refer to <https://unlicense.org> */
//! @file
//! @brief Kalman filter main project header.

#include <functional>
#include <type_traits>

namespace fcarouge::internal
Expand All @@ -50,15 +51,15 @@ namespace fcarouge::internal
extrapolate_state(const auto &x, const auto &ff, const auto &f, const auto &g,
const auto &u)
{
using state = std::remove_reference_t<std::remove_cv_t<decltype(x)>>;
using state = std::decay_t<decltype(x)>;

return state{ ff(x, f) + g * u };
}

[[nodiscard]] inline constexpr auto
extrapolate_state(const auto &x, const auto &ff, const auto &f)
{
using state = std::remove_reference_t<std::remove_cv_t<decltype(x)>>;
using state = std::decay_t<decltype(x)>;

return state{ ff(x, f) };
}
Expand All @@ -67,10 +68,8 @@ template <template <typename> class Transpose>
[[nodiscard]] inline constexpr auto
extrapolate_covariance(const auto &p, const auto &f, const auto &q)
{
using estimate_uncertainty =
std::remove_reference_t<std::remove_cv_t<decltype(p)>>;
using state_transition =
std::remove_reference_t<std::remove_cv_t<decltype(f)>>;
using estimate_uncertainty = std::decay_t<decltype(p)>;
using state_transition = std::decay_t<decltype(f)>;

Transpose<state_transition> transpose;

Expand All @@ -84,8 +83,7 @@ inline constexpr void predict(auto &x, auto &p, const auto &ff, const auto &f,
{
x = extrapolate_state(x, ff, f);

using estimate_uncertainty =
std::remove_reference_t<std::remove_cv_t<decltype(p)>>;
using estimate_uncertainty = std::decay_t<decltype(p)>;

Symmetrize<estimate_uncertainty> symmetrize;

Expand All @@ -99,8 +97,7 @@ inline constexpr void predict(auto &x, auto &p, const auto &ff, const auto &f,
{
x = extrapolate_state(x, ff, f, g, u);

using estimate_uncertainty =
std::remove_reference_t<std::remove_cv_t<decltype(p)>>;
using estimate_uncertainty = std::decay_t<decltype(p)>;

Symmetrize<estimate_uncertainty> symmetrize;

Expand All @@ -110,7 +107,7 @@ inline constexpr void predict(auto &x, auto &p, const auto &ff, const auto &f,
[[nodiscard]] inline constexpr auto update_state(const auto &x, const auto &k,
const auto &y)
{
using state = std::remove_reference_t<std::remove_cv_t<decltype(x)>>;
using state = std::decay_t<decltype(x)>;

return state{ x + k * y };
}
Expand All @@ -120,9 +117,8 @@ template <template <typename> typename Transpose,
[[nodiscard]] inline constexpr auto
update_covariance(const auto &p, const auto &k, const auto &h, const auto &r)
{
using estimate_uncertainty =
std::remove_reference_t<std::remove_cv_t<decltype(p)>>;
using gain = std::remove_reference_t<std::remove_cv_t<decltype(k)>>;
using estimate_uncertainty = std::decay_t<decltype(p)>;
using gain = std::decay_t<decltype(k)>;

Transpose<estimate_uncertainty> transpose_p;
Transpose<gain> transpose_k;
Expand All @@ -132,39 +128,33 @@ update_covariance(const auto &p, const auto &k, const auto &h, const auto &r)
k * r * transpose_k(k) };
}

template <template <typename> typename Transpose,
template <typename, typename> typename Divide>
template <template <typename> typename Transpose, typename Divide>
[[nodiscard]] inline constexpr auto weight_gain(const auto &p, const auto &h,
const auto &r)
{
using observation = std::remove_reference_t<std::remove_cv_t<decltype(h)>>;
using output_uncertainty =
std::remove_reference_t<std::remove_cv_t<decltype(r)>>;
using observation = std::decay_t<decltype(h)>;
using gain = std::invoke_result_t<Transpose<observation>, observation>;
using innovation_uncertainty = std::decay_t<decltype(r)>;

Transpose<observation> transpose_h;
Divide<gain, output_uncertainty> divide;

using innovation_uncertainty =
std::remove_reference_t<std::remove_cv_t<decltype(r)>>;
Divide divides;

const innovation_uncertainty s{ h * p * transpose_h(h) + r };

return gain{ divide(p * transpose_h(h), s) };
return gain{ divides(p * transpose_h(h), s) };
}

[[nodiscard]] inline constexpr auto innovate(const auto &x, const auto &z,
const auto &h)
{
using innovation = std::remove_reference_t<std::remove_cv_t<decltype(z)>>;
using innovation = std::decay_t<decltype(z)>;

return innovation{ z - h * x };
}

//! @todo Do we want to allow the client to view the gain k? And the residual y?
template <template <typename> typename Transpose,
template <typename> typename Symmetrize,
template <typename, typename> typename Divide,
template <typename> typename Symmetrize, typename Divide,
template <typename> typename Identity>
inline constexpr void update(auto &x, auto &p, const auto &h, const auto &r,
const auto &z)
Expand All @@ -175,8 +165,7 @@ inline constexpr void update(auto &x, auto &p, const auto &h, const auto &r,

x = update_state(x, k, y);

using estimate_uncertainty =
std::remove_reference_t<std::remove_cv_t<decltype(p)>>;
using estimate_uncertainty = std::decay_t<decltype(p)>;

Symmetrize<estimate_uncertainty> symmetrize;

Expand Down
17 changes: 0 additions & 17 deletions include/fcarouge/internal/kalman_operator.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -75,23 +75,6 @@ template <typename Type> struct symmetrize {
}
};

//! @brief Function object for performing matrix division.
//!
//! @tparam Numerator The type template parameter of the dividend.
//! @tparam Denominator The type template parameter of the divisor.
template <typename Numerator, typename Denominator> struct divide {
//! @brief Returns the quotient of `numerator` and `denominator`.
//!
//! @param numerator The dividend of the division.
//! @param denominator The divisor of the division.
[[nodiscard]] inline constexpr auto
operator()(const Numerator &numerator,
const Denominator &denominator) const noexcept
{
return numerator / denominator;
}
};

//! @brief Function object for providing an identy matrix.
//!
//! @tparam Type The type template parameter of the matrix.
Expand Down
Loading