Skip to content

Feat/waypoint manager - #645

Merged
jorgenfj merged 45 commits into
mainfrom
feat/waypoint_manager
Dec 19, 2025
Merged

jorgenfj merged 45 commits into
mainfrom
feat/waypoint_manager

Conversation

@jorgenfj

@jorgenfj jorgenfj commented Dec 7, 2025

Copy link
Copy Markdown
Contributor

vortexntnu/vortex-msgs#35
Added mode logic for waypoints in reference filter.
Added waypoint manager + some basic tests

@Andeshog Andeshog left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Would be nice to see a four corner test (similar to what we did in easter testing) addition to the integration tests.

Comment on lines +35 to +40
std::bind(&WaypointManagerNode::handle_waypoint_goal, this,
std::placeholders::_1, std::placeholders::_2),
std::bind(&WaypointManagerNode::handle_waypoint_cancel, this,
std::placeholders::_1),
std::bind(&WaypointManagerNode::handle_waypoint_accepted, this,
std::placeholders::_1));

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Generally, consider using lambda instead of std::bind.

Comment on lines +110 to +115
bool persistent_action_mode_{false};
bool priority_mode_{false};

ReferenceFilterAction::Feedback latest_ref_feedback_;
bool have_reference_pose_{false};
bool cancel_in_progress_{false};

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

persistent_action_mode_active_
priority_mode_active_
has_reference_pose_
is_cancel_in_progress_
perhaps?

Comment on lines +116 to +117

std::uint64_t mission_id_ = 0;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Cant wait to see mission number 18,446,744,073,709,551,615 😂

Comment on lines +170 to +171

(void)goal_handle; // suppress unused variable warning

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

could also just do

rclcpp_action::CancelResponse WaypointManagerNode::handle_waypoint_cancel(
    const std::shared_ptr<WaypointManagerGoalHandle> /*goal_handle*/)

Comment on lines +77 to +78
Eigen::Vector6d fill_reference_goal(const geometry_msgs::msg::Pose& goal);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Why is stamped removed?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

The function did not use the header, so no need to pass more than what is required

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

vortex utils ros conversion here instead?

