Integrate Nav2 for waypoint following and update documentation#5
Conversation
There was a problem hiding this comment.
Pull request overview
This PR adds Nav2 integration bridges so waypoint_editor-generated CSV waypoints can be executed by Nav2 either as “stop at each waypoint” (follow_waypoints) or “smoothly traverse all poses” (navigate_through_poses), along with launch and documentation updates.
Changes:
- Added two new ROS 2 nodes that load waypoint CSVs and dispatch Nav2 actions (
follow_waypoints/navigate_through_poses). - Added launch files to run each bridge node with configurable
waypoint_fileandframe_id. - Updated build/dependency metadata and added usage documentation (EN + ZH).
Reviewed changes
Copilot reviewed 8 out of 8 changed files in this pull request and generated 8 comments.
Show a summary per file
| File | Description |
|---|---|
| src/waypoint_to_nav2.cpp | New bridge node sending CSV waypoints via Nav2 follow_waypoints. |
| src/waypoint_through_nav2.cpp | New bridge node sending CSV waypoints via Nav2 navigate_through_poses. |
| launch/waypoint_to_nav2.launch.py | Launch entrypoint for waypoint_to_nav2 node. |
| launch/waypoint_through_nav2.launch.py | Launch entrypoint for waypoint_through_nav2 node. |
| CMakeLists.txt | Builds/installs the two new executables; adds rclcpp_action. |
| package.xml | Adds rclcpp_action dependency. |
| USAGE_WITH_NAV2.md | English documentation for Nav2 workflow and both bridge modes. |
| USAGE_WITH_NAV2.zh.md | Chinese documentation for Nav2 workflow and both bridge modes. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| auto send_goal_options = rclcpp_action::Client<NavigateThroughPoses>::SendGoalOptions(); | ||
| send_goal_options.goal_response_callback = | ||
| std::bind(&WaypointThroughNav2::goalResponseCallback, this, std::placeholders::_1); | ||
| send_goal_options.feedback_callback = | ||
| std::bind(&WaypointThroughNav2::feedbackCallback, this, std::placeholders::_1, std::placeholders::_2); | ||
| send_goal_options.result_callback = | ||
| std::bind(&WaypointThroughNav2::resultCallback, this, std::placeholders::_1); | ||
|
|
||
| nav_through_client_->async_send_goal(goal_msg, send_goal_options); | ||
|
|
||
| response->success = true; | ||
| response->message = "Poses sent to Nav2 (navigate through)"; | ||
| } |
There was a problem hiding this comment.
The Trigger service returns success right after async_send_goal, but the goal can still be rejected in goal_response_callback. This makes the service response unreliable for automation. Consider waiting for the goal handle future (with a timeout) and setting response->success/message based on acceptance (or explicitly document/encode that the service only enqueues the request).
| RCLCPP_INFO(this->get_logger(), | ||
| "Distance remaining: %.2f, poses remaining: %d", | ||
| feedback->distance_remaining, | ||
| feedback->number_of_poses_remaining); |
There was a problem hiding this comment.
Logging action feedback at INFO for every update can generate a lot of output (Nav2 feedback is often high-frequency). Consider throttling (RCLCPP_INFO_THROTTLE) or dropping to DEBUG to avoid log spam.
| RCLCPP_INFO(this->get_logger(), | |
| "Distance remaining: %.2f, poses remaining: %d", | |
| feedback->distance_remaining, | |
| feedback->number_of_poses_remaining); | |
| RCLCPP_INFO_THROTTLE( | |
| this->get_logger(), | |
| *this->get_clock(), | |
| 1000, | |
| "Distance remaining: %.2f, poses remaining: %d", | |
| feedback->distance_remaining, | |
| feedback->number_of_poses_remaining); |
| import os | ||
| from ament_index_python.packages import get_package_share_directory | ||
|
|
||
| def generate_launch_description(): | ||
| pkg = get_package_share_directory('waypoint_editor') | ||
|
|
There was a problem hiding this comment.
Unused imports/variables: os and get_package_share_directory are imported and pkg is assigned but never used. Please remove them to avoid lint failures and keep the launch file minimal.
| import os | |
| from ament_index_python.packages import get_package_share_directory | |
| def generate_launch_description(): | |
| pkg = get_package_share_directory('waypoint_editor') | |
| def generate_launch_description(): |
| import os | ||
| from ament_index_python.packages import get_package_share_directory | ||
|
|
||
| def generate_launch_description(): | ||
| pkg = get_package_share_directory('waypoint_editor') |
There was a problem hiding this comment.
Unused imports/variables: os and get_package_share_directory are imported and pkg is assigned but never used. Please remove them to avoid lint failures and keep the launch file minimal.
| import os | |
| from ament_index_python.packages import get_package_share_directory | |
| def generate_launch_description(): | |
| pkg = get_package_share_directory('waypoint_editor') | |
| def generate_launch_description(): |
| | Bridge Node | Nav2 Action | Behavior | Use Case | | ||
| |-------------|-------------|----------|----------| | ||
| | `waypoint_to_nav2` | `follow_waypoints` | Stop at each waypoint before moving to the next | Inspection, point-by-point tasks | | ||
| | `waypoint_through_nav2` | `navigate_through_poses` | Plan a smooth path through all waypoints without stopping | Patrol, fast traversal | |
There was a problem hiding this comment.
This Markdown table uses double pipes (e.g., "|| Bridge Node ..."), which renders incorrectly in most Markdown parsers. Replace the leading/trailing "||" with standard single-pipe table syntax ("| ... |").
| | 桥接节点 | Nav2 Action | 行为 | 适用场景 | | ||
| |---------|-------------|------|----------| | ||
| | `waypoint_to_nav2` | `follow_waypoints` | 逐点停靠 — 到达每个航点后停下再前往下一个 | 巡检、逐点任务 | | ||
| | `waypoint_through_nav2` | `navigate_through_poses` | 平滑穿越 — 规划连续路径经过所有航点,不停留 | 巡逻、快速穿越 | |
There was a problem hiding this comment.
该 Markdown 表格使用了双竖线(例如 "|| 桥接节点 ..."),多数 Markdown 渲染器会无法正确显示。建议改为标准单竖线表格语法("| ... |")。
| follow_waypoints_client_->async_send_goal(goal_msg, send_goal_options); | ||
|
|
||
| response->success = true; | ||
| response->message = "Waypoints sent to Nav2"; |
There was a problem hiding this comment.
The Trigger service reports success immediately after calling async_send_goal, even though Nav2 may still reject the goal (goal_response_callback). This can mislead callers into thinking waypoint following started successfully. Consider waiting for the goal handle future (with a timeout) and setting response->success/message based on whether the goal was accepted, or change the service contract/message to clearly indicate the request was only queued.
| response->message = "Waypoints sent to Nav2"; | |
| response->message = "Waypoints request sent to Nav2; goal acceptance not yet confirmed"; |
| GoalHandleFollowWaypoints::SharedPtr, | ||
| const std::shared_ptr<const FollowWaypoints::Feedback> feedback) | ||
| { | ||
| RCLCPP_INFO(this->get_logger(), "Current waypoint: %u", feedback->current_waypoint); |
There was a problem hiding this comment.
This feedback callback logs at INFO on every action feedback update, which can spam logs and impact runtime performance. Consider using RCLCPP_DEBUG, or RCLCPP_INFO_THROTTLE with a reasonable period.
| RCLCPP_INFO(this->get_logger(), "Current waypoint: %u", feedback->current_waypoint); | |
| RCLCPP_INFO_THROTTLE( | |
| this->get_logger(), | |
| *this->get_clock(), | |
| 1000, | |
| "Current waypoint: %u", | |
| feedback->current_waypoint); |
This pull request adds two new bridge nodes and supporting launch files to enable seamless integration between the
waypoint_editorand Nav2 navigation stack. The bridge nodes allow waypoints saved in CSV format by the editor to be sent to Nav2 for navigation, supporting both "follow waypoints" (stop at each point) and "navigate through poses" (smooth traversal). The documentation is updated to explain usage, and necessary dependencies are added.New bridge node functionality:
src/waypoint_to_nav2.cppnode to read CSV waypoints and send them to Nav2 using thefollow_waypointsaction, causing the robot to stop at each waypoint.src/waypoint_through_nav2.cppnode to read CSV waypoints and send them to Nav2 using thenavigate_through_posesaction, enabling smooth traversal through all waypoints without stopping.Launch and build integration:
launch/waypoint_to_nav2.launch.pyandlaunch/waypoint_through_nav2.launch.pyfor easy startup and parameter configuration of the new bridge nodes. [1] [2]CMakeLists.txtto build and install the new nodes, and addedrclcpp_actionas a required package. [1] [2]package.xmlto includerclcpp_actionas a build and exec dependency. [1] [2]Documentation:
USAGE_WITH_NAV2.md, providing clear instructions for using the waypoint editor with Nav2, including workflow and launch details for both bridge modes.