Skip to content

Add lowpass filter #152

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

Merged

Conversation

guihomework
Copy link
Contributor

This is a rework of PR #115 for the low-pass filter part, now using generate_parameter_library.

dzumkeller and others added 12 commits March 7, 2023 15:29
- added testcases for loading parameters
removed parameter_namespace and added override flag
# Conflicts:
#	include/control_filters/gravity_compensation.hpp
#	src/control_filters/gravity_compensation.cpp
fixed gravity compensation calculated values
fixed guard condition issues (rclcpp init must be called before)
fixed configure issues (low-level must be configured to avoid undefined logger)

# Conflicts:
#	CMakeLists.txt
#	test/control_filters/test_gravity_compensation.cpp
#	test/control_filters/test_gravity_compensation.hpp
@guihomework
Copy link
Contributor Author

xmlcheck complained about angle brackets, to type of class to instantiate.
since there is no cli for pluginlib in ros2 yet, to quickly test if the <> would be usable in the command line, a pluginlib instantiation should be tested within the tests

@guihomework
Copy link
Contributor Author

Test passes with the escaped angle brackets.

@destogl
Copy link
Member

destogl commented Mar 11, 2023

@bmagyar can we branch-out here for humble and rolling?, i.e., we need one foxy branch that holds current code for foxy and galactic.

@destogl destogl marked this pull request as ready for review March 11, 2023 12:17
Copy link
Member

@destogl destogl left a comment

Choose a reason for hiding this comment

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

1st part...

CMakeLists.txt Outdated
Comment on lines 67 to 78

target_include_directories(low_pass_filter PUBLIC
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
$<BUILD_INTERFACE:${EIGEN3_INCLUDE_DIR}>
$<INSTALL_INTERFACE:include>
)
generate_parameter_library(
low_pass_filter_parameters
src/control_filters/low_pass_filter_parameters.yaml
)
target_link_libraries(low_pass_filter low_pass_filter_parameters)
ament_target_dependencies(low_pass_filter ${CONTROL_FILTERS_INCLUDE_DEPENDS})
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
target_include_directories(low_pass_filter PUBLIC
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
$<BUILD_INTERFACE:${EIGEN3_INCLUDE_DIR}>
$<INSTALL_INTERFACE:include>
)
generate_parameter_library(
low_pass_filter_parameters
src/control_filters/low_pass_filter_parameters.yaml
)
target_link_libraries(low_pass_filter low_pass_filter_parameters)
ament_target_dependencies(low_pass_filter ${CONTROL_FILTERS_INCLUDE_DEPENDS})
target_compile_features(low_pass_filter PUBLIC cxx_std_17)
target_include_directories(low_pass_filter PUBLIC
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
$<BUILD_INTERFACE:${EIGEN3_INCLUDE_DIR}>
$<INSTALL_INTERFACE:include/control_filters>
)
target_link_libraries(low_pass_filter PUBLIC low_pass_filter_parameters)
ament_target_dependencies(low_pass_filter ${CONTROL_FILTERS_INCLUDE_DEPENDS})

Copy link
Member

Choose a reason for hiding this comment

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

This line $<INSTALL_INTERFACE:include/control_filters> maybe have to be $<INSTALL_INTERFACE:include/control_toolbox> - please test which version is working.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

i am actually surprised one needs to install the includes in a different folder than the project name or our own name (control_filters).
The code before my PR #152 (which is only 3 weeks old from #145 ) already installs in a control_toolbox sub-folder of the project name, making it look like
my_ws/install/control_toolbox/include/control_toolbox/control_toolbox
my_ws/install/control_toolbox/include/control_toolbox/control_filters
is that really what we want ? I have difficulties understanding the "override" thing, so maybe there is a good reason, otherwise I would expect:
my_ws/install/control_toolbox/include/control_toolbox
and for the control filters
my_ws/install/control_toolbox/include/control_filters

it is possible this got un-noticed, because with underlays still having the control_toolbox includes looking as I would expect it, this simply worked (the underlay libs were found ?) until this new change gets released ?

Copy link
Member

Choose a reason for hiding this comment

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

I understand this is confusing. It is also for all of us, but this is how ament und colcon work...

you can read here more details and check references why we have to do that: ros-controls/ros2_control#926

