Skip to content

Commit 869deab

Browse files
committed
pid class
1 parent c0ca7eb commit 869deab

File tree

3 files changed

+231
-1
lines changed

3 files changed

+231
-1
lines changed

CMakeLists.txt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ set(USV_LIBS_SRC
2222
src/control/ASMC.cpp
2323
src/control/AITSMC.cpp
2424
src/control/AITSMC_NEW.cpp
25+
src/control/PID.cpp
2526
src/model/dynamic_model.cpp
2627
src/utils/ControllerUtils.cpp
2728
src/perturbances/wind_and_waves.cpp)
@@ -50,4 +51,4 @@ target_link_libraries(usv_libs Eigen3::Eigen)
5051
# GTest::gtest_main
5152
# Eigen3::Eigen)
5253
# target_include_directories(USV_Tests PRIVATE src/)
53-
# gtest_discover_tests(USV_Tests)
54+
# gtest_discover_tests(USV_Tests)

src/control/PID.cpp

Lines changed: 160 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,160 @@
1+
#include "PID.h"
2+
#include <cmath>
3+
#include <algorithm>
4+
#include <iostream>
5+
6+
PID::PID(const PIDParams &params) {
7+
this->p = params;
8+
g_u = (1 / (model.m - model.X_u_dot));
9+
g_psi = (1 / (model.Iz - model.N_r_dot));
10+
}
11+
12+
PIDParams PID::defaultParams() {
13+
PIDParams p;
14+
p.pk_u = 0.5;
15+
p.i_u = 0.2;
16+
p.d_u = 0.1;
17+
p.pk_psi = 0.5;
18+
p.i_psi = 0.2;
19+
p.d_psi = 0.1;
20+
p.tc_u = 2.0;
21+
p.tc_psi = 2;
22+
p.q_u = 3.0;
23+
p.q_psi = 3.0;
24+
p.p_u = 5.0;
25+
p.p_psi = 5.0;
26+
return p;
27+
}
28+
29+
double PID::normalize_angle(double angle_in){
30+
double angle_out = std::fmod(angle_in + M_PI, 2 * M_PI);
31+
if(angle_out < 0){
32+
angle_out += 2*M_PI;
33+
}
34+
return angle_out - M_PI;
35+
}
36+
37+
double PID::angle_dist(double ang1, double ang2){
38+
double diff = ang1 - ang2;
39+
return normalize_angle(diff);
40+
}
41+
42+
ControllerOutput PID::update(const vanttec::ControllerState &s, const PIDSetpoint &setpoint) {
43+
double Xu = -25;
44+
double Xuu = 0;
45+
if (std::abs(s.u) > 1.2) {
46+
Xu = 64.55;
47+
Xuu = -70.92;
48+
}
49+
50+
double sideslip_angle = std::asin(s.v / (0.001 + std::hypot(s.u, s.v)));
51+
sideslip_angle = 0;
52+
53+
double Nr = (-0.52) * std::hypot(s.u, s.v);
54+
double f_u = (((m - model.Y_v_dot) * s.v * s.r + (Xuu * std::abs(s.u) * s.u + Xu * s.u)) / (m - model.X_u_dot));
55+
double f_psi = (((-model.X_u_dot + model.Y_v_dot) * s.u * s.v + (model.Nrr * std::abs(s.r) * s.r + Nr * s.r)) /
56+
(Iz - model.N_r_dot));
57+
58+
double e_u = setpoint.u - s.u;
59+
60+
// Second order error (yaw rate)
61+
// double e_psi = angle_dist(setpoint.psi, s.psi);
62+
// Same but including
63+
double e_psi = angle_dist(setpoint.psi + sideslip_angle, s.psi);
64+
std::cout << "SIDESLIP: " << sideslip_angle << std::endl;
65+
// TODO: PRINT THE SIDESLIP VARIABLE, DO FURTHER DEBUGGING TO KNOW WHY EVERYTHING F'S UP WHEN THE BOAT GOES FAST
66+
67+
// First order error (heading)
68+
// double e_psi = setpoint.psi - s.r;
69+
70+
double sign_u = copysign(e_u != 0 ? 1 : 0, e_u);
71+
double sign_psi = copysign(e_psi != 0 ? 1 : 0, e_psi);
72+
73+
double edot_u = (e_u - e_u_last) / integral_step;
74+
e_u_last = e_u;
75+
double eidot_u = sign_u * std::pow(std::abs(e_u), p.q_u / p.p_u);
76+
double eidot_psi = sign_psi * std::pow(std::abs(e_psi), p.q_psi / p.p_psi);
77+
ei_u = integral_step * (eidot_u + eidot_u_last) / 2.0 + ei_u;
78+
eidot_u_last = eidot_u;
79+
ei_psi = integral_step * (eidot_psi + eidot_psi_last) / 2.0 + ei_psi;
80+
// ei_psi = std::clamp(ei_psi, -M_PI, M_PI);
81+
eidot_psi_last = eidot_psi;
82+
83+
double edot_psi = setpoint.psi_dot - s.r;
84+
e_psi_last_last = e_psi_last;
85+
e_psi_last = e_psi;
86+
87+
// TODO find how to initialize vars
88+
static int starting = 1;
89+
if(starting == 0){
90+
double e_u0 = e_u;
91+
double e_psi0 = e_psi;
92+
alpha_u = (std::pow(std::abs(e_u0),1-p.q_u/p.p_u))/(p.tc_u*(1-p.q_u/p.p_u));
93+
alpha_psi = (std::pow(std::abs(e_psi0),1-p.q_psi/p.p_psi))/(p.tc_psi*(1-p.q_psi/p.p_psi));
94+
alpha_u = 0.0001;
95+
// alpha_psi = 0.0001;
96+
alpha_psi = 0.01;
97+
beta_psi = 10.;
98+
// beta_psi = 0.;
99+
ei_u = -e_u0 / alpha_u;
100+
ei_psi = -e_psi0 / alpha_psi;
101+
if(alpha_u < 0.0001) ei_u = 0;
102+
if(alpha_psi < 0.0001) ei_psi = 0;
103+
starting = 2;
104+
}
105+
106+
double ua_u = p.pk_u*e_u + p.i_u*ei_u + p.d_u*edot_u;
107+
double ua_psi = p.pk_psi*e_psi + p.i_psi*ei_psi + p.d_psi*edot_psi;
108+
109+
double Tx = (setpoint.dot_u + (alpha_u * eidot_u) - f_u - ua_u) / g_u;
110+
111+
// Second order control output
112+
double Tz = (setpoint.dot_r + (beta_psi * edot_psi) + (alpha_psi * eidot_psi) - f_psi - ua_psi) / g_psi;
113+
114+
// First order control output
115+
// double Tz = (setpoint.dot_r + (alpha_psi * eidot_psi) - f_psi - ua_psi) / g_psi;
116+
117+
// Clamp forces
118+
Tx = std::clamp(Tx, -60.0, 73.0);
119+
Tz = std::clamp(Tz, -14.0, 14.0);
120+
121+
if(starting == 1){
122+
Tx = 0;
123+
Tz = 0;
124+
Ka_u = 0;
125+
Ka_dot_last_u = 0;
126+
127+
Ka_psi = 0;
128+
Ka_dot_last_psi = 0;
129+
130+
ei_u = -e_u / alpha_u;
131+
eidot_u_last = 0;
132+
133+
ei_psi = -e_psi / alpha_psi;
134+
eidot_psi_last = 0;
135+
// edot_psi = 0;
136+
137+
starting = 0;
138+
}
139+
140+
double port_t = (Tx / 2.0) + (Tz / B);
141+
double starboard_t = (Tx / (2.0 * c)) - (Tz / (B * c));
142+
143+
port_t = std::clamp(port_t, -60.0, 73.0) / 2.0;
144+
starboard_t = std::clamp(starboard_t, -60.0, 73.0) / 2.0;
145+
146+
ControllerOutput out{};
147+
out.left_thruster= port_t;
148+
out.right_thruster = starboard_t;
149+
150+
out.Tx = Tx;
151+
out.Tz = Tz;
152+
153+
debugData.e_u = e_u;
154+
debugData.e_psi = e_psi;
155+
debugData.ei_psi = eidot_psi;
156+
debugData.Tx = Tx;
157+
debugData.Tz = Tz;
158+
159+
return out;
160+
}

