Skip to content

Commit 2b40ee5

Browse files
authored
Exponantial filter refactoring (#493)
1 parent 18c4b12 commit 2b40ee5

File tree

5 files changed

+347
-18
lines changed

5 files changed

+347
-18
lines changed

control_toolbox/include/control_filters/exponential_filter.hpp

Lines changed: 14 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,12 @@
1818
#include <limits>
1919
#include <memory>
2020
#include <string>
21+
#include <vector>
2122

2223
#include "filters/filter_base.hpp"
2324

25+
#include "control_toolbox/exponential_filter.hpp"
2426
#include "control_toolbox/exponential_filter_parameters.hpp"
25-
#include "control_toolbox/filters.hpp"
2627

2728
namespace control_filters
2829
{
@@ -67,7 +68,7 @@ class ExponentialFilter : public filters::FilterBase<T>
6768
std::shared_ptr<rclcpp::Logger> logger_;
6869
std::shared_ptr<exponential_filter::ParamListener> parameter_handler_;
6970
exponential_filter::Params parameters_;
70-
T last_smoothed_value;
71+
std::shared_ptr<control_toolbox::ExponentialFilter<T>> expo_;
7172
};
7273

7374
template <typename T>
@@ -100,16 +101,20 @@ bool ExponentialFilter<T>::configure()
100101
}
101102
}
102103
parameters_ = parameter_handler_->get_params();
104+
expo_ = std::make_shared<control_toolbox::ExponentialFilter<T>>(parameters_.alpha);
103105

104-
last_smoothed_value = std::numeric_limits<double>::quiet_NaN();
105-
106-
return true;
106+
bool configured = expo_->configure();
107+
if (!configured)
108+
{
109+
RCLCPP_ERROR((*logger_), "ExponentialFilter: Failed to configure underlying filter instance.");
110+
}
111+
return configured;
107112
}
108113

109114
template <typename T>
110115
bool ExponentialFilter<T>::update(const T & data_in, T & data_out)
111116
{
112-
if (!this->configured_)
117+
if (!this->configured_ || !expo_ || !expo_->is_configured())
113118
{
114119
throw std::runtime_error("Filter is not configured");
115120
}
@@ -118,18 +123,12 @@ bool ExponentialFilter<T>::update(const T & data_in, T & data_out)
118123
if (parameter_handler_->is_old(parameters_))
119124
{
120125
parameters_ = parameter_handler_->get_params();
126+
expo_->set_params(parameters_.alpha);
121127
}
122128

123-
if (std::isnan(last_smoothed_value))
124-
{
125-
last_smoothed_value = data_in;
126-
}
127-
128-
data_out = last_smoothed_value =
129-
filters::exponentialSmoothing(data_in, last_smoothed_value, parameters_.alpha);
130-
return true;
129+
// Delegate filtering to toolbox filter instance
130+
return expo_->update(data_in, data_out);
131131
}
132-
133132
} // namespace control_filters
134133

