Conversation
…ith new test setup
for more information, see https://pre-commit.ci
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## main #643 +/- ##
==========================================
+ Coverage 33.53% 35.24% +1.70%
==========================================
Files 44 45 +1
Lines 3003 3459 +456
Branches 780 1078 +298
==========================================
+ Hits 1007 1219 +212
- Misses 1813 1944 +131
- Partials 183 296 +113
Flags with carried forward coverage won't be shown. Click here to find out more.
🚀 New features to boost your workflow:
|
Andeshog
left a comment
There was a problem hiding this comment.
Since this is still a draft I wont comment on the debugs and prints and so on. But I do encourage utilizing Eta and Nu from vortex-utils, along with the relevant functions 👍 Also, when time comes it would be cool to see a version of the integration test utilizing this controller for a continuous proof of the quality 💯
There was a problem hiding this comment.
Everything in this file exist in vortex-utils, and most is embedded in the Eta struct as well 😄
| // TODO: parameter callback for dynamic reconfigure of PID gains | ||
| //@brief Callback function for parameter updates | ||
| // @param parameters: vector of parameters to be set | ||
| rcl_interfaces::msg::SetParametersResult parametersCallback( | ||
| const std::vector<rclcpp::Parameter>& parameters); |
There was a problem hiding this comment.
Consider using a yaml-based approach like Anbit did. Mixing this approach with a service call (Trigger) allows for the same dynamic reconfiguration, but without relying so much on ROS.
| Kp: [70.0, 70.0, 70.0, 12.0, 12.0, 12.0] | ||
| Ki: [2.0, 2.0, 2.0, 0.12, 0.12, 0.12] | ||
| Kd: [10.0, 10.0, 10.0, 4.0, 5.0, 4.0] | ||
| # Kp: [70.0, 70.0, 70.0, 12.0, 12.0, 12.0] | ||
| # Ki: [2.0, 2.0, 2.0, 0.12, 0.12, 0.12] | ||
| # Kd: [10.0, 10.0, 10.0, 4.0, 5.0, 4.0] | ||
| Kp_x: 10.0 | ||
| Kp_y: 0.0 | ||
| Kp_z: 0.0 | ||
| Kp_roll: 0.0 | ||
| Kp_pitch: 0.0 | ||
| Kp_yaw: 0.0 | ||
| Ki_x: 0.0 | ||
| Ki_y: 0.0 | ||
| Ki_z: 0.0 | ||
| Ki_roll: 0.0 | ||
| Ki_pitch: 0.0 | ||
| Ki_yaw: 0.0 | ||
| Kd_x: 0.0 | ||
| Kd_y: 0.0 | ||
| Kd_z: 0.0 | ||
| Kd_roll: 0.0 | ||
| Kd_pitch: 0.0 | ||
| Kd_yaw: 0.0 |
There was a problem hiding this comment.
Is it not more tidy to have the parameters in vectors here?
|
This is actively being worked on. I guess we just forgot to change it from draft |
chrstrom
left a comment
There was a problem hiding this comment.
First pass, I'll have another read-through when its out of draft / feature-complete 🚀
| src/pid_controller_conversions.cpp | ||
| ) | ||
|
|
||
| ament_target_dependencies(${LIB_NAME} PUBLIC |
There was a problem hiding this comment.
Sticking to the "keep non-ROS code separate from everything else", you wouldn't want to pull in anything to your lib using ament_target_dependencies. Instead, use pure cmake for the library, and link in ros-deps + the lib with ament for the final executable
|
|
||
| rcl_interfaces::msg::SetParametersResult PIDControllerNode::parametersCallback( | ||
| const std::vector<rclcpp::Parameter>& parameters) { | ||
| rcl_interfaces::msg::SetParametersResult result; | ||
| result.successful = true; | ||
| result.reason = "success"; |
There was a problem hiding this comment.
would consider vectorizing parameters here, or make an unordered map for "parameter sting rep" -> "some struct holding gain type and eigen index"
| @@ -114,20 +250,68 @@ void PIDControllerNode::publish_tau() { | |||
| } | |||
|
|
|||
| void PIDControllerNode::set_pid_params() { | |||
There was a problem hiding this comment.
Would argue that you should disallow default parameters here and throw / panic if unset. Easy to miss one in config and could lead to painful debugging times
| spdlog::info("Eta: "); | ||
| print_eta(eta); | ||
| spdlog::info("Eta desired: "); | ||
| print_eta(eta_d); | ||
| spdlog::info("Eta error:"); | ||
| print_eta(error); |
There was a problem hiding this comment.
Would suggest making this spdlog::trace (you could pass in log level to the print methods). Lets you f.ex compile debug with trace log level and release with info/warn, and set different log levels for file/terminal (io is expensive)
| #include "pid_controller_dp/pid_controller.hpp" | ||
| #include "pid_controller_dp/pid_controller_utils.hpp" | ||
|
|
||
| void print_eta(const types::Eta& eta) { |
There was a problem hiding this comment.
For all these printing utils, consider checking out #include <spdlog/fmt/ostr.h> and/or overloading << and/or adding custom fmt:: formatters to the vortex-utils lib, would make things much neater
| bool killswitch_on_; | ||
|
|
||
| std::string software_mode_; | ||
|
|
There was a problem hiding this comment.
probably applies to more than just this pr / package, but dealing with string-representation for stuff like this can get really annoying. if you need a string-rep at any point, i'd suggest converting to an enum (magic-enum f.ex) as early as possible in the chain
| // calculate pid control | ||
| types::Vector6d tau = | ||
| pid_controller_.calculate_tau(eta_, eta_d_, nu_, eta_dot_d_); | ||
| pid_controller_.calculate_tau(eta_body_, eta_d_body_, nu_, nu_d_body_); |
There was a problem hiding this comment.
been thinking about the calculate_tau interface for a bit, don't have anything definite here, but, some food for thought:
I think it could be very easy for someone to accidentally pass state/desired in different frames, but I also don't see an easy way to enforce this, without wrapping eta/nu in some POD with a field for frame definitions. Could be mitigated by letting calculate_tau just take errors, but then you're shifting a bit of a burden onto the user-side.
| return eta - eta_d; | ||
| } |
There was a problem hiding this comment.
been a while since i've dealt with any of this, but would you want to negate the quat part if the scalar error < 0? like to ensure shortest path
There was a problem hiding this comment.
If not, then I guess you don't need to wrap this, just use the - overload directly wherever needed
| return vortex::utils::math::clamp_values(values, min_val, max_val); | ||
| } |
There was a problem hiding this comment.
could also just call this directly instead of wrapping it?
| types::Matrix6d Kp_; | ||
| types::Matrix6d Ki_; | ||
| types::Matrix6d Kd_; | ||
| types::Vector7d integral_; |
There was a problem hiding this comment.
is this consistent? as in like, accumulating error in an overrepresentation (by 1 dim), instead of first transforming to 6d with J then keeping the integration 6d?
There was a problem hiding this comment.
i guess in either case it would be nice to keep the integral 6d, so the anti-windup makes physical sense and everythings easier to reason with?
b064f9f to
2d71411
Compare
Goal: correctly implement and validate the existing quaternion-based DP controller
Completed work
Known issue
rqt_reconfiguretool, the system receives the correct value, but all other gains are immediately reset to 0 in the controller's internal stateTODO