Copy link
Member

Choose a reason for hiding this comment

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

it is possible this got un-noticed, because with underlays still having the control_toolbox includes looking as I would expect it, this simply worked (the underlay libs were found ?) until this new change gets released ?

You are adding here new libs, and they work without problem. The issue comes when you have a lib, install in the system and want to override it as in ROS 1 – this doesn't work without these tricks. After loosing already a dozen of hours debugging non-existing issues, we decided to take this ugly implementation and just make things to be easily used.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

OK, maybe #145 should have at least pointed to the doc justifying that, then I would not have asked.

This is not nice but very important and something others will stumble upon. I had seen the override warnings in colcon build but I did not relate the "ordering" to the strange naming.

I see that ROS 1 solved that known issue of overlays by having re-ordering of the includes done in the cmake when catkin was called.

I hope this gets solved one day.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This line $<INSTALL_INTERFACE:include/control_filters> maybe have to be $<INSTALL_INTERFACE:include/control_toolbox> - please test which version is working.

since the destination of the source includes installation is this name-trick to permit override, the install interface of the filters has to be in the same folder as this name-trick.
if one wants to have a different name-trick applied to the control_filters so that it goes in control_filters/control_filters
the install cmake command must be modified to do 2 sub-folder installs for control_toolbox and control_filters separately.

depends what you prefer:

include/control_toolbox/control_toolbox
include/control_toolbox/control_filters
or
include/control_toolbox/control_toolbox
include/control_filters/control_filters

Copy link
Contributor Author

Choose a reason for hiding this comment

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

For my understanding :
Could you confirm there is no override issue with the generated libraries headers (in case a this generate library yaml gets changed in an overlay), although they get installed in include/low_pass_filter_parameters/ and not in include/low_pass_filter_parameters/low_pass_filter_parameters because the target_link_library sees it is a local target and finds the local header ?

Copy link
Member

Choose a reason for hiding this comment

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

We didn't test this yet with generated parameters.

README.md Outdated
Comment on lines 48 to 50
- `clang-format-10`
```
sudo apt install clang-format-10
Copy link
Member

Choose a reason for hiding this comment

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

We use clang-format-14

Suggested change
- `clang-format-10`
```
sudo apt install clang-format-10
- `clang-format-14`
```
sudo apt install clang-format-14

See here: https://github.com/ros-controls/control_toolbox/blob/ros2-master/.github/workflows/ci-format.yml

Copy link
Member

Choose a reason for hiding this comment

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

Please let the reviewer close/mark the comments as resolved. You can just give a short remark like "done" or thumbs up emoji if you just agree. Sometimes is confusing when something is marked as done, but actually one doesn't sees it in the changes.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Oh ok, this is how it works. I did not use it this way in the past.

@guihomework guihomework force-pushed the add-lowpass-filter-rolling branch from ee9115c to b98f199 Compare March 13, 2023 19:28
Copy link
Member

@destogl destogl left a comment

Choose a reason for hiding this comment

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

Except the small issues, I am happy with this.

README.md Outdated
@@ -27,3 +27,25 @@ doi = {10.21105/joss.00456},
URL = {http://www.theoj.org/joss-papers/joss.00456/10.21105.joss.00456.pdf}
}
```


## Code Formatting
Copy link
Member

Choose a reason for hiding this comment

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

We should add this in the separate PR. It's not part of the functionality presented here

low_pass_filter::Params parameters_;

// Filter parameters
// TODO(destogl): we should do this more intelligently using only one set of types
Copy link
Member

Choose a reason for hiding this comment

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

Not necessary since we didn't come up with any better solution.

Suggested change
// TODO(destogl): we should do this more intelligently using only one set of types

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This was not worked on yet. I had a quick look, maybe something along using std::enable_if to detect if a type can be directly filtered with the y(n)= b * x(n-1) + a * y(n-1) example double, ints Eigen<N,1>, etc..) or if a specialization has been provided for converting the T type to a processable storage...
https://medium.com/@sidbhasin82/c-templates-what-is-std-enable-if-and-how-to-use-it-fd76d3abbabe

