Skip to content

Commit 84c6edd

Browse files
committed
Update remus100.py
1 parent d3d7bad commit 84c6edd

File tree

1 file changed

+61
-48
lines changed

1 file changed

+61
-48
lines changed

src/python_vehicle_simulator/vehicles/remus100.py

Lines changed: 61 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,8 @@
2929
n propeller revolution (rpm) ]
3030
3131
u = depthHeadingAutopilot(eta,nu,sampleTime)
32-
Simultaneously control of depth and heading using two controllers of
33-
PID type. Propeller rpm is given as a step command.
32+
Simultaneously control of depth and heading using controllers of
33+
PID and SMC ype. Propeller rpm is given as a step command.
3434
3535
u = stepInput(t) generates tail rudder, stern planes and RPM step inputs.
3636
@@ -48,7 +48,7 @@
4848
import numpy as np
4949
import math
5050
import sys
51-
from python_vehicle_simulator.lib.control import PIDpolePlacement
51+
from python_vehicle_simulator.lib.control import integralSMC
5252
from python_vehicle_simulator.lib.gnc import crossFlowDrag,forceLiftDrag,Hmtrx,m2c,gvect,ssa
5353

5454
# Class Vehicle
@@ -122,11 +122,11 @@ def __init__(
122122

123123

124124
# Actuator dynamics
125-
self.deltaMax_r = 30 * self.D2R # max rudder angle (rad)
126-
self.deltaMax_s = 30 * self.D2R # max stern plane angle (rad)
125+
self.deltaMax_r = 15 * self.D2R # max rudder angle (rad)
126+
self.deltaMax_s = 15 * self.D2R # max stern plane angle (rad)
127127
self.nMax = 1525 # max propeller revolution (rpm)
128-
self.T_delta = 1.0 # rudder/stern plane time constant (s)
129-
self.T_n = 1.0 # propeller time constant (s)
128+
self.T_delta = 0.1 # rudder/stern plane time constant (s)
129+
self.T_n = 0.1 # propeller time constant (s)
130130

131131
if r_rpm < 0.0 or r_rpm > self.nMax:
132132
sys.exit("The RPM value should be in the interval 0-%s", (self.nMax))
@@ -187,14 +187,16 @@ def __init__(
187187
self.w_pitch = math.sqrt( self.W * ( self.r_bg[2]-self.r_bb[2] ) /
188188
self.M[4][4] )
189189

190-
# Tail rudder parameters (single)
190+
S_fin = 0.00665; # fin area
191+
192+
# Tail rudder parameters
191193
self.CL_delta_r = 0.5 # rudder lift coefficient
192-
self.A_r = 2 * 0.10 * 0.05 # rudder area (m2)
194+
self.A_r = 2 * S_fin # rudder area (m2)
193195
self.x_r = -a # rudder x-position (m)
194196

195-
# Stern-plane paramaters (double)
197+
# Stern-plane parameters (double)
196198
self.CL_delta_s = 0.7 # stern-plane lift coefficient
197-
self.A_s = 2 * 0.10 * 0.05 # stern-plane area (m2)
199+
self.A_s = 2 * S_fin # stern-plane area (m2)
198200
self.x_s = -a # stern-plane z-position (m)
199201

200202
# Low-speed linear damping matrix parameters
@@ -203,30 +205,40 @@ def __init__(
203205
self.T_heave = self.T_sway # equal for for a cylinder-shaped AUV
204206
self.zeta_roll = 0.3 # relative damping ratio in roll
205207
self.zeta_pitch = 0.8 # relative damping ratio in pitch
206-
self.T_yaw = 5 # time constant in yaw (s)
208+
self.T_yaw = 1 # time constant in yaw (s)
209+
210+
# Feed forward gains (Nomoto gain parameters)
211+
self.K_nomoto = 5.0/20.0 # K_nomoto = r_max / delta_max
212+
self.T_nomoto = self.T_yaw # Time constant in yaw
207213

208-
# Heading autopilot
209-
self.wn_psi = 0.5 # PID pole placement parameters
210-
self.zeta_psi = 1
211-
self.r_max = 1 * math.pi / 180 # maximum yaw rate
212-
self.psi_d = 0 # position, velocity and acc. states
214+
# Heading autopilot reference model
215+
self.psi_d = 0 # position, velocity and acc. states
213216
self.r_d = 0
214217
self.a_d = 0
215-
self.wn_d = self.wn_psi / 5 # desired natural frequency
216-
self.zeta_d = 1 # desired realtive damping ratio
218+
self.wn_d = 0.1 # desired natural frequency
219+
self.zeta_d = 1 # desired realtive damping ratio
220+
self.r_max = 5.0 * math.pi / 180 # maximum yaw rate
221+
222+
# Heading autopilot (Equation 16.479 in Fossen 2021)
223+
# sigma = r-r_d + 2*lambda*ssa(psi-psi_d) + lambda^2 * integral(ssa(psi-psi_d))
224+
# delta = (T_nomoto * r_r_dot + r_r - K_d * sigma
225+
# - K_sigma * (sigma/phi_b)) / K_nomoto
226+
self.lam = 0.1
227+
self.phi_b = 0.1 # boundary layer thickness
228+
self.K_d = 0.5 # PID gain
229+
self.K_sigma = 0.05 # SMC switching gain
217230

218231
self.e_psi_int = 0 # yaw angle error integral state
219232

220-
221-
222233
# Depth autopilot
223-
self.wn_d_z = 1/20 # desired natural frequency, reference model
234+
self.wn_d_z = 0.02 # desired natural frequency, reference model
224235
self.Kp_z = 0.1 # heave proportional gain, outer loop
225236
self.T_z = 100.0 # heave integral gain, outer loop
226-
self.Kp_theta = 1.0 # pitch PID controller
227-
self.Kd_theta = 3.0
228-
self.Ki_theta = 0.1
229-
237+
self.Kp_theta = 5.0 # pitch PID controller
238+
self.Kd_theta = 2.0
239+
self.Ki_theta = 0.3
240+
self.K_w = 5.0 # optional heave velocity feedback gain
241+
230242
self.z_int = 0 # heave position integral state
231243
self.z_d = 0 # desired position, LP filter initial state
232244
self.theta_int = 0 # pitch angle integral state
@@ -309,13 +321,17 @@ def dynamics(self, eta, nu, u_actual, u_control, sampleTime):
309321
# Rigi-body/added mass Coriolis/centripetal matrices expressed in the CO
310322
CRB = m2c(self.MRB, nu_r)
311323
CA = m2c(self.MA, nu_r)
312-
313-
# Nonlinear quadratic velocity terms in pitch and yaw (Munk moments)
314-
# are set to zero since only linear damping is used
315-
CA[4][0] = 0
324+
325+
# CA-terms in roll, pitch and yaw can destabilize the model if quadratic
326+
# rotational damping is missing. These terms are assumed to be zero
327+
CA[4][0] = 0 # Quadratic velocity terms due to pitching
328+
CA[0][4] = 0
316329
CA[4][2] = 0
317-
CA[5][0] = 0
330+
CA[2][4] = 0
331+
CA[5][0] = 0 # Munk moment in yaw
332+
CA[0][5] = 0
318333
CA[5][1] = 0
334+
CA[1][5] = 0
319335

320336
C = CRB + CA
321337

@@ -329,9 +345,9 @@ def dynamics(self, eta, nu, u_actual, u_control, sampleTime):
329345
self.M[5][5] / self.T_yaw
330346
])
331347

332-
D[0][0] = D[0][0] * math.exp(-3*U_r) # For DOF 1,2,6 the D elements
333-
D[1][1] = D[1][1] * math.exp(-3*U_r) # go to zero at higher speeds, i.e.
334-
D[5][5] = D[5][5] * math.exp(-3*U_r) # drag and lift/drag dominate
348+
# Linear surge and sway damping
349+
D[0][0] = D[0][0] * math.exp(-3*U_r) # vanish at high speed where quadratic
350+
D[1][1] = D[1][1] * math.exp(-3*U_r) # drag and lift forces dominates
335351

336352
tau_liftdrag = forceLiftDrag(self.diam,self.S,self.CD_0,alpha,U_r)
337353
tau_crossflow = crossFlowDrag(self.L,self.diam,self.diam,nu_r)
@@ -424,6 +440,7 @@ def depthHeadingAutopilot(self, eta, nu, sampleTime):
424440
z = eta[2] # heave position (depth)
425441
theta = eta[4] # pitch angle
426442
psi = eta[5] # yaw angle
443+
w = nu[2] # heave velocity
427444
q = nu[4] # pitch rate
428445
r = nu[5] # yaw rate
429446
e_psi = psi - self.psi_d # yaw angle tracking error
@@ -446,40 +463,36 @@ def depthHeadingAutopilot(self, eta, nu, sampleTime):
446463
# PI controller
447464
theta_d = self.Kp_z * ( (z - self.z_d) + (1/self.T_z) * self.z_int )
448465
delta_s = -self.Kp_theta * ssa( theta - theta_d ) - self.Kd_theta * q \
449-
- self.Ki_theta * self.theta_int
466+
- self.Ki_theta * self.theta_int - self.K_w * w
450467

451468
# Euler's integration method (k+1)
452469
self.z_int += sampleTime * ( z - self.z_d );
453470
self.theta_int += sampleTime * ssa( theta - theta_d );
454471

455472
#######################################################################
456-
# Heading autopilot (PID controller)
473+
# Heading autopilot (SMC controller)
457474
#######################################################################
458475

459-
wn = self.wn_psi # PID natural frequency
460-
zeta = self.zeta_psi # PID natural relative damping factor
461476
wn_d = self.wn_d # reference model natural frequency
462477
zeta_d = self.zeta_d # reference model relative damping factor
463478

464-
m = self.M[5][5]
465-
d = 0
466-
k = 0
467479

468-
# PID feedback controller with 3rd-order reference model
480+
# Integral SMC with 3rd-order reference model
469481
[delta_r, self.e_psi_int, self.psi_d, self.r_d, self.a_d] = \
470-
PIDpolePlacement(
482+
integralSMC(
471483
self.e_psi_int,
472484
e_psi, e_r,
473485
self.psi_d,
474486
self.r_d,
475487
self.a_d,
476-
m,
477-
d,
478-
k,
488+
self.T_nomoto,
489+
self.K_nomoto,
479490
wn_d,
480491
zeta_d,
481-
wn,
482-
zeta,
492+
self.K_d,
493+
self.K_sigma,
494+
self.lam,
495+
self.phi_b,
483496
psi_ref,
484497
self.r_max,
485498
sampleTime

0 commit comments

Comments
 (0)