Skip to content

Commit e817778

Browse files
Make member variables of LowPassFilter class generic
Signed-off-by: Pedro Nogueira <pedro_azeredo@usp.br>
1 parent ab67c3e commit e817778

File tree

1 file changed

+63
-49
lines changed

1 file changed

+63
-49
lines changed

control_toolbox/include/control_toolbox/low_pass_filter.hpp

Lines changed: 63 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
#include <memory>
2323
#include <stdexcept>
2424
#include <string>
25+
#include <type_traits>
2526
#include <vector>
2627

2728
#include "geometry_msgs/msg/wrench_stamped.hpp"
@@ -123,10 +124,17 @@ class LowPassFilter
123124
// Filter parameters
124125
double a1_; /** feedbackward coefficient. */
125126
double b1_; /** feedforward coefficient. */
126-
/** internal data storage of template type. */
127-
T filtered_value, filtered_old_value, old_value;
128-
/** internal data storage (wrench). */
129-
Eigen::Matrix<double, 6, 1> msg_filtered, msg_filtered_old, msg_old;
127+
128+
// Define the storage type based on T
129+
using StorageType = typename std::conditional<
130+
std::is_same<T, geometry_msgs::msg::WrenchStamped>::value, Eigen::Matrix<double, 6, 1>,
131+
T>::type;
132+
133+
// Member variables
134+
StorageType filtered_value_;
135+
StorageType filtered_old_value_;
136+
StorageType old_value_;
137+
130138
bool configured_ = false;
131139
};
132140

