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

Add standalone version of LPF #222

Open
wants to merge 10 commits into
base: ros2-master
Choose a base branch
from
107 changes: 23 additions & 84 deletions include/control_filters/low_pass_filter.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,12 @@
#include <string>
#include <vector>

#include "low_pass_filter_parameters.hpp"
#include "filters/filter_base.hpp"

#include "geometry_msgs/msg/wrench_stamped.hpp"

#include "control_toolbox/low_pass_filter.hpp"
#include "low_pass_filter_parameters.hpp"

namespace control_filters
{

Expand Down Expand Up @@ -79,14 +80,6 @@ template <typename T>
class LowPassFilter : public filters::FilterBase<T>
{
public:
// Default constructor
LowPassFilter();

/*!
* \brief Destructor of LowPassFilter class.
*/
~LowPassFilter() override;

/*!
* \brief Configure the LowPassFilter (access and process params).
*/
Expand All @@ -102,44 +95,14 @@ class LowPassFilter : public filters::FilterBase<T>
*/
bool update(const T & data_in, T & data_out) override;

protected:
/*!
* \brief Internal computation of the feedforward and feedbackward coefficients
* according to the LowPassFilter parameters.
*/
void compute_internal_params()
{
a1_ = exp(
-1.0 / parameters_.sampling_frequency * (2.0 * M_PI * parameters_.damping_frequency) /
(pow(10.0, parameters_.damping_intensity / -10.0)));
b1_ = 1.0 - a1_;
};

private:
rclcpp::Clock::SharedPtr clock_;
std::shared_ptr<rclcpp::Logger> logger_;
std::shared_ptr<low_pass_filter::ParamListener> parameter_handler_;
low_pass_filter::Params parameters_;

// Filter parameters
/** internal data storage (double). */
double filtered_value, filtered_old_value, old_value;
/** internal data storage (wrench). */
Eigen::Matrix<double, 6, 1> msg_filtered, msg_filtered_old, msg_old;
double a1_; /**< feedbackward coefficient. */
double b1_; /**< feedforward coefficient. */
std::shared_ptr<control_toolbox::LowPassFilter<T>> lpf_;
};

template <typename T>
LowPassFilter<T>::LowPassFilter() : a1_(1.0), b1_(0.0)
{
}

template <typename T>
LowPassFilter<T>::~LowPassFilter()
{
}

template <typename T>
bool LowPassFilter<T>::configure()
{
Expand Down Expand Up @@ -168,24 +131,19 @@ bool LowPassFilter<T>::configure()
}
}
parameters_ = parameter_handler_->get_params();
compute_internal_params();
lpf_ = std::make_shared<control_toolbox::LowPassFilter<T>>(
parameters_.sampling_frequency,
parameters_.damping_frequency,
parameters_.damping_intensity);

// Initialize storage Vectors
filtered_value = filtered_old_value = old_value = 0;
// TODO(destogl): make the size parameterizable and more intelligent is using complex types
for (size_t i = 0; i < 6; ++i)
{
msg_filtered[i] = msg_filtered_old[i] = msg_old[i] = 0;
}

return true;
return lpf_->configure();
}

template <>
inline bool LowPassFilter<geometry_msgs::msg::WrenchStamped>::update(
const geometry_msgs::msg::WrenchStamped & data_in, geometry_msgs::msg::WrenchStamped & data_out)
{
if (!this->configured_)
if (!this->configured_ || !lpf_ || !lpf_->is_configured())
{
if (logger_)
RCLCPP_ERROR_SKIPFIRST_THROTTLE((*logger_), *clock_, 2000, "Filter is not configured");
Comment on lines +146 to 149
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If the filter is not configured, i think it's better to throw an exception rather than continuing right?

Expand All @@ -196,55 +154,36 @@ inline bool LowPassFilter<geometry_msgs::msg::WrenchStamped>::update(
if (parameter_handler_->is_old(parameters_))
{
parameters_ = parameter_handler_->get_params();
compute_internal_params();
lpf_->set_params(
parameters_.sampling_frequency,
parameters_.damping_frequency,
parameters_.damping_intensity);
}

// IIR Filter
msg_filtered = b1_ * msg_old + a1_ * msg_filtered_old;
msg_filtered_old = msg_filtered;

// TODO(destogl): use wrenchMsgToEigen
msg_old[0] = data_in.wrench.force.x;
msg_old[1] = data_in.wrench.force.y;
msg_old[2] = data_in.wrench.force.z;
msg_old[3] = data_in.wrench.torque.x;
msg_old[4] = data_in.wrench.torque.y;
msg_old[5] = data_in.wrench.torque.z;

data_out.wrench.force.x = msg_filtered[0];
data_out.wrench.force.y = msg_filtered[1];
data_out.wrench.force.z = msg_filtered[2];
data_out.wrench.torque.x = msg_filtered[3];
data_out.wrench.torque.y = msg_filtered[4];
data_out.wrench.torque.z = msg_filtered[5];

// copy the header
data_out.header = data_in.header;
Comment on lines -203 to -222
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

May be the update method specific to geometry_msgs Wrench should be removed?. It kinda has same content of templated one right?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the math is the same, but here it uses the Eigen matrices to do the linear combination. this can't work with the templated method alone?

return true;
return lpf_->update(data_in, data_out);
}

template <typename T>
bool LowPassFilter<T>::update(const T & data_in, T & data_out)
{
if (!this->configured_)
if (!this->configured_ || !lpf_ || !lpf_->is_configured())
{
RCLCPP_ERROR_SKIPFIRST_THROTTLE((*logger_), *clock_, 2000, "Filter is not configured");
if (logger_)
RCLCPP_ERROR_SKIPFIRST_THROTTLE((*logger_), *clock_, 2000, "Filter is not configured");
return false;
}

// Update internal parameters if required
if (parameter_handler_->is_old(parameters_))
{
parameters_ = parameter_handler_->get_params();
compute_internal_params();
lpf_->set_params(
parameters_.sampling_frequency,
parameters_.damping_frequency,
parameters_.damping_intensity);
}

// Filter
data_out = b1_ * old_value + a1_ * filtered_old_value;
filtered_old_value = data_out;
old_value = data_in;

return true;
return lpf_->update(data_in, data_out);
}

} // namespace control_filters
Expand Down
Loading
Loading