Open
Conversation
Signed-off-by: Francisco Martín Rico <fmrico@gmail.com>
Signed-off-by: Francisco Martín Rico <fmrico@gmail.com>
…easynav features. Initial pose now changes initial utm pose to change robot position in the map
There was a problem hiding this comment.
Pull request overview
This PR aims to standardize how EasyNav localizer plugins consume the RViz-style initial pose topic and adds/updates functional GTests to validate parameter-seeded initialization plus runtime updates via /initialpose.
Changes:
- Added
/initialposesubscriptions and callbacks to multiple localizers (AMCL variants, GPS, Fusion) and documented the interface. - Reworked/added functional tests to validate deterministic seeding and runtime pose resets.
- Updated Fusion’s UKF set-pose path to deterministically update filter state.
Reviewed changes
Copilot reviewed 29 out of 29 changed files in this pull request and generated 8 comments.
Show a summary per file
| File | Description |
|---|---|
| maps_managers/easynav_simple_maps_manager/src/easynav_simple_maps_manager/SimpleMapsManager.cpp | Removes leftover debug prints. |
| localizers/easynav_simple_localizer/tests/simple_localizer_tests.cpp | Replaces prior tests with functional /initialpose-driven initialization/reset test. |
| localizers/easynav_simple_localizer/src/easynav_simple_localizer/AMCLLocalizer.cpp | Adds /initialpose subscription + callback that reinitializes particles from pose/covariance. |
| localizers/easynav_simple_localizer/include/easynav_simple_localizer/AMCLLocalizer.hpp | Declares initial pose subscription + callback. |
| localizers/easynav_simple_localizer/README.md | Documents initial pose subscription interface. |
| localizers/easynav_simple_localizer/CMakeLists.txt | Enables building tests subdirectory. |
| localizers/easynav_navmap_localizer/tests/navmap_localizer_tests.cpp | Adds functional /initialpose initialization/reset test. |
| localizers/easynav_navmap_localizer/tests/costmap_localizer_tests.cpp | Removes older navmap tests (dynamic update/map/service). |
| localizers/easynav_navmap_localizer/tests/CMakeLists.txt | Switches test target to new navmap localizer test. |
| localizers/easynav_navmap_localizer/src/easynav_navmap_localizer/AMCLLocalizer.cpp | Adds /initialpose subscription + callback mirroring simple AMCL behavior. |
| localizers/easynav_navmap_localizer/include/easynav_navmap_localizer/AMCLLocalizer.hpp | Declares initial pose subscription + callback. |
| localizers/easynav_navmap_localizer/README.md | Documents initial pose subscription interface. |
| localizers/easynav_navmap_localizer/CMakeLists.txt | Enables building tests subdirectory. |
| localizers/easynav_gps_localizer/tests/gps_localizer_tests.cpp | Adds functional test for param-seeded init + /initialpose reset. |
| localizers/easynav_gps_localizer/tests/CMakeLists.txt | Adds gtest target for GPS localizer tests. |
| localizers/easynav_gps_localizer/src/easynav_gps_localizer/GpsLocalizer.cpp | Adds /initialpose subscription and parameter-based initial pose staging to align UTM origin. |
| localizers/easynav_gps_localizer/include/easynav_gps_localizer/GpsLocalizer.hpp | Adds initial pose subscription + pending init pose storage. |
| localizers/easynav_gps_localizer/README.md | Documents initial pose params and subscription interface. |
| localizers/easynav_gps_localizer/CMakeLists.txt | Enables building tests subdirectory. |
| localizers/easynav_fusion_localizer/tests/fusion_localizer_tests.cpp | Adds functional test expecting param-seeded init + /initialpose reset. |
| localizers/easynav_fusion_localizer/tests/CMakeLists.txt | Adds gtest target for Fusion localizer tests. |
| localizers/easynav_fusion_localizer/src/easynav_fusion_localizer/ukf_wrapper.cpp | Makes set-pose deterministically set filter state; only processes measurement if uninitialized. |
| localizers/easynav_fusion_localizer/src/easynav_fusion_localizer/FusionLocalizer.cpp | Adds /initialpose subscription and forwards pose to filters; adjusts GNSS NavState access pattern. |
| localizers/easynav_fusion_localizer/include/easynav_fusion_localizer/FusionLocalizer.hpp | Declares initial pose subscription + callback. |
| localizers/easynav_fusion_localizer/config/example_params_summit_dual_gazebo.yaml | Assigns GNSS sensor to gnss group. |
| localizers/easynav_fusion_localizer/README.md | Updates package name/docs; documents initial pose parameters and subscription. |
| localizers/easynav_fusion_localizer/CMakeLists.txt | Enables building tests subdirectory. |
| localizers/easynav_costmap_localizer/tests/costmap_localizer_tests.cpp | Replaces prior tests with functional /initialpose initialization/reset test. |
| localizers/easynav_costmap_localizer/CMakeLists.txt | Enables building tests subdirectory. |
Comments suppressed due to low confidence (2)
localizers/easynav_fusion_localizer/src/easynav_fusion_localizer/FusionLocalizer.cpp:39
FusionLocalizerdoesn’t currently declare/read the documented<plugin>.initial_pose.{x,y,yaw}parameters or apply a seed pose during startup. This makes parameter-based deterministic initialization (and the new functional test expectation) ineffective until an/initialposemessage arrives. Consider reading these parameters inon_initialize()and callingukf_global_/ukf_local_->setPoseCallback()(or equivalent) to seed the filters.
const std::string & plugin_name = this->get_plugin_name();
const auto & tf_info = RTTFBuffer::getInstance()->get_tf_info();
RCLCPP_INFO(localizer_node->get_logger(), "Using tf_prefix: '%s'", tf_info.tf_prefix.c_str());
RCLCPP_INFO(localizer_node->get_logger(), "Using parameter namespace: '%s'",
localizers/easynav_navmap_localizer/tests/CMakeLists.txt:10
${std_srvs_TARGETS}is linked into this test target but nothing innavmap_localizer_tests.cppappears to require it anymore. Remove it if unused to keep the link interface minimal.
target_link_libraries(navmap_localizer_tests
${PROJECT_NAME}
rclcpp::rclcpp
rclcpp_lifecycle::rclcpp_lifecycle
${std_srvs_TARGETS}
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| node->get_fully_qualified_name() + std::string("/") + plugin_name + "/pose", 10); | ||
|
|
||
| init_pose_sub_ = get_node()->create_subscription<geometry_msgs::msg::PoseWithCovarianceStamped>( | ||
| "initialpose", 10, |
|
|
||
| // Subscribe to initial pose | ||
| init_pose_sub_ = node->create_subscription<geometry_msgs::msg::PoseWithCovarianceStamped>( | ||
| "initialpose", 10, |
|
|
||
| // Subscribe to initial pose | ||
| init_pose_sub_ = node->create_subscription<geometry_msgs::msg::PoseWithCovarianceStamped>( | ||
| "initialpose", 10, |
Comment on lines
+28
to
+33
| | Name | Type | Default | Description | | ||
| |---|---|---:|---| | ||
| | `<plugin>.initial_pose.x` | `double` | `0.0` | Initial X position (m). | | ||
| | `<plugin>.initial_pose.y` | `double` | `0.0` | Initial Y position (m). | | ||
| | `<plugin>.initial_pose.yaw` | `double` | `0.0` | Initial yaw (rad). | | ||
|
|
Comment on lines
3
to
+6
| find_package(std_srvs REQUIRED) | ||
|
|
||
| ament_add_gtest(costmap_localizer_tests costmap_localizer_tests.cpp) | ||
| target_link_libraries(costmap_localizer_tests | ||
| ament_add_gtest(navmap_localizer_tests navmap_localizer_tests.cpp) | ||
| target_link_libraries(navmap_localizer_tests |
| node->get_fully_qualified_name() + std::string("/") + plugin_name + "/pose", 10); | ||
|
|
||
| init_pose_sub_ = get_node()->create_subscription<geometry_msgs::msg::PoseWithCovarianceStamped>( | ||
| "initialpose", 10, |
|
|
||
| rclcpp::executors::SingleThreadedExecutor executor; | ||
| executor.add_node(node->get_node_base_interface()); | ||
| TEST_F(AMCLLocalizerInitialPoseTest, SubscribesToInitialPoseWithDefaultCallbackGroup) |
Comment on lines
+59
to
+70
| node->declare_parameter<double>(plugin_name + ".initial_pose.x", 0.0); | ||
| node->declare_parameter<double>(plugin_name + ".initial_pose.y", 0.0); | ||
| node->declare_parameter<double>(plugin_name + ".initial_pose.yaw", 0.0); | ||
|
|
||
| double init_x = 0.0; | ||
| double init_y = 0.0; | ||
| double init_yaw = 0.0; | ||
| node->get_parameter(plugin_name + ".initial_pose.x", init_x); | ||
| node->get_parameter(plugin_name + ".initial_pose.y", init_y); | ||
| node->get_parameter(plugin_name + ".initial_pose.yaw", init_yaw); | ||
|
|
||
| if (std::abs(init_x) > 1e-12 || std::abs(init_y) > 1e-12 || std::abs(init_yaw) > 1e-12) { |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
PR: Normalize
/initialposeacross localizers + functional tests (AMCL/GPS/Fusion)Context / motivation
Within
easynav_plugins/localizers, plugins differed in how they consumed the standard/initialposetopic (RViz-style initial pose). This made integration harder and prevented consistent validation that localizers react correctly to:/initialpose.What changed
1) Consistent
/initialposesubscription in all localizersAll plugins under
src/easynav_plugins/localizerswere reviewed and normalized so that:/initialpose(geometry_msgs/msg/PoseWithCovarianceStamped).Localizers covered:
easynav_costmap_localizereasynav_simple_localizereasynav_navmap_localizereasynav_gps_localizereasynav_fusion_localizer2) Functional tests to validate end-to-end behavior
Tests were migrated/re-structured into a consistent functional pattern (GTest) to cover:
NavState)./initialpose.Updated/added tests:
easynav_costmap_localizer/tests/*easynav_simple_localizer/tests/*easynav_navmap_localizer/tests/*easynav_gps_localizer/tests/gps_localizer_tests.cppeasynav_fusion_localizer/tests/fusion_localizer_tests.cpp3) Parameter-based initial pose seed in GPS and Fusion
To enable deterministic initialization (and make it testable), the following parameters are now read:
<plugin>.initial_pose.x<plugin>.initial_pose.y<plugin>.initial_pose.yawImplemented in:
easynav_gps_localizer(preloads the initial pose)easynav_fusion_localizer(preloads / applies the initial pose to the filter(s))4) Fix:
/initialposemust be reflected deterministically in Fusion (UKF)An issue was found where Fusion would receive
/initialpose, but the output (NavState[robot_pose]) would not reliably update due to how the UKF set-pose path was handled.robot_localization::UkfWrapper::setPoseCallback()was updated so that “set pose”:processMeasurement()if the filter was not initialized yet.This makes
/initialposeimpact Fusion’s published pose immediately and enables robust functional tests.Please, check it @midemig
Compatibility notes
Checklist
/initialpose.SubscriptionOptions(no explicit callback group)./initialposeupdates./initialposedeterministically inrobot_pose.