src/control/PID.h

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
#pragma once
2+
#include "datatypes.h"
3+
4+
using namespace vanttec;
5+
6+
struct PIDParams {
7+
double pk_u, i_u, d_u,
8+
pk_psi, i_psi, d_psi,
9+
tc_u,
10+
tc_psi,
11+
q_u,
12+
q_psi,
13+
p_u,
14+
p_psi;
15+
};
16+
17+
struct PIDSetpoint{
18+
double u{0}, psi{0}, psi_dot{0};
19+
double dot_u{0}, dot_r{0};
20+
};
21+
22+
struct PIDDebugData {
23+
double e_u{0}, e_psi{0};
24+
double edot_psi{0}, ei_psi{0};
25+
double s_u{0}, s_psi{0};
26+
double Ka_u{0}, Ka_psi{0};
27+
double Tx{0}, Tz{0};
28+
};
29+
30+
class PID {
31+
public:
32+
explicit PID(const PIDParams &params);
33+
34+
ControllerOutput update(const ControllerState &s, const PIDSetpoint &setpoint);
35+
36+
static PIDParams defaultParams();
37+
38+
double normalize_angle(double angle_in);
39+
double angle_dist(double ang1, double ang2);
40+
41+
[[nodiscard]] PIDDebugData getDebugData() const {
42+
return debugData;
43+
}
44+
45+
private:
46+
PIDParams p;
47+
48+
double m = 40; // Mass
49+
double Iz = 4.1;
50+
double B = 0.41;
51+
double c = 1.;
52+
53+
static constexpr double integral_step{0.01};
54+
double eidot_u_last{0}, eidot_psi_last{0};
55+
double e_u_last{0};
56+
double e_psi_last{0}, e_psi_last_last{0};
57+
58+
double alpha_u{0}, alpha_psi{0};
59+
double beta_psi{0}, gamma_psi{0};
60+
double Ka_u{0}, Ka_psi{0};
61+
double ei_u{0}, ei_psi{0};
62+
63+
double Ka_dot_last_u{0}, Ka_dot_last_psi{0};
64+
65+
PIDDebugData debugData;
66+
67+
USVModel model = USVModel::getBarcolomeo(); // TODO make this configurable
68+
double g_u{0}, g_psi{0};
69+
};

0 commit comments

Comments
 (0)