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

fuse -> ROS 2 fuse_core : Parameters and Tests #286

Merged
merged 13 commits into from
Nov 30, 2022

Conversation

methylDragon
Copy link
Collaborator

@methylDragon methylDragon commented Nov 17, 2022

See: #276

Description

With this PR, tests now run (and pass) on fuse_core! (Sans linting)

This PR incorporates all remaining changes @BrettRD made to fuse_core, and then applies patches on top of them to fix parameters and the tests.

Additionally, it brings in changes from #273 to allow for Ceres support in the tests. (That PR's been merged but not on the rolling branch. I've cherry-picked the changes.)

Also, this PR adds the NodeInterfaces class proposed in ros2/rclcpp#2041 to fuse_core, to port passing of ROS node handles around.

Notes

  • The launch testing is a little hacky (I have to assert stdout for a gtest).
  • I had to change the behavior of two tests due to changes in how ROS 2 handles parameters (strongly typed), I think what I did made sense, but I'd like a confirmation

Pinging @svwilliams for visibility.

sloretz and others added 10 commits November 14, 2022 14:50
Signed-off-by: Shane Loretz <sloretz@osrfoundation.org>
Signed-off-by: methylDragon <methylDragon@gmail.com>
Signed-off-by: methylDragon <methylDragon@gmail.com>
Authored-by: Brett Downing

- moves publishers mostly to ros2 APIs
- adds convenience functions
- start building publishers and models
- builds and links as shared libraries
- uses ros2 services for optimizer reset
- removes redundant diagnostic updater timer
- adds ParameterDescriptors to load parameter descriptions
- adds a rough compatibility patch for ros1 style parameters
- loads sensor models and publishers with ros2
- loads motion_models from ros2 params
- add descriptions to CLI parameter tools
- makes config files slightly closer to ROS1 layout
- fixes type errors
- cleanup, deprecate XmlRpc API for parameters
- uses Node directly in parameter helpers to simplify the port
- add missing dependency
- Adding Ceres options 
- Adding more classes to the CMakeLists
- converts stored parameters to double, allowing dynamic reconf
- uses rclcpp::ok
- binds timer callbacks
- tweaks order of arguments
- fix params and chrono, build fuse_graphs
- change params, fix chrono, build fuse_graphs
Signed-off-by: methylDragon <methylDragon@gmail.com>
Authored-by: Brett Downing

- moves publishers mostly to ros2 APIs
- adds convenience functions
- start building publishers and models
- builds and links as shared libraries
- uses ros2 services for optimizer reset
- removes redundant diagnostic updater timer
- adds ParameterDescriptors to load parameter descriptions
- adds a rough compatibility patch for ros1 style parameters
- loads sensor models and publishers with ros2
- loads motion_models from ros2 params
- add descriptions to CLI parameter tools
- makes config files slightly closer to ROS1 layout
- fixes type errors
- cleanup, deprecate XmlRpc API for parameters
- uses Node directly in parameter helpers to simplify the port
- add missing dependency
- Adding Ceres options 
- Adding more classes to the CMakeLists
- converts stored parameters to double, allowing dynamic reconf
- uses rclcpp::ok
- binds timer callbacks
- tweaks order of arguments
- fix params and chrono, build fuse_graphs
- change params, fix chrono, build fuse_graphs
Signed-off-by: methylDragon <methylDragon@gmail.com>
Signed-off-by: methylDragon <methylDragon@gmail.com>
Ceres added this argument in ceres-solver/ceres-solver@e7a3035 we need to pass it else template substitution fails.
Upstream commit made me assume kGlobalSize, but that threw at runtime when the tests ran.
This seems to work, also put a using statement there to make roslint happy.
Signed-off-by: methylDragon <methylDragon@gmail.com>
Signed-off-by: methylDragon <methylDragon@gmail.com>
Copy link
Collaborator

@sloretz sloretz left a comment

Choose a reason for hiding this comment

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

Quick feedback - will come back to review parameters use and tests

fuse_core/CMakeLists.txt Outdated Show resolved Hide resolved
fuse_core/include/fuse_core/throttled_callback.h Outdated Show resolved Hide resolved
fuse_core/include/fuse_core/throttled_callback.h Outdated Show resolved Hide resolved
fuse_core/src/async_motion_model.cpp Outdated Show resolved Hide resolved
@methylDragon methylDragon force-pushed the rolling-params branch 2 times, most recently from 51dbb91 to 329a3dc Compare November 18, 2022 23:14
@methylDragon
Copy link
Collaborator Author

methylDragon commented Nov 18, 2022

Wait a sec.. that caused a test regression :X

Edit: Fixed https://github.com/locusrobotics/fuse/compare/329a3dc486673b87ced0c3576a4d61894bf8798e..67c6fd9a7f97eb49dc851a119ea0940d2c7706ff

With these changes merged into the downstream PRs, no non-lint tests are broken.

Signed-off-by: methylDragon <methylDragon@gmail.com>
Copy link
Collaborator

@sloretz sloretz left a comment

Choose a reason for hiding this comment

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

A bunch of small comments! I still have 6 more files to review.

fuse_core/include/fuse_core/async_publisher.h Outdated Show resolved Hide resolved
rclcpp::Time wait_time_elapsed = rclcpp::Clock(RCL_SYSTEM_TIME).now() + rclcpp::Duration::from_seconds(10.0);
while (!publisher.callback_processed && rclcpp::Clock(RCL_SYSTEM_TIME).now() < wait_time_elapsed)
rclcpp::Time wait_time_elapsed =
rclcpp::Clock(RCL_SYSTEM_TIME).now() + rclcpp::Duration::from_seconds(10.0);
Copy link
Collaborator

Choose a reason for hiding this comment

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

nit, I'd recommend constructing the clock once and then using it.

{
rclcpp::sleep_for(rclcpp::Duration::from_seconds(0.1));
rclcpp::sleep_for(std::chrono::milliseconds(100));
}
EXPECT_TRUE(publisher.callback_processed);
}

int main(int argc, char** argv)
Copy link
Collaborator

Choose a reason for hiding this comment

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

Nit, i think the whole int main() function can be deleted since ament_add_gtest links to gtest_main.

@@ -121,12 +136,5 @@ TEST(AsyncSensorModel, SendTransaction)
int main(int argc, char** argv)
Copy link
Collaborator

Choose a reason for hiding this comment

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

nit, same comment about int main() can be deleted.

@@ -120,12 +135,5 @@ TEST(AsyncMotionModel, ApplyCallback)
int main(int argc, char** argv)
Copy link
Collaborator

Choose a reason for hiding this comment

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

nit same comment about int main()

fuse_core/test/launch_tests/test_parameters.cpp Outdated Show resolved Hide resolved
fuse_core/test/launch_tests/test_parameters.cpp Outdated Show resolved Hide resolved
fuse_core/test/launch_tests/test_parameters.cpp Outdated Show resolved Hide resolved
fuse_core/test/CMakeLists.txt Outdated Show resolved Hide resolved
fuse_core/test/CMakeLists.txt Outdated Show resolved Hide resolved
std::string default_value = "";
value = getParam(interfaces, key, default_value);

if (value == default_value)
Copy link
Collaborator

Choose a reason for hiding this comment

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

What if the value was explicitly set to empty string?

This might have to use one of the decalare_parameter() overrides that doesn't accept a default value. It looks like the second getParam() above already implements that.

Copy link
Collaborator Author

@methylDragon methylDragon Nov 29, 2022

Choose a reason for hiding this comment

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

Actually all of the declare_parameter signatures require a default value... The one with value.get_type() just uses the default constructed value of that type (which is an empty string)... I'm not sure how you'd distinguish between the two in this case :/

You have to declare a param before you can query it, and declaring it requires the input of a default value.

{
rcl_interfaces::msg::ParameterDescriptor tmp_descr;

std::string namespace_;
Copy link
Collaborator

Choose a reason for hiding this comment

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

nit, namespace_ with a trailing underscore means "member variable" (in ROS 2 style via Google Style guide).

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Ah, I was trying to get around the keyword namespace, I'll rename it to ns instead then.

} else {
namespace_ = namespace_string + ".";
}

#if CERES_VERSION_AT_LEAST(1, 13, 0)
Copy link
Collaborator

Choose a reason for hiding this comment

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

libceres-dev is version 1.13.0 in Bionic - since we're targeting Rolling I think it's safe to remove this check.

fuse_core/src/ceres_options.cpp Outdated Show resolved Hide resolved
namespace_ + "enable_fast_removal", problem_options.enable_fast_removal, tmp_descr
);

tmp_descr.description = "If true, trades memory for faster Problem::RemoveResidualBlock()";
Copy link
Collaborator

Choose a reason for hiding this comment

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

It looks like this description was copied from the above, and it seems different from upstream's description:

https://github.com/ceres-solver/ceres-solver/blob/352b320ab1b5438a0838aea09cbbf07fa4ff5d71/include/ceres/problem.h#L149-L158

fuse_core/src/ceres_options.cpp Outdated Show resolved Hide resolved
fuse_core/src/ceres_options.cpp Outdated Show resolved Hide resolved
@methylDragon methylDragon force-pushed the rolling-params branch 4 times, most recently from dc149ff to d126a1e Compare November 30, 2022 02:25
Copy link
Collaborator

@sloretz sloretz left a comment

Choose a reason for hiding this comment

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

Most of the way through re-reviewing, only one comment so far!

fuse_core/test/test_throttled_callback.cpp Outdated Show resolved Hide resolved
Copy link
Collaborator

@sloretz sloretz left a comment

Choose a reason for hiding this comment

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

Last two comments!

@pytest.fixture
def test_proc():
test_root = os.path.join(
get_package_prefix('fuse_core'), '..', '..', 'build', 'fuse_core', 'test'
Copy link
Collaborator

Choose a reason for hiding this comment

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

It looks like this assumes the test is being run after being built with colcon, with the default name for the build directory. It also assumes the software has been installed. I would recommend not using get_package_prefix() at all. There are at least a couple good alternatives.

One alternative would be to set the WORKING_DIRECTORY argument to ament_add_pytest_test to ${CMAKE_CURRENT_SOURCE_DIR} and use a relative path.

Another alternative would be to use the ENV arugment to pass in the path to the parameters file as an environment variable and use that as the path here.

def test_no_failed_gtests(test_proc, launch_context):
def validate_output(output):
assert '[ PASSED ] 2 tests.' in output.splitlines(), (
'process never printed required passes')
Copy link
Collaborator

Choose a reason for hiding this comment

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

It looks like the test is returning RUN_ALL_TESTS();. I'd bet the exit code would be non-zero on failure, and so that could be the check here.

Copy link
Collaborator

@sloretz sloretz left a comment

Choose a reason for hiding this comment

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

The substance looks good to me, just nits about unused imports

fuse_core/test/launch_tests/test_parameters.py Outdated Show resolved Hide resolved
fuse_core/test/launch_tests/test_parameters.py Outdated Show resolved Hide resolved
fuse_core/test/launch_tests/test_parameters.py Outdated Show resolved Hide resolved
fuse_core/test/launch_tests/test_parameters.py Outdated Show resolved Hide resolved
fuse_core/test/launch_tests/test_parameters.py Outdated Show resolved Hide resolved
fuse_core/test/launch_tests/test_parameters.py Outdated Show resolved Hide resolved
Copy link
Collaborator

@sloretz sloretz left a comment

Choose a reason for hiding this comment

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

One last important change - the package.xml needs a <test_depend>launch_pytest</test_depend>

Signed-off-by: methylDragon <methylDragon@gmail.com>
Copy link
Collaborator

@sloretz sloretz left a comment

Choose a reason for hiding this comment

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

LGTM!

All tests pass except cpplint, uncrustify, and xmllint. Approving since linting is to be fixed in the next PR.

@methylDragon methylDragon merged commit df291bd into locusrobotics:rolling Nov 30, 2022
@methylDragon methylDragon deleted the rolling-params branch November 30, 2022 21:06
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants