Skip to content

Conversation

@jorgenfj
Copy link
Contributor

@jorgenfj jorgenfj commented Dec 7, 2025

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

Copy link
Contributor

@Andeshog Andeshog left a comment

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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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.

Copy link
Member

@chrstrom chrstrom Dec 18, 2025

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
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
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
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)

Comment on lines +37 to +44
[this](auto goal_id, auto goal) {
return handle_waypoint_goal(goal_id, goal);
},

[this](auto goal_id) { return handle_waypoint_cancel(goal_id); },

[this](auto goal_handle) {
return handle_waypoint_accepted(goal_handle);
Copy link
Contributor

Choose a reason for hiding this comment

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

Could parameters here be const ref? (too lazy to find out myself)

Copy link
Contributor

Choose a reason for hiding this comment

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

Could this be done for the bash script tests as well? I believe the launch test and script test should coexist, but in my opinion they should do different things. As it is now, the launch tests can directly replace the bash script based node tests, and test that the content in each package works by itself. This also gives test coverage, which is good. The integration tests should then be handled (as they are now) by the github actions workflow, where the whole system is started up in the same way as on deployment. One pro here is that the rosbag (in case of a failing run) is easily accessable from the artifact, as well as nice logs. The potential of using scripting to orchestrate integration tests is also far bigger.

IMO this gets the best of both worlds.

The immediate action I would do is to remove the node tests and put the launch-based node tests in their corresponding package (make an issue on this if you dont want to cook it up now).

Copy link
Contributor

@Q3rkses Q3rkses left a comment

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
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
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
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
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
Copy link

codecov bot commented Dec 18, 2025

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 1 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
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
Contributor

Choose a reason for hiding this comment

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

unnecessary if here?

Copy link
Contributor

@Andeshog Andeshog left a comment

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
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