Comment on lines 24 to 34
#divider:
#{
# type: int,
# # default_value: 3,
# description: "Divider",
# validation:
# {
# gt_eq<>: [0]
# },
# read_only: true
#}
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
#divider:
#{
# type: int,
# # default_value: 3,
# description: "Divider",
# validation:
# {
# gt_eq<>: [0]
# },
# read_only: true
#}

destogl
destogl previously approved these changes Mar 27, 2023
Copy link
Member

@destogl destogl left a comment

Choose a reason for hiding this comment

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

This looks great! Thanks. Just a few more cleanings. One test is duplicate since using generate_paramter_library and since it it done in a test later.

low_pass_filter:
sampling_frequency: {
type: double,
# default_value: 1000.0,
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
# default_value: 1000.0,

}
damping_frequency: {
type: double,
# default_value: 20.5,
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
# default_value: 20.5,

}
damping_intensity: {
type: double,
# default_value: 1.25,
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
# default_value: 1.25,

Copy link
Contributor Author

Choose a reason for hiding this comment

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

done all of these 3 default removal

Comment on lines +34 to +42
TEST_F(LowPassFilterTest, TestLowPassWrenchFilterMissingParameter)
{
std::shared_ptr<filters::FilterBase<geometry_msgs::msg::WrenchStamped>> filter_ =
std::make_shared<control_filters::LowPassFilter<geometry_msgs::msg::WrenchStamped>>();

// should deny configuration as sampling frequency is missing
ASSERT_FALSE(filter_->configure("", "TestLowPassFilter",
node_->get_node_logging_interface(), node_->get_node_parameters_interface()));
}
Copy link
Member

Choose a reason for hiding this comment

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

not needed when using generate_parameter_library

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I don't see why one should not test for filter configure failing "properly". This test permits to verify that the parameters were correctly defined in the generate_parameter_library YAML as "should fail if missing", and that the throw is caught correctly isn't it ?

Comment on lines +7 to +11
TestLowPassWrenchFilterMissingParameter:
ros__parameters:
damping_frequency: 20.5
damping_intensity: 1.25

Copy link
Member

Choose a reason for hiding this comment

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

Not needed since using generate_parameter library.

Copy link
Contributor

@christophfroehlich christophfroehlich left a comment

Choose a reason for hiding this comment

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

If I were allowed to wish something: a short README would help guiding new users, as well as adding some function API documentation inside the header (like in all other functions of this repository).

@guihomework
Copy link
Contributor Author

If I were allowed to wish something: a short README would help guiding new users

Do you mean a doc similar to the one in the Gravity Compensation "filter" https://github.com/ros-controls/control_toolbox/blob/f181fe76279860ff9b1c9f3d9edde927da29703b/src/control_filters/README.md
or more a general description of the role of control filters and why they are there and how to use them ?

@christophfroehlich
Copy link
Contributor

If I were allowed to wish something: a short README would help guiding new users

Do you mean a doc similar to the one in the Gravity Compensation "filter" https://github.com/ros-controls/control_toolbox/blob/f181fe76279860ff9b1c9f3d9edde927da29703b/src/control_filters/README.md or more a general description of the role of control filters and why they are there and how to use them ?

I mean a doc similar to the Gravity filter -> it will be short for this one. A general readme for this repo is out of scope for this PR IMHO.

@guihomework
Copy link
Contributor Author

@christophfroehlich Thanks for the clarification. Another question: I am new to PR that require rebasing+changes, when the reviewer does merges of master in the PR. What should I do on my side ? rebase my initial branch (before your merge from master) on top of maaster, commit the requested changes and push or now add the requested changes over your merged-commit. I am used to always keep history of branches clean and straight.

@christophfroehlich
Copy link
Contributor

I also prefer having a clean history, but in the end everything gets squashed in a single commit on master -> I'd suggest that you just commit on top of the last merge-commit.

@guihomework
Copy link
Contributor Author

This makes sense. When I kept branches clean, it was to keep all commits in the master as well.

@guihomework
Copy link
Contributor Author

If I were allowed to wish something: a short README would help guiding new users, as well as adding some function API documentation inside the header (like in all other functions of this repository).

both done now.

Copy link
Contributor

@christophfroehlich christophfroehlich left a comment

Choose a reason for hiding this comment

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

Great, thx!

@destogl destogl merged commit 00eb150 into ros-controls:ros2-master Aug 8, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants