22
22
#include < memory>
23
23
#include < stdexcept>
24
24
#include < string>
25
+ #include < type_traits>
25
26
#include < vector>
26
27
27
28
#include " geometry_msgs/msg/wrench_stamped.hpp"
@@ -123,10 +124,17 @@ class LowPassFilter
123
124
// Filter parameters
124
125
double a1_; /* * feedbackward coefficient. */
125
126
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
+
130
138
bool configured_ = false ;
131
139
};
132
140
@@ -143,12 +151,18 @@ LowPassFilter<T>::~LowPassFilter()
143
151
template <typename T>
144
152
bool LowPassFilter<T>::configure()
145
153
{
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
150
164
{
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 ();
152
166
}
153
167
154
168
return configured_ = true ;
@@ -164,36 +178,36 @@ inline bool LowPassFilter<geometry_msgs::msg::WrenchStamped>::update(
164
178
}
165
179
// If this is the first call to update initialize the filter at the current state
166
180
// so that we dont apply an impulse to the data.
167
- if (msg_filtered .hasNaN ())
181
+ if (filtered_value_ .hasNaN ())
168
182
{
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_ ;
177
191
}
178
192
179
193
// 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_ ;
182
196
183
197
// 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 ];
197
211
198
212
// copy the header
199
213
data_out.header = data_in.header ;
@@ -211,28 +225,28 @@ inline bool LowPassFilter<std::vector<double>>::update(
211
225
// If this is the first call to update initialize the filter at the current state
212
226
// so that we dont apply an impulse to the data.
213
227
// This also sets the size of the member variables to match the input data.
214
- if (filtered_value .empty ())
228
+ if (filtered_value_ .empty ())
215
229
{
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;
219
233
}
220
234
else
221
235
{
222
236
assert (
223
- data_in.size () == filtered_value .size () &&
237
+ data_in.size () == filtered_value_ .size () &&
224
238
" Internal data and the data_in doesn't hold the same size" );
225
239
assert (data_out.size () == data_in.size () && " data_in and data_out doesn't hold same size" );
226
240
}
227
241
228
242
// Filter each value in the vector
229
243
for (std::size_t i = 0 ; i < data_in.size (); i++)
230
244
{
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];
233
247
if (std::isfinite (data_in[i]))
234
248
{
235
- old_value [i] = data_in[i];
249
+ old_value_ [i] = data_in[i];
236
250
}
237
251
}
238
252
@@ -248,24 +262,24 @@ bool LowPassFilter<T>::update(const T & data_in, T & data_out)
248
262
}
249
263
// If this is the first call to update initialize the filter at the current state
250
264
// so that we dont apply an impulse to the data.
251
- if (std::isnan (filtered_value ))
265
+ if (std::isnan (filtered_value_ ))
252
266
{
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;
256
270
}
257
271
258
272
// 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;
261
275
if (std::isfinite (data_in))
262
276
{
263
- old_value = data_in;
277
+ old_value_ = data_in;
264
278
}
265
279
266
280
return true ;
267
281
}
268
282
269
283
} // namespace control_toolbox
270
284
271
- #endif // CONTROL_TOOLBOX__LOW_PASS_FILTER_HPP_
285
+ #endif // CONTROL_TOOLBOX__LOW_PASS_FILTER_HPP_
0 commit comments