135134
#endif // CONTROL_FILTERS__EXPONENTIAL_FILTER_HPP_
Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
// Copyright (c) 2023, Stogl Robotics Consulting UG (haftungsbeschränkt)
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
#ifndef CONTROL_TOOLBOX__EXPONENTIAL_FILTER_HPP_
16+
#define CONTROL_TOOLBOX__EXPONENTIAL_FILTER_HPP_
17+
18+
#include <cmath>
19+
#include <limits>
20+
#include <memory>
21+
#include <stdexcept>
22+
#include <string>
23+
#include <type_traits>
24+
#include <vector>
25+
26+
#include "control_toolbox/filter_traits.hpp"
27+
#include "control_toolbox/filters.hpp"
28+
29+
namespace control_toolbox
30+
{
31+
template <typename T>
32+
class ExponentialFilter
33+
{
34+
public:
35+
// Default constructor
36+
ExponentialFilter();
37+
explicit ExponentialFilter(double alpha) { set_params(alpha); }
38+
39+
~ExponentialFilter();
40+
41+
bool configure();
42+
43+
bool update(const T & data_in, T & data_out);
44+
45+
bool is_configured() const { return configured_; }
46+
47+
void set_params(double alpha) { alpha_ = alpha; }
48+
49+
private:
50+
double alpha_;
51+
52+
// Define the storage type based on T
53+
using Traits = FilterTraits<T>;
54+
using StorageType = typename Traits::StorageType;
55+
56+
StorageType old_value_;
57+
58+
bool configured_ = false;
59+
};
60+
61+
template <typename T>
62+
ExponentialFilter<T>::ExponentialFilter() : alpha_(0.5)
63+
{
64+
}
65+
66+
template <typename T>
67+
ExponentialFilter<T>::~ExponentialFilter()
68+
{
69+
}
70+
71+
template <typename T>
72+
bool ExponentialFilter<T>::configure()
73+
{
74+
Traits::initialize(old_value_);
75+
76+
return configured_ = true;
77+
}
78+
79+
template <typename T>
80+
bool ExponentialFilter<T>::update(const T & data_in, T & data_out)
81+
{
82+
if (!configured_)
83+
{
84+
throw std::runtime_error("Filter is not configured");
85+
}
86+
87+
// First call: initialize filter state
88+
if (Traits::is_nan(old_value_) || Traits::is_empty(old_value_))
89+
{
90+
if (!Traits::is_finite(data_in))
91+
{
92+
return false;
93+
}
94+
Traits::assign(old_value_, data_in);
95+
}
96+
else
97+
{
98+
Traits::validate_input(data_in, old_value_, data_out);
99+
}
100+
101+
// Convert data_in to StorageType for arithmetic
102+
StorageType storage_in;
103+
Traits::assign(storage_in, data_in);
104+
105+
// Exponential filter update using the templated exponentialSmoothing function
106+
old_value_ = filters::exponentialSmoothing(storage_in, old_value_, alpha_);
107+
108+
Traits::assign(data_out, old_value_);
109+
Traits::add_metadata(data_out, data_in);
110+
111+
return true;
112+
}
113+
114+
} // namespace control_toolbox
115+
116+
#endif // CONTROL_TOOLBOX__EXPONENTIAL_FILTER_HPP_

control_toolbox/include/control_toolbox/filters.hpp

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -40,11 +40,12 @@ namespace filters
4040
/** Exponential smoothing filter. Alpha is between 0 and 1.
4141
* Values closer to 0 weight the last smoothed value more heavily */
4242

43-
static inline double exponentialSmoothing(
44-
double current_raw_value, double last_smoothed_value, double alpha)
43+
template <typename T>
44+
static inline T exponentialSmoothing(
45+
const T & current_raw_value, const T & last_smoothed_value, double alpha)
4546
{
4647
return alpha * current_raw_value + (1 - alpha) * last_smoothed_value;
4748
}
4849
} // namespace filters
4950

50-
#endif // CONTROL_TOOLBOX__FILTERS_HPP_"
51+
#endif // CONTROL_TOOLBOX__FILTERS_HPP_

control_toolbox/src/control_filters/exponential_filter.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,3 +17,10 @@
1717
#include "pluginlib/class_list_macros.hpp"
1818

1919
PLUGINLIB_EXPORT_CLASS(control_filters::ExponentialFilter<double>, filters::FilterBase<double>)
20+
21+
PLUGINLIB_EXPORT_CLASS(
22+
control_filters::ExponentialFilter<std::vector<double>>, filters::FilterBase<std::vector<double>>)
23+
24+
PLUGINLIB_EXPORT_CLASS(
25+
control_filters::ExponentialFilter<geometry_msgs::msg::WrenchStamped>,
26+
filters::FilterBase<geometry_msgs::msg::WrenchStamped>)

0 commit comments

Comments
 (0)