Skip to content

Commit

Permalink
Remove use of mp_units from //filter (#22)
Browse files Browse the repository at this point in the history
Use of `mp_units` results in very long compile-times when building on
the Raspberry Pi. This commit removes its use from `//filter`.

Change-Id: I951300fa9db996dcc34544d780a6cf8e4f070119
  • Loading branch information
oliverlee authored Jul 27, 2023
1 parent 39e98b2 commit 8d86f57
Show file tree
Hide file tree
Showing 3 changed files with 39 additions and 45 deletions.
1 change: 0 additions & 1 deletion filter/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,4 @@ cc_library(
name = "filter",
hdrs = ["filter.hpp"],
visibility = ["//:__subpackages__"],
deps = ["@mp_units"],
)
56 changes: 20 additions & 36 deletions filter/filter.hpp
Original file line number Diff line number Diff line change
@@ -1,30 +1,22 @@
#pragma once

#include <mp-units/systems/si/si.h>
#include <numbers>
#include <utility>

// Low and high pass filters
// https://gitlab.com/mechmotum/row_filter/-/blob/master/row_filter/complementary.py

namespace filter {

namespace mp = mp_units;
namespace si = mp_units::si;

template <
auto CutoffFrequency,
auto SamplePeriod,
class Rep = double,
mp::Quantity Q = mp::quantity<mp::si::radian, Rep>>
template <auto CutoffFrequency, auto SamplePeriod, class Rep = double>
struct lowpass
{
using rep_type = Rep;
using value_type = Rep;

static constexpr auto w0 = mp::quantity<si::radian / si::second, rep_type>{
2 * std::numbers::pi_v<rep_type> * CutoffFrequency};
static constexpr auto dt = mp::quantity<si::second, rep_type>{SamplePeriod};
static constexpr auto w0 =
2 * std::numbers::pi_v<value_type> * CutoffFrequency;
static constexpr auto dt = SamplePeriod;

using value_type = Q;
using derivative_type = decltype(std::declval<value_type>() / dt);

struct signal
Expand All @@ -41,20 +33,20 @@ struct lowpass
static constexpr auto squared = [](auto x) { return x * x; };

static constexpr auto a = squared(w0);
static constexpr auto b = std::numbers::sqrt2_v<rep_type> * w0;
static constexpr auto b = std::numbers::sqrt2_v<value_type> * w0;

// Integrate the filter state equation using the midpoint Euler method with
// time step h
static constexpr auto h = dt;
static constexpr auto h2 = squared(h);
static constexpr auto denom = 4 * mp::one + 2 * h * b + h2 * a;
static constexpr auto denom = 4 + 2 * h * b + h2 * a;

static constexpr auto A = (4 * mp::one + 2 * h * b - h2 * a) / denom;
static constexpr auto A = (4 + 2 * h * b - h2 * a) / denom;
static constexpr auto B = 4 * h / denom;
static constexpr auto C = -4 * h * a / denom;
static constexpr auto D = (4 * mp::one - 2 * h * b - h2 * a) / denom;
static constexpr auto D = (4 - 2 * h * b - h2 * a) / denom;
static constexpr auto E = 2 * h2 * a / denom;
static constexpr auto F = 4 * mp::one * h * a / denom;
static constexpr auto F = 4 * h * a / denom;

const auto x0 = value;
const auto x1 = prev_unfiltered;
Expand All @@ -68,24 +60,16 @@ struct lowpass
}
};

template <
auto CutoffFrequency,
auto SamplePeriod,
class Rep = double,
mp::Quantity Q = mp::quantity<mp::si::radian, Rep>>
template <auto CutoffFrequency, auto SamplePeriod, class Rep = double>
struct highpass
{
using rep_type = Rep;

static constexpr auto w0 = mp::quantity<si::radian / si::second, rep_type>{
2 * std::numbers::pi_v<rep_type> * CutoffFrequency};
static constexpr auto dt = mp::quantity<si::second, rep_type>{SamplePeriod};
using value_type = Rep;

using value_type = Q;
static constexpr auto w0 =
2 * std::numbers::pi_v<value_type> * CutoffFrequency;
static constexpr auto dt = SamplePeriod;

using state_type = std::tuple<
mp::quantity<mp::si::second, rep_type>,
mp::quantity<mp::square(mp::si::second), rep_type>>;
using state_type = std::tuple<value_type, value_type>;

value_type prev_unfiltered{};
state_type prev_state{};
Expand All @@ -106,12 +90,12 @@ struct highpass
const auto xim1 = prev_unfiltered;
const auto [z1im1, z2im1] = prev_state;

static constexpr auto a0 = std::numbers::sqrt2_v<rep_type> * h * w0;
static constexpr auto a0 = std::numbers::sqrt2_v<value_type> * h * w0;
static constexpr auto a1 = squared(h);
static constexpr auto a2 = squared(w0);
static constexpr auto a3 = a1 * a2;
static constexpr auto a4 = 2 * a0;
static constexpr auto a5 = a3 + a4 + 4 * mp::one;
static constexpr auto a5 = a3 + a4 + 4;
static constexpr auto a6 = 1 / a5;
const auto a7 =
a1 * xi + a1 * xim1 - a3 * z2im1 + a4 * z2im1 + 4 * h * z1im1 +
Expand All @@ -122,7 +106,7 @@ struct highpass
a6 *
(a5 * (-a0 * z1im1 - a8 * z2im1 + h * xi + h * xim1 + 2 * z1im1) -
a7 * a8) /
(a0 + 2 * mp::one);
(a0 + 2);
const auto z2i = a6 * a7;
const auto yi = (z1i - z1im1) / h;

Expand Down
27 changes: 19 additions & 8 deletions filter/test/filter_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,24 @@

#include <boost/ut.hpp>

#include <mp-units/systems/si/si.h>
// Clang does not yet support floating point NTTP
//
template <class T>
struct constant
{
using value_type = T;

// NOLINTNEXTLINE(cppcoreguidelines-avoid-const-or-ref-data-members)
const value_type value;

consteval constant(value_type val) : value{val} {}

using namespace mp_units::si::unit_symbols;
constexpr operator T() const { return value; }
};

// NOLINTBEGIN(readability-magic-numbers)
constexpr auto cutoff_freq = 20 * Hz;
constexpr auto sample_period = 5 * ms;
constexpr auto cutoff_freq = constant{20}; // Hz;
constexpr auto sample_period = constant{0.005}; // ms;
// NOLINTEND(readability-magic-numbers)

auto main() -> int
Expand All @@ -18,13 +29,13 @@ auto main() -> int

test("high pass filter invocable") = [] {
auto highpass = filter::highpass<cutoff_freq, sample_period>{};
[[maybe_unused]] const auto [y0, z0] = highpass(1.0 * rad);
[[maybe_unused]] const auto _ = y0.number();
[[maybe_unused]] const auto [y0, z0] = highpass(1.0);
[[maybe_unused]] const auto _ = y0;
};

test("low pass filter invocable") = [] {
auto lowpass = filter::lowpass<cutoff_freq, sample_period>{};
[[maybe_unused]] const auto [y0, yd0] = lowpass(1.0 * rad);
[[maybe_unused]] const auto _ = y0.number();
[[maybe_unused]] const auto [y0, yd0] = lowpass(1.0);
[[maybe_unused]] const auto _ = y0;
};
}

0 comments on commit 8d86f57

Please sign in to comment.