-
Notifications
You must be signed in to change notification settings - Fork 26
feat/fix: PID quaternion-based DP controller #643
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
16f8668
d333822
a27998d
71df096
edcd63b
1ed1d42
98c5d57
85f9b1a
457c2af
471e32d
b4aefb9
e7cdcf9
2d71411
afab550
f1df4f7
386fd99
7c72929
9fe9af2
bf97597
d97c0f2
d69fed6
9a560f7
ae83763
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,7 +1,94 @@ | ||
| ## PID controller | ||
| # PID controller | ||
|
|
||
| The PID controller is defined | ||
|
|
||
| ```math | ||
| \tau = -J_{q}^{\dagger}(K_p \tilde{\eta} + K_d \dot{\tilde{\eta}} + K_i \int^t_0 \tilde{\eta}(\tau)d\tau) | ||
| ``` | ||
|
|
||
| where $\tau$ is the control input, $\tilde{\eta} = \eta - \eta_d$ is the pose error, $J_q$ is the quaternion based Jacobian matrix and $K_p$, $K_d$ and $K_i$ are tuning matrices. | ||
| where: | ||
|
|
||
| - $\tilde{\eta} = \eta - \eta_d$ is the pose error (7D quaternion representation), | ||
| - $J_q$ is the quaternion Jacobian (7×6), and $J_q^{\dagger}$ is its (pseudo-)inverse, | ||
| - $K_p$, $K_d$, $K_i$ are 6×6 gain matrices. | ||
|
|
||
| ## PID controller (pid_controller_dp) | ||
|
|
||
| This package implements a 6-DOF PID controller that operates on the | ||
| 6-dimensional control vector | ||
| $$\tau = [X, Y, Z, K, M, N]^T$$ | ||
| and uses a quaternion-based 7D pose representation for attitude. | ||
|
|
||
| ## Build | ||
|
|
||
|
|
||
| This package is built as part of the workspace. From the workspace root: | ||
|
|
||
| ```bash | ||
| colcon build --packages-select pid_controller_dp | ||
| ``` | ||
|
|
||
| To run tests for this package only: | ||
|
|
||
| ```bash | ||
| colcon test --packages-select pid_controller_dp && colcon test-result --verbose | ||
| ``` | ||
|
|
||
| ## Usage (ROS 2 node) | ||
|
|
||
| The package provides a node `pid_controller_node` that subscribes to pose, | ||
| twist and guidance topics and publishes wrench (tau) commands. | ||
|
|
||
|
|
||
| - `topics.pose` (type: `geometry_msgs/PoseWithCovarianceStamped`) — vehicle pose input | ||
| - `topics.twist` (type: `geometry_msgs/TwistWithCovarianceStamped`) — velocity input | ||
| - `topics.guidance.dp` (type: `vortex_msgs/ReferenceFilter`) — desired states (pose/vecocity) | ||
| - `topics.wrench_input` (type: `geometry_msgs/WrenchStamped`) — output wrench | ||
|
|
||
| Parameters expose PID gains (Kp, Ki, Kd) as per-component values which are | ||
| assembled into diagonal gain matrices inside the node. See the node source | ||
| (`src/pid_controller_ros.cpp`) for parameter names. | ||
|
|
||
| ## Examples | ||
|
|
||
| Start the node (after sourcing workspace): | ||
|
|
||
| 1. Run the simulation | ||
|
|
||
| ```bash | ||
| ros2 launch stonefish_sim simulation.launch.py scenario:=default | ||
| ``` | ||
|
|
||
| 2. Run the thrust allocation node: | ||
|
|
||
| ```bash | ||
| ros2 launch thrust_allocator_auv thrust_allocator_auv.launch.py | ||
| ``` | ||
|
|
||
| 3. To move the robot, run the joystick node | ||
|
|
||
| ```bash | ||
| ros2 launch stonefish_sim orca_sim.launch.py | ||
| ``` | ||
|
|
||
| 4. Run the controller | ||
|
|
||
| ```bash | ||
| ros2 launch pid_controller_dp pid_controller_dp.launch.py | ||
| ``` | ||
|
|
||
| Use the joy stick to move the robot. The key mappings are: | ||
|
|
||
| - B - kill | ||
| - Y - autonomous mode (reference model) | ||
| - A - manual mode | ||
|
|
||
| Note: When plotting, the axis plotted and actual command might not align since the plotting is based on the joy controller frame (`odom`), whereas the controller works on the robot frame (`body_frame`) | ||
|
|
||
| ## Tuning | ||
|
|
||
| The `rqt_reconfigure` can be used to change the controller gains. | ||
|
|
||
| ```bash | ||
| ros2 run rqt_reconfigure rqt_reconfigure | ||
| ``` |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,5 +1,20 @@ | ||
| /**: | ||
| ros__parameters: | ||
| 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: 20.0 | ||
| Kp_y: 26.0 | ||
| Kp_z: 50.0 | ||
| Kp_roll: 10.0 | ||
| Kp_pitch: 41.0 | ||
| Kp_yaw: 6.0 | ||
| Ki_x: 0.092 | ||
| Ki_y: 0.00059 | ||
| Ki_z: 0.085 | ||
| Ki_roll: 0.002 | ||
| Ki_pitch: 0.01 | ||
| Ki_yaw: 0.0003 | ||
| Kd_x: 0.001 | ||
| Kd_y: 0.0 | ||
| Kd_z: 0.0 | ||
| Kd_roll: 0.002 | ||
| Kd_pitch: 0.0 | ||
| Kd_yaw: 0.001 |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -7,6 +7,7 @@ | |
| #include <geometry_msgs/msg/twist_with_covariance_stamped.hpp> | ||
| #include <geometry_msgs/msg/wrench_stamped.hpp> | ||
| #include <nav_msgs/msg/odometry.hpp> | ||
| #include <rcl_interfaces/msg/set_parameters_result.hpp> | ||
| #include <rclcpp/rclcpp.hpp> | ||
| #include <std_msgs/msg/bool.hpp> | ||
| #include <std_msgs/msg/float64_multi_array.hpp> | ||
|
|
@@ -35,16 +36,6 @@ class PIDControllerNode : public rclcpp::Node { | |
| void operation_mode_callback( | ||
| const vortex_msgs::msg::OperationMode::SharedPtr msg); | ||
|
|
||
| // @brief Callback function for the pose topic | ||
| // @param msg: PoseWithCovarianceStamped message containing the AUV pose | ||
| void pose_callback( | ||
| const geometry_msgs::msg::PoseWithCovarianceStamped::SharedPtr msg); | ||
|
|
||
| // @brief Callback function for the twist topic | ||
| // @param msg: TwistWithCovarianceStamped message containing the AUV speed | ||
| void twist_callback( | ||
| const geometry_msgs::msg::TwistWithCovarianceStamped::SharedPtr msg); | ||
|
|
||
| // @brief Callback function for the tau publisher timer | ||
| void publish_tau(); | ||
|
|
||
|
|
@@ -64,6 +55,15 @@ class PIDControllerNode : public rclcpp::Node { | |
| void guidance_callback( | ||
| const vortex_msgs::msg::ReferenceFilter::SharedPtr msg); | ||
|
|
||
| // @brief Callback function for the odometry topic | ||
| // @param msg: Odometry message containing the AUV pose and speed | ||
| void odom_callback(const nav_msgs::msg::Odometry::SharedPtr msg); | ||
|
|
||
| // @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); | ||
|
|
||
| rclcpp::Client<vortex_msgs::srv::GetOperationMode>::SharedPtr | ||
| get_operation_mode_client_; | ||
|
|
||
|
|
@@ -74,11 +74,7 @@ class PIDControllerNode : public rclcpp::Node { | |
| rclcpp::Subscription<vortex_msgs::msg::OperationMode>::SharedPtr | ||
| operation_mode_sub_; | ||
|
|
||
| rclcpp::Subscription< | ||
| geometry_msgs::msg::PoseWithCovarianceStamped>::SharedPtr pose_sub_; | ||
|
|
||
| rclcpp::Subscription< | ||
| geometry_msgs::msg::TwistWithCovarianceStamped>::SharedPtr twist_sub_; | ||
| rclcpp::Subscription<nav_msgs::msg::Odometry>::SharedPtr odom_sub_; | ||
|
|
||
| rclcpp::Subscription<vortex_msgs::msg::ReferenceFilter>::SharedPtr | ||
| guidance_sub_; | ||
|
|
@@ -107,6 +103,8 @@ class PIDControllerNode : public rclcpp::Node { | |
|
|
||
| vortex::utils::types::Mode operation_mode_{ | ||
| vortex::utils::types::Mode::manual}; | ||
|
|
||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 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
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nvm seems to have been changed in #656 |
||
| OnSetParametersCallbackHandle::SharedPtr callback_handle_; | ||
| }; | ||
|
|
||
| #endif // PID_CONTROLLER_DP__PID_CONTROLLER_ROS_HPP_ | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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