@@ -143,12 +151,18 @@ LowPassFilter<T>::~LowPassFilter()
143151
template <typename T>
144152
bool LowPassFilter<T>::configure()
145153
{
146-
// Initialize storage Vectors
147-
filtered_value = filtered_old_value = old_value = std::numeric_limits<T>::quiet_NaN();
148-
// TODO(destogl): make the size parameterizable and more intelligent is using complex types
149-
for (Eigen::Index i = 0; i < 6; ++i)
154+
// Initialize storage Vectors, depending on the type of T
155+
if constexpr (std::is_same<T, geometry_msgs::msg::WrenchStamped>::value)
156+
{
157+
// TODO(destogl): make the size parameterizable and more intelligent is using complex types
158+
for (Eigen::Index i = 0; i < 6; ++i)
159+
{
160+
filtered_value_[i] = filtered_old_value_[i] = old_value_[i] = std::numeric_limits<double>::quiet_NaN();
161+
}
162+
}
163+
else
150164
{
151-
msg_filtered[i] = msg_filtered_old[i] = msg_old[i] = std::numeric_limits<double>::quiet_NaN();
165+
filtered_value_ = filtered_old_value_ = old_value_ = std::numeric_limits<T>::quiet_NaN();
152166
}
153167

154168
return configured_ = true;
@@ -164,36 +178,36 @@ inline bool LowPassFilter<geometry_msgs::msg::WrenchStamped>::update(
164178
}
165179
// If this is the first call to update initialize the filter at the current state
166180
// so that we dont apply an impulse to the data.
167-
if (msg_filtered.hasNaN())
181+
if (filtered_value_.hasNaN())
168182
{
169-
msg_filtered[0] = data_in.wrench.force.x;
170-
msg_filtered[1] = data_in.wrench.force.y;
171-
msg_filtered[2] = data_in.wrench.force.z;
172-
msg_filtered[3] = data_in.wrench.torque.x;
173-
msg_filtered[4] = data_in.wrench.torque.y;
174-
msg_filtered[5] = data_in.wrench.torque.z;
175-
msg_filtered_old = msg_filtered;
176-
msg_old = msg_filtered;
183+
filtered_value_[0] = data_in.wrench.force.x;
184+
filtered_value_[1] = data_in.wrench.force.y;
185+
filtered_value_[2] = data_in.wrench.force.z;
186+
filtered_value_[3] = data_in.wrench.torque.x;
187+
filtered_value_[4] = data_in.wrench.torque.y;
188+
filtered_value_[5] = data_in.wrench.torque.z;
189+
filtered_old_value_ = filtered_value_;
190+
old_value_ = filtered_value_;
177191
}
178192

179193
// IIR Filter
180-
msg_filtered = b1_ * msg_old + a1_ * msg_filtered_old;
181-
msg_filtered_old = msg_filtered;
194+
filtered_value_ = b1_ * old_value_ + a1_ * filtered_old_value_;
195+
filtered_old_value_ = filtered_value_;
182196

183197
// TODO(destogl): use wrenchMsgToEigen
184-
msg_old[0] = data_in.wrench.force.x;
185-
msg_old[1] = data_in.wrench.force.y;
186-
msg_old[2] = data_in.wrench.force.z;
187-
msg_old[3] = data_in.wrench.torque.x;
188-
msg_old[4] = data_in.wrench.torque.y;
189-
msg_old[5] = data_in.wrench.torque.z;
190-
191-
data_out.wrench.force.x = msg_filtered[0];
192-
data_out.wrench.force.y = msg_filtered[1];
193-
data_out.wrench.force.z = msg_filtered[2];
194-
data_out.wrench.torque.x = msg_filtered[3];
195-
data_out.wrench.torque.y = msg_filtered[4];
196-
data_out.wrench.torque.z = msg_filtered[5];
198+
filtered_old_value_[0] = data_in.wrench.force.x;
199+
filtered_old_value_[1] = data_in.wrench.force.y;
200+
filtered_old_value_[2] = data_in.wrench.force.z;
201+
filtered_old_value_[3] = data_in.wrench.torque.x;
202+
filtered_old_value_[4] = data_in.wrench.torque.y;
203+
filtered_old_value_[5] = data_in.wrench.torque.z;
204+
205+
data_out.wrench.force.x = filtered_value_[0];
206+
data_out.wrench.force.y = filtered_value_[1];
207+
data_out.wrench.force.z = filtered_value_[2];
208+
data_out.wrench.torque.x = filtered_value_[3];
209+
data_out.wrench.torque.y = filtered_value_[4];
210+
data_out.wrench.torque.z = filtered_value_[5];
197211

198212
// copy the header
199213
data_out.header = data_in.header;
@@ -211,28 +225,28 @@ inline bool LowPassFilter<std::vector<double>>::update(
211225
// If this is the first call to update initialize the filter at the current state
212226
// so that we dont apply an impulse to the data.
213227
// This also sets the size of the member variables to match the input data.
214-
if (filtered_value.empty())
228+
if (filtered_value_.empty())
215229
{
216-
filtered_value = data_in;
217-
filtered_old_value = data_in;
218-
old_value = data_in;
230+
filtered_value_ = data_in;
231+
filtered_old_value_ = data_in;
232+
old_value_ = data_in;
219233
}
220234
else
221235
{
222236
assert(
223-
data_in.size() == filtered_value.size() &&
237+
data_in.size() == filtered_value_.size() &&
224238
"Internal data and the data_in doesn't hold the same size");
225239
assert(data_out.size() == data_in.size() && "data_in and data_out doesn't hold same size");
226240
}
227241

228242
// Filter each value in the vector
229243
for (std::size_t i = 0; i < data_in.size(); i++)
230244
{
231-
data_out[i] = b1_ * old_value[i] + a1_ * filtered_old_value[i];
232-
filtered_old_value[i] = data_out[i];
245+
data_out[i] = b1_ * old_value_[i] + a1_ * filtered_old_value_[i];
246+
filtered_old_value_[i] = data_out[i];
233247
if (std::isfinite(data_in[i]))
234248
{
235-
old_value[i] = data_in[i];
249+
old_value_[i] = data_in[i];
236250
}
237251
}
238252

@@ -248,24 +262,24 @@ bool LowPassFilter<T>::update(const T & data_in, T & data_out)
248262
}
249263
// If this is the first call to update initialize the filter at the current state
250264
// so that we dont apply an impulse to the data.
251-
if (std::isnan(filtered_value))
265+
if (std::isnan(filtered_value_))
252266
{
253-
filtered_value = data_in;
254-
filtered_old_value = data_in;
255-
old_value = data_in;
267+
filtered_value_ = data_in;
268+
filtered_old_value_ = data_in;
269+
old_value_ = data_in;
256270
}
257271

258272
// Filter
259-
data_out = b1_ * old_value + a1_ * filtered_old_value;
260-
filtered_old_value = data_out;
273+
data_out = b1_ * old_value_ + a1_ * filtered_old_value_;
274+
filtered_old_value_ = data_out;
261275
if (std::isfinite(data_in))
262276
{
263-
old_value = data_in;
277+
old_value_ = data_in;
264278
}
265279

266280
return true;
267281
}
268282

269283
} // namespace control_toolbox
270284

271-
#endif // CONTROL_TOOLBOX__LOW_PASS_FILTER_HPP_
285+
#endif // CONTROL_TOOLBOX__LOW_PASS_FILTER_HPP_

0 commit comments

Comments
 (0)