Comment on lines +249 to +253
case vortex_msgs::msg::Waypoint::FORWARD_HEADING: {
double dx = r_in(0) - x_(0);
double dy = r_in(1) - x_(1);

double forward_yaw = std::atan2(dy, dx);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

2 things:

  • No reason to use both heading and yaw in this block, choose one.
  • r_ and x_ are really poor names. Would be better off using something like reference_pose and current_drone_state. Would not be bad to integrate some of the new structs in vortex utils either, but that is probably out of scope for this PR

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

'out of scope for this PR' my favorite words

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Issue material 👨‍🦯

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Comment on lines +243 to +247
case vortex_msgs::msg::Waypoint::ONLY_POSITION:
r_out(3) = x_(3);
r_out(4) = x_(4);
r_out(5) = x_(5);
break;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Why isn't logic like ONLY_POSITION and ONLY_ORIENTATION handled in the motion controller(s) instead? Also with this you risk locking the desired orientation in awkward ways, instead of just not controlling said DOFs. If the locking behavior (fixing the desired value of one or more DOF) is something that is desired, that could easily be handled in the controller(s) in the same logic segment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I do think its fine that the wp manager/guidance controls which mode and so on, but the controller(s) should probably also know what mode it is performing

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

The locking is desired for this use case.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I agree that the mode logic could be handled in the controller, but this setup currently works as a MVP, and fits nicely within the scope of the action.
I feel the guidance and controller system could use a refactor with a "main orchestrator" or something, and this mode logic can be revamped then. The waypoint manager could potentially be incorporated into this "main orchestrator" and be extended to support LOS/velocity controller as well.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

locking the drone to a desired orientation could be something that the state machine requests and guidance system does i don't see the point of the (DP) controller differenciating between locking orientation and locking pose it is the same thing but simpler, albeit could be better tuned to some extent if we separate them.

The use case in this situation is more that we do not really want to change the position which would require the state machine to remember its last waypoint, recover the (x,y,z) coordinates and then send the same waypoint but with changed orientation which seemes tedious. Same goes for position only vice versa.

The thing that could be something to discuss is if we want the state machine to only communicate its desires with the orchistrator/manager node, otherwise we could make the state machine directly send requests to DP guidance about locking orientation.

@chrstrom chrstrom Dec 18, 2025

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Possible to just let each dof be addressable (i.e. Eigen::Index, strongly typed) and let whatever thing thats managing task execution lock whatever axes as required? (could also alias "common" things like position only, orientation only, z only, etc, etc). That way you keep the controller "dumb" in the sense that it has no knowledge of "mode", just "which axes are currently constrained". (I don't know anything about the current dp code so correct me if this is already the case 🔥)

Comment on lines +63 to +66
tf2::Quaternion q;
q.setRPY(fb.reference.roll, fb.reference.pitch, fb.reference.yaw);

pose.orientation = tf2::toMsg(q);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

seems to me this would make a nice vortex_utils function.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Comment on lines +120 to +122
rclcpp_action::GoalResponse WaypointManagerNode::handle_waypoint_goal(
const rclcpp_action::GoalUUID&,
std::shared_ptr<const WaypointManager::Goal> goal) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

A better way of handling unused parameters:

rclcpp_action::GoalResponse WaypointManagerNode::handle_waypoint_goal(
    const rclcpp_action::GoalUUID& /*goal_uuid*/,
    std::shared_ptr<const WaypointManager::Goal> goal)

@Q3rkses Q3rkses left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

lazy review

Comment on lines +243 to +247
case vortex_msgs::msg::Waypoint::ONLY_POSITION:
r_out(3) = x_(3);
r_out(4) = x_(4);
r_out(5) = x_(5);
break;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

locking the drone to a desired orientation could be something that the state machine requests and guidance system does i don't see the point of the (DP) controller differenciating between locking orientation and locking pose it is the same thing but simpler, albeit could be better tuned to some extent if we separate them.

The use case in this situation is more that we do not really want to change the position which would require the state machine to remember its last waypoint, recover the (x,y,z) coordinates and then send the same waypoint but with changed orientation which seemes tedious. Same goes for position only vice versa.

The thing that could be something to discuss is if we want the state machine to only communicate its desires with the orchistrator/manager node, otherwise we could make the state machine directly send requests to DP guidance about locking orientation.

pose.position.x = x
pose.position.y = y
pose.position.z = z
half = yaw * 0.5

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

why not quat to euler?

@jorgenfj

Copy link
Copy Markdown
Contributor Author

@Andeshog @kluge7 I think we might have to move the new tests to a separate repo or change the workflow. Right now some of the workflows does not have stonefish in their dependencies.repos and when running colcon test, the tests that depend on stonefish fails.

@Andeshog

Copy link
Copy Markdown
Contributor

@Andeshog @kluge7 I think we might have to move the new tests to a separate repo or change the workflow. Right now some of the workflows does not have stonefish in their dependencies.repos and when running colcon test, the tests that depend on stonefish fails.

The nodetests/launch tests should not depend on stonefish? Those tests are only testing the ros part for a node. Integration/system tests can stay as they are (the bash scripts) IMO, from this comment.

@codecov

codecov Bot commented Dec 18, 2025

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 50.20243% with 123 lines in your changes missing coverage. Please review.
✅ Project coverage is 35.63%. Comparing base (54caaa7) to head (f1f181a).
⚠️ Report is 78 commits behind head on main.

Files with missing lines Patch % Lines
...sion/waypoint_manager/src/waypoint_manager_ros.cpp 51.47% 77 Missing and 22 partials ⚠️
...e/reference_filter_dp/src/reference_filter_ros.cpp 44.18% 20 Missing and 4 partials ⚠️
Additional details and impacted files
@@             Coverage Diff             @@
##             main     #645       +/-   ##
===========================================
+ Coverage   24.01%   35.63%   +11.62%     
===========================================
  Files          38       38               
  Lines        2286     2256       -30     
  Branches      612      686       +74     
===========================================
+ Hits          549      804      +255     
+ Misses       1588     1273      -315     
- Partials      149      179       +30     
Flag Coverage Δ
unittests 35.63% <50.20%> (+11.62%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

Files with missing lines Coverage Δ
...e/reference_filter_dp/src/reference_filter_ros.cpp 72.94% <44.18%> (+72.36%) ⬆️
...sion/waypoint_manager/src/waypoint_manager_ros.cpp 51.47% <51.47%> (ø)

... and 1 file with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@jorgenfj
jorgenfj requested a review from Andeshog December 18, 2025 16:37
Comment on lines +283 to +287
const geometry_msgs::msg::Pose goal =
goal_handle->get_goal()->waypoint.pose;
uint8_t mode = goal_handle->get_goal()->waypoint.mode;
double convergence_threshold =
goal_handle->get_goal()->convergence_threshold;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I would try to use auto here, and elsewhere where it makes sense. It avoids visual clutter and potential accidental implicit conversions. However, do not use auto with Eigen types (eigen common pitfalls)

Comment on lines +6 to +7

if(BUILD_TESTING)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

unnecessary if here?

@Andeshog Andeshog left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

lgetm

@jorgenfj
jorgenfj merged commit 007bb81 into main Dec 19, 2025
14 checks passed
@jorgenfj
jorgenfj deleted the feat/waypoint_manager branch December 19, 2025 10:48
anbit-adhi pushed a commit that referenced this pull request Jan 6, 2026
* waypoint mode handling

* update tests with new message

* initial package setup

* ros interface function declaration

* node setup

* working prototype

* reentrant cb, multithreaded

* single threaded impl

* conv threshold action goal

* default thresholdref conv value

* removed switching logic

* removed timer execution

* sim test utils

* waypoint_manager_test setup

* no rendering test arg

* waypoint tests, timeout error

* test refactor

* format

* rename utils package

* test suite and description

* first waypoint test

* removed unused function

* renamed service field to priority. Added simple tests

* waypoint manager readme

* uniform attitude naming convention

* fix pr requests

* update tests with new service fields

* four corner test

* update util func name

* update with new action def

* removed failing build type

* test dependencies

* ignore failing yasmin package

* remove __init__ files

* quat_to_euler in make_pose helper

* added __init__ file

* removed sim deps for test packages

* added action shutdown handling

* removed waypoint manager set setup

* added waypoint manager node tests

* waypoint manager 4 corner sim test

* added missing launch testing test dependency

* add sleep for topic discovery

* fix action member field name

* removed unnecessary if here
CurryMonsters pushed a commit that referenced this pull request Jan 23, 2026
* waypoint mode handling

* update tests with new message

* initial package setup

* ros interface function declaration

* node setup

* working prototype

* reentrant cb, multithreaded

* single threaded impl

* conv threshold action goal

* default thresholdref conv value

* removed switching logic

* removed timer execution

* sim test utils

* waypoint_manager_test setup

* no rendering test arg

* waypoint tests, timeout error

* test refactor

* format

* rename utils package

* test suite and description

* first waypoint test

* removed unused function

* renamed service field to priority. Added simple tests

* waypoint manager readme

* uniform attitude naming convention

* fix pr requests

* update tests with new service fields

* four corner test

* update util func name

* update with new action def

* removed failing build type

* test dependencies

* ignore failing yasmin package

* remove __init__ files

* quat_to_euler in make_pose helper

* added __init__ file

* removed sim deps for test packages

* added action shutdown handling

* removed waypoint manager set setup

* added waypoint manager node tests

* waypoint manager 4 corner sim test

* added missing launch testing test dependency

* add sleep for topic discovery

* fix action member field name

* removed unnecessary if here
@github-actions

Copy link
Copy Markdown

🎉 This PR is included in version 2.6.0 🎉

The release is available on GitHub release

Your semantic-release bot 📦🚀

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants