Skip to content

merge control stack from easter testing into main#706

Open
Q3rkses wants to merge 36 commits intomainfrom
dp_adaptive_backstepping_controler_to_quaternion
Open

merge control stack from easter testing into main#706
Q3rkses wants to merge 36 commits intomainfrom
dp_adaptive_backstepping_controler_to_quaternion

Conversation

@Q3rkses
Copy link
Copy Markdown
Contributor

@Q3rkses Q3rkses commented Apr 6, 2026

implemented quat adaptive backstepping dp
modified quat pid dp
modified joystick interface
modified reference filter quat

@Q3rkses Q3rkses requested a review from kluge7 April 6, 2026 18:12
@Q3rkses Q3rkses self-assigned this Apr 6, 2026
Copy link
Copy Markdown
Contributor

@vortexuser vortexuser left a comment

Choose a reason for hiding this comment

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

first round of reviews

Copy link
Copy Markdown
Contributor

@kluge7 kluge7 left a comment

Choose a reason for hiding this comment

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

Image

@codecov
Copy link
Copy Markdown

codecov bot commented Apr 6, 2026

Codecov Report

❌ Patch coverage is 39.17616% with 694 lines in your changes missing coverage. Please review.
✅ Project coverage is 40.75%. Comparing base (8a0f2e8) to head (fe8b381).

Files with missing lines Patch % Lines
...ntrol/pid_controller_dp/src/pid_controller_ros.cpp 0.00% 192 Missing ⚠️
...troller_quat/src/dp_adapt_backs_controller_ros.cpp 0.60% 165 Missing ⚠️
...ller_quat/test/dp_adapt_backs_controller_tests.cpp 52.86% 1 Missing and 114 partials ⚠️
...ol/pid_controller_dp/test/pid_controller_tests.cpp 60.76% 0 Missing and 113 partials ⚠️
control/pid_controller_dp/src/pid_controller.cpp 24.24% 50 Missing ⚠️
...pid_controller_dp_euler/src/pid_controller_ros.cpp 0.00% 17 Missing ⚠️
...ce_filter_dp_quat/src/ros/reference_filter_ros.cpp 0.00% 12 Missing ⚠️
...rol/pid_controller_dp/src/pid_controller_utils.cpp 65.00% 6 Missing and 1 partial ⚠️
..._controller_quat/src/dp_adapt_backs_controller.cpp 89.47% 6 Missing ⚠️
...rence_filter_dp_quat/src/lib/waypoint_follower.cpp 0.00% 4 Missing ⚠️
... and 5 more
Additional details and impacted files
@@            Coverage Diff             @@
##             main     #706      +/-   ##
==========================================
+ Coverage   39.70%   40.75%   +1.04%     
==========================================
  Files          79       82       +3     
  Lines        5332     6265     +933     
  Branches     1715     2411     +696     
==========================================
+ Hits         2117     2553     +436     
- Misses       2769     3037     +268     
- Partials      446      675     +229     
Flag Coverage Δ
unittests 40.75% <39.17%> (+1.04%) ⬆️

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

Files with missing lines Coverage Δ
...ference_filter_dp/src/ros/reference_filter_ros.cpp 81.96% <100.00%> (ø)
...de/thrust_allocator_auv/thrust_allocator_utils.hpp 70.58% <ø> (-13.79%) ⬇️
...ust_allocator_auv/tests/thrust_allocator_tests.cpp 60.91% <100.00%> (ø)
...trol/pid_controller_dp/src/pid_controller_node.cpp 0.00% <0.00%> (ø)
...s_controller/src/dp_adapt_backs_controller_ros.cpp 0.66% <0.00%> (ø)
...oller_quat/src/dp_adapt_backs_controller_utils.cpp 94.64% <94.64%> (ø)
...ntroller_dp/include/pid_controller_dp/typedefs.hpp 0.00% <0.00%> (ø)
...rence_filter_dp_quat/src/lib/waypoint_follower.cpp 83.60% <0.00%> (-4.33%) ⬇️
.../thrust_allocator_auv/src/thrust_allocator_ros.cpp 0.93% <0.00%> (-0.01%) ⬇️
..._controller_quat/src/dp_adapt_backs_controller.cpp 89.47% <89.47%> (ø)
... and 8 more

... and 2 files with indirect coverage changes

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

@Q3rkses Q3rkses requested review from Andeshog and jorgenfj April 7, 2026 11:52
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.

is this controller going to be used? If so, maybe clean it up a bit. A lot of unused includes, outdated types/not using common types from vortex utils, redefinitions of existing utils functions

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.

yes pid controllah was pretty 🔥

Comment on lines +4 to +68
void print_eta(const types::Eta& eta) {
spdlog::info("Eta values:");
auto pos = eta.pos_vector();
auto ori = eta.ori_quaternion();
spdlog::info("Position - North: {}, East: {}, Down: {}", pos[0], pos[1],
pos[2]);
spdlog::info("Orientation - w: {}, x: {}, y: {}, z: {}", ori.w(), ori.x(),
ori.y(), ori.z());
}

void print_nu(const types::Nu& nu) {
spdlog::info("Nu values:");
auto v = nu.to_vector();
spdlog::info("Linear Speed - u: {}, v: {}, w: {}", v(0), v(1), v(2));
spdlog::info("Angular Speed - p: {}, q: {}, r: {}", v(3), v(4), v(5));
}

void print_vect_6d(const types::Vector6d& vec) {
spdlog::info("Vector6d values:");
for (int i = 0; i < 6; ++i) {
spdlog::info("Element[{}]: {}", i, vec[i]);
}
}

void print_J_transformation(const types::J_transformation& J) {
spdlog::info("J_transformation:");

spdlog::info("R (3x3) elements:");
for (int i = 0; i < J.R.rows(); ++i) {
for (int j = 0; j < J.R.cols(); ++j) {
spdlog::info("R[{},{}] = {}", i, j, J.R(i, j));
}
}

spdlog::info("T (4x3) elements:");
for (int i = 0; i < J.T.rows(); ++i) {
for (int j = 0; j < J.T.cols(); ++j) {
spdlog::info("T[{},{}] = {}", i, j, J.T(i, j));
}
}

spdlog::info("Combined Matrix (7x6) elements:");
auto M = J.as_matrix();
for (int i = 0; i < M.rows(); ++i) {
for (int j = 0; j < M.cols(); ++j) {
spdlog::info("M[{},{}] = {}", i, j, M(i, j));
}
}
}

void print_Jinv_transformation(const types::Matrix6x7d& J_inv) {
spdlog::info("J_pseudo_inverse (6x7):");
for (int i = 0; i < J_inv.rows(); ++i) {
std::string row;
row.reserve(128);
row += "[";
for (int j = 0; j < J_inv.cols(); ++j) {
row += std::to_string(J_inv(i, j));
if (j < J_inv.cols() - 1)
row += ", ";
}
row += "]";
spdlog::info("{}", row);
}
}
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 are these still here? We added those to debug the weird behavior last year, not to be used on main

Comment on lines +81 to 82
types::Eta error = error_eta(eta, eta_d); // calculate eta error

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.

This comment doesnt add very much

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.

Goes for the rest of the comments in this file too

Comment on lines +84 to +85
types::Vector6d error_6;
error_6 << error.x, error.y, error.z, error.qx, error.qy, error.qz;
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.

Minor, but having the 6 in the variable name doesnt really do any good, especially when there no longer is references to the 7 sized vector anymore. Also, would probably benefit from adding updated utility functions for the 6 dof quat maths

Comment on lines 7 to 32
types::Eta eta_convert_from_ros_to_eigen(
const geometry_msgs::msg::PoseWithCovarianceStamped::SharedPtr msg) {
const geometry_msgs::msg::PoseWithCovariance& msg) {
types::Eta eta;
eta.pos << msg->pose.pose.position.x, msg->pose.pose.position.y,
msg->pose.pose.position.z;
eta.ori.w() = msg->pose.pose.orientation.w;
eta.ori.x() = msg->pose.pose.orientation.x;
eta.ori.y() = msg->pose.pose.orientation.y;
eta.ori.z() = msg->pose.pose.orientation.z;
eta.x = msg.pose.position.x;
eta.y = msg.pose.position.y;
eta.z = msg.pose.position.z;
eta.qw = msg.pose.orientation.w;
eta.qx = msg.pose.orientation.x;
eta.qy = msg.pose.orientation.y;
eta.qz = msg.pose.orientation.z;

return eta;
}

types::Nu nu_convert_from_ros_to_eigen(
const geometry_msgs::msg::TwistWithCovarianceStamped::SharedPtr msg) {
const geometry_msgs::msg::TwistWithCovariance& msg) {
types::Nu nu;
nu.linear_speed << msg->twist.twist.linear.x, msg->twist.twist.linear.y,
msg->twist.twist.linear.z;
nu.angular_speed << msg->twist.twist.angular.x, msg->twist.twist.angular.y,
msg->twist.twist.angular.z;
nu.u = msg.twist.linear.x;
nu.v = msg.twist.linear.y;
nu.w = msg.twist.linear.z;
nu.p = msg.twist.angular.x;
nu.q = msg.twist.angular.y;
nu.r = msg.twist.angular.z;

return nu;
}
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.

Just use what exists in vortex utils?

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.

yes

Comment on lines +32 to +33
callback_handle_ = this->add_on_set_parameters_callback(std::bind(
&PIDControllerNode::parametersCallback, 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.

lambda over bind

Comment on lines +166 to +183
this->declare_parameter<double>("Kp_x", 1.0);
this->declare_parameter<double>("Kp_y", 1.0);
this->declare_parameter<double>("Kp_z", 1.0);
this->declare_parameter<double>("Kp_roll", 1.0);
this->declare_parameter<double>("Kp_pitch", 1.0);
this->declare_parameter<double>("Kp_yaw", 1.0);
this->declare_parameter<double>("Ki_x", 0.1);
this->declare_parameter<double>("Ki_y", 0.1);
this->declare_parameter<double>("Ki_z", 0.1);
this->declare_parameter<double>("Ki_roll", 0.1);
this->declare_parameter<double>("Ki_pitch", 0.1);
this->declare_parameter<double>("Ki_yaw", 0.1);
this->declare_parameter<double>("Kd_x", 0.1);
this->declare_parameter<double>("Kd_y", 0.1);
this->declare_parameter<double>("Kd_z", 0.1);
this->declare_parameter<double>("Kd_roll", 0.1);
this->declare_parameter<double>("Kd_pitch", 0.1);
this->declare_parameter<double>("Kd_yaw", 0.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.

Would personally drop default values

Comment on lines +185 to +212
std::vector<double> Kp_vec = {
this->get_parameter("Kp_x").as_double(),
this->get_parameter("Kp_y").as_double(),
this->get_parameter("Kp_z").as_double(),
this->get_parameter("Kp_roll").as_double(),
this->get_parameter("Kp_pitch").as_double(),
this->get_parameter("Kp_yaw").as_double(),
};
std::vector<double> Ki_vec = {
this->get_parameter("Ki_x").as_double(),
this->get_parameter("Ki_y").as_double(),
this->get_parameter("Ki_z").as_double(),
this->get_parameter("Ki_roll").as_double(),
this->get_parameter("Ki_pitch").as_double(),
this->get_parameter("Ki_yaw").as_double(),
};
std::vector<double> Kd_vec = {
this->get_parameter("Kd_x").as_double(),
this->get_parameter("Kd_y").as_double(),
this->get_parameter("Kd_z").as_double(),
this->get_parameter("Kd_roll").as_double(),
this->get_parameter("Kd_pitch").as_double(),
this->get_parameter("Kd_yaw").as_double(),
};

types::Vector6d Kp_vec_eigen(Kp_vec.data());
types::Vector6d Ki_vec_eigen(Ki_vec.data());
types::Vector6d Kd_vec_eigen(Kd_vec.data());
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.

No reason to go through std::vector here is it?

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.

Have not loooked at it probably you are right

Copy link
Copy Markdown
Contributor

@jorgenfj jorgenfj left a comment

Choose a reason for hiding this comment

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

We should also refactor the ros nodes to publish with unique_ptr and the subscriptions to follow this guideline

Comment on lines +61 to +64
/** Enforce positive hemisphere to prevent sign flips in the published
* reference quaternion that would cause the downstream controller to
* see large spurious orientation errors.
*/
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.

It makes more sense for the controllers that compare quaternions to be responsible for the sign handling instead of assuming an input convention. But this is still nice for plotting 👍

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 like plots converging :(

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 are there 3 param files?

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.

because i need to test that everything works, will change the workflows to use the sim file in the sim tests when my claude usage is back (i dont do devops dont blame me)

Comment on lines +69 to 79
/**
* @brief Compute the 6D quaternion error state ε̃ = [Δp; ε_q].
*
* The scalar part q̃_w is not returned. The sign of the quaternion error is
* flipped when q̃_w < 0 to enforce the shortest-path convention.
*
* @param eta Actual vehicle pose [x, y, z, qw, qx, qy, qz]
* @param eta_d Desired vehicle pose [x, y, z, qw, qx, qy, qz]
* @return Eta struct whose [qx, qy, qz] fields carry ε_q (qw is discarded)
*/
types::Eta error_eta(const types::Eta& eta, const types::Eta& eta_d);
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.

Is this comment correct?

Comment on lines 25 to 36
types::Eta error_eta(const types::Eta& eta, const types::Eta& eta_d) {
types::Eta eta_error;

eta_error.pos = eta.pos - eta_d.pos;
eta_error.ori = eta_d.ori.conjugate() * eta.ori;

eta_error.ori = eta_error.ori.normalized();

return eta_error;
types::Eta error = eta - eta_d;
// Enforce shortest path: q and -q represent the same rotation, but only
// qw >= 0 gives the correct sign for the vector part used as error signal.
if (error.qw < 0.0) {
error.qw = -error.qw;
error.qx = -error.qx;
error.qy = -error.qy;
error.qz = -error.qz;
}
return error;
}
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.

If we want this to return the 6d error vector we should use the error_quaternion from vortex_utils math.hpp.

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.

yes, i think i added that after doing this fix during easter

Comment on lines +222 to +241
reference_msg.header.frame_id = "odom"
# reference_msg.header.frame_id = "odom"
reference_msg.header.frame_id = "base_link"
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.

This should still be odom

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.

bro one line changes you could do yourself T-T

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.

Out of the scope of this review

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.

Should avoid the RPY representation of pose/current_state so the reference mode does not inherit gimbal lock problems etc..

eta_error.ori = eta_error.ori.normalized();

return eta_error;
types::Eta error = eta - eta_d;
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 am also not a fan of the - operator for quaternions types

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.

By the way wouldn't it be more accurate to use the full quaternion identity for error using the tan^-1 function (in utils) so that errors dont trickle down

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.

Depends on use case IMO. For the reference filter and controllers the errors should ideally never be large enough that it is a problem. This also avoids the singularity of the tan error

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.

So for the reference filter it is fine, but if you want to use the tan version for the controllers you are free to do so

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