Last active
February 6, 2019 16:04
-
-
Save oikonang/6695a21df14d757a0ee02cdc850c6d51 to your computer and use it in GitHub Desktop.
1st Simulation - Interactive
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
numpy==1.15.4 | |
scipy==1.1.0 | |
pandas==0.23.4 | |
bokeh==1.0.1 | |
matplotlib==3.0.2 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import numpy as np | |
import math | |
from numpy.linalg import inv | |
def container(x,ui): | |
''' | |
container function returns the speed U in m/s (optionally) and the | |
time derivative of the state vector: x = [ u v r x y psi p phi delta n ] for | |
a container ship L = 175 m, where | |
u = surge velocity SOG (m/s) | |
v = sway velocity SOG (m/s) | |
r = yaw velocity (rad/s) | |
x = position in x-direction (m) | |
y = position in y-direction (m) | |
psi = yaw angle (rad) | |
p = roll velocity (rad/s) | |
phi = roll angle (rad) | |
delta = actual rudder angle (rad) | |
n = actual shaft velocity (rpm) | |
ucx = current surge velocity (m/s) invoke constant current x | |
ucy = current sway velocity (m/s) invoke constant current y | |
The input vector is : | |
ui = [ delta_c n_c ]' where | |
delta_c = commanded rudder angle (rad) | |
n_c = commanded shaft velocity (rpm) | |
Reference: Son og Nomoto (1982). On the Coupled Motion of Steering and | |
Rolling of a High Speed Container Ship, Naval Architect of Ocean Engineering, | |
20: 73-83. From J.S.N.A. , Japan, Vol. 150, 1981. | |
Author: Trygve Lauvdal | |
Date: 12th May 1994 | |
Revisions: 18th July 2001 (Thor I. Fossen): added output U, changed order of x-vector | |
20th July 2001 (Thor I. Fossen): changed my = 0.000238 to my = 0.007049 | |
10th January 2019 (Angelos Ikonomakis): translated the whole script in python | |
''' | |
assert (len(x) == 12),'x-vector must have dimension 10 !' | |
assert (len(ui) == 2),'u-vector must have dimension 2 !' | |
# Normalization variables | |
L = 175 # length of ship (m) | |
#U = np.sqrt(x[0]**2 + x[1]**2) # service speed STW (m/s) | |
U = np.sqrt((x[0]-x[10])**2 + (x[1]-x[11])**2) # service speed STW (m/s) | |
Uog = np.sqrt(x[0]**2 + x[1]**2) # SOG | |
# Check service speed | |
assert (U > 0),'The ship must have speed greater than zero' | |
assert (x[9] > 0),'The propeller rpm must be greater than zero' | |
delta_max = 10; # max rudder angle (deg) | |
Ddelta_max = 5; # max rudder rate (deg/s) | |
n_max = 160; # max shaft velocity (rpm) | |
# Non-dimensional states and inputs | |
delta_c = ui[0]; | |
n_c = ui[1]/60*L/U; | |
u = (x[0]-x[10])/U; v = (x[1]-x[11])/U; | |
p = x[6]*L/U; r = x[2]*L/U; | |
phi = x[7]; psi = x[5]; | |
delta = x[8]; n = x[9]/60*L/U; | |
# Parameters, hydrodynamic derivatives and main dimensions | |
m = 0.00792; mx = 0.000238; my = 0.007049; | |
Ix = 0.0000176; alphay = 0.05; lx = 0.0313; | |
ly = 0.0313; Ix = 0.0000176; Iz = 0.000456; | |
Jx = 0.0000034; Jz = 0.000419; xG = 0; | |
B = 25.40; dF = 8.00; g = 9.81; | |
dA = 9.00; d = 8.50; nabla = 21222; | |
KM = 10.39; KB = 4.6154; AR = 33.0376; | |
Delta = 1.8219; D = 6.533; GM = 0.3/L; | |
rho = 1025; t = 0.175; T = 0.0005; | |
W = rho*g*nabla/(rho*L**2*U**2/2); | |
Xuu = -0.0004226; Xvr = -0.00311; Xrr = 0.00020; | |
Xphiphi = -0.00020; Xvv = -0.00386; | |
Kv = 0.0003026; Kr = -0.000063; Kp = -0.0000075; | |
Kphi = -0.000021; Kvvv = 0.002843; Krrr = -0.0000462; | |
Kvvr = -0.000588; Kvrr = 0.0010565; Kvvphi = -0.0012012; | |
Kvphiphi = -0.0000793; Krrphi = -0.000243; Krphiphi = 0.00003569; | |
Yv = -0.0116; Yr = 0.00242; Yp = 0; | |
Yphi = -0.000063; Yvvv = -0.109; Yrrr = 0.00177; | |
Yvvr = 0.0214; Yvrr = -0.0405; Yvvphi = 0.04605; | |
Yvphiphi = 0.00304; Yrrphi = 0.009325; Yrphiphi = -0.001368; | |
Nv = -0.0038545; Nr = -0.00222; Np = 0.000213; | |
Nphi = -0.0001424; Nvvv = 0.001492; Nrrr = -0.00229; | |
Nvvr = -0.0424; Nvrr = 0.00156; Nvvphi = -0.019058; | |
Nvphiphi = -0.0053766; Nrrphi = -0.0038592; Nrphiphi = 0.0024195; | |
kk = 0.631; epsilon = 0.921; xR = -0.5; | |
wp = 0.184; tau = 1.09; xp = -0.526; | |
cpv = 0.0; cpr = 0.0; ga = 0.088; | |
cRr = -0.156; cRrrr = -0.275; cRrrv = 1.96; | |
cRX = 0.71; aH = 0.237; zR = 0.033; | |
xH = -0.48; | |
# Masses and moments of inertia | |
m11 = (m+mx); | |
m22 = (m+my); | |
m32 = -my*ly; | |
m42 = my*alphay; | |
m33 = (Ix+Jx); | |
m44 = (Iz+Jz); | |
# Rudder saturation and dynamics | |
if np.abs(delta_c) >= delta_max*math.pi/180: | |
delta_c = np.sign(delta_c)*delta_max*math.pi/180; | |
delta_dot = delta_c - delta | |
if np.abs(delta_dot) >= Ddelta_max*math.pi/180: | |
delta_dot = np.sign(delta_dot)*Ddelta_max*math.pi/180; | |
# Shaft velocity saturation and dynamics | |
n_c = n_c*U/L; | |
n = n*U/L; | |
if np.abs(n_c) >= n_max/60: | |
n_c = np.sign(n_c)*n_max/60; | |
if n > 0.3: | |
Tm=5.65/n; | |
else: | |
Tm=18.83; | |
n_dot = 1/Tm*(n_c-n)*60; | |
# Calculation of state derivatives | |
vR = ga*v + cRr*r + cRrrr*r**3 + cRrrv*r**2*v; | |
uP = math.cos(v)*((1 - wp) + tau*((v + xp*r)**2 + cpv*v + cpr*r)); | |
J = uP*U/(n*D); | |
KT = 0.527 - 0.455*J; | |
uR = uP*epsilon*np.sqrt(1 + 8*kk*KT/(math.pi*J**2)); | |
alphaR = delta + math.atan(vR/uR); | |
FN = - ((6.13*Delta)/(Delta + 2.25))*(AR/L**2)*(uR**2 + vR**2)*math.sin(alphaR); | |
T = 2*rho*D**4/(U**2*L**2*rho)*KT*n*np.abs(n); # Thrust | |
T_real = rho*D**4*KT*n*np.abs(n); # Denormalized Thrust (surge) | |
R_real = 0.5*rho*U**2*L**2*Xuu*u**2 # Denormalized Resistance (surge) | |
# Forces and moments | |
X = Xuu*u**2 + (1-t)*T + Xvr*v*r + Xvv*v**2 + Xrr*r**2 + Xphiphi*phi**2 + \ | |
cRX*FN*math.sin(delta) + (m + my)*v*r; | |
Y = Yv*v + Yr*r + Yp*p + Yphi*phi + Yvvv*v**3 + Yrrr*r**3 + Yvvr*v**2*r + \ | |
Yvrr*v*r**2 + Yvvphi*v**2*phi + Yvphiphi*v*phi**2 + Yrrphi*r**2*phi + \ | |
Yrphiphi*r*phi**2 + (1 + aH)*FN*math.cos(delta) - (m + mx)*u*r; | |
K = Kv*v + Kr*r + Kp*p + Kphi*phi + Kvvv*v**3 + Krrr*r**3 + Kvvr*v**2*r + \ | |
Kvrr*v*r**2 + Kvvphi*v**2*phi + Kvphiphi*v*phi**2 + Krrphi*r**2*phi + \ | |
Krphiphi*r*phi**2 - (1 + aH)*zR*FN*math.cos(delta) + mx*lx*u*r - W*GM*phi; | |
N = Nv*v + Nr*r + Np*p + Nphi*phi + Nvvv*v**3 + Nrrr*r**3 + Nvvr*v**2*r + \ | |
Nvrr*v*r**2 + Nvvphi*v**2*phi + Nvphiphi*v*phi**2 + Nrrphi*r**2*phi + \ | |
Nrphiphi*r*phi**2 + (xR + aH*xH)*FN*math.cos(delta); | |
# Dimensional state derivatives xdot = [ u v r x y psi p phi delta n ]' | |
detM = m22*m33*m44-m32**2*m44-m42**2*m33; | |
xdot =np.array([ X*(U**2/L)/m11, | |
-((-m33*m44*Y+m32*m44*K+m42*m33*N)/detM)*(U**2/L), | |
((-m42*m33*Y+m32*m42*K+N*m22*m33-N*m32**2)/detM)*(U**2/L**2), | |
(math.cos(psi)*u-math.sin(psi)*math.cos(phi)*v)*U, | |
(math.sin(psi)*u+math.cos(psi)*math.cos(phi)*v)*U, | |
math.cos(phi)*r*(U/L), | |
((-m32*m44*Y+K*m22*m44-K*m42**2+m32*m42*N)/detM)*(U**2/L**2), | |
p*(U/L), | |
delta_dot, | |
n_dot, | |
0, # hardcode x-current acceleration | |
0 # hardcode y-current acceleration | |
]); | |
return xdot, U, Uog, T_real, R_real | |
def Lcontainer(x,ui,U0=7.0): | |
'''Lcontainer(x,ui,U0) returns the speed U in m/s (optionally) and the | |
time derivative of the state vector: x = [ u v r x y psi p phi delta ]' using the | |
the LINEARIZED model corresponding to the nonlinear model container.m. | |
u = surge velocity (m/s) | |
v = sway velocity (m/s) | |
r = yaw velocity (rad/s) | |
x = position in x-direction (m) | |
y = position in y-direction (m) | |
psi = yaw angle (rad) | |
p = roll velocity (rad/s) | |
phi = roll angle (rad) | |
delta = actual rudder angle (rad) | |
The inputs are : | |
Uo = service speed (optinally. Default speed U0 = 7 m/s | |
ui = commanded rudder angle (rad) | |
Reference: Son og Nomoto (1982). On the Coupled Motion of Steering and | |
Rolling of a High Speed Container Ship, Naval Architect of Ocean Engineering, | |
20: 73-83. From J.S.N.A. , Japan, Vol. 150, 1981. | |
Author: Thor I. Fossen | |
Date: 23rd July 2001 | |
Revisions: | |
''' | |
# Check of input and state dimensions | |
assert (x.shape[0] == 9),'x-vector must have dimension 9 !' | |
assert (U0 > 0),'The ship must have speed greater than zero' | |
# Normalization variables | |
rho = 1025 # water density (kg/m^3) | |
L = 175 # length of ship (m) | |
U = np.sqrt(U0**2 + x[1,0]**2) # ship speed (m/s) | |
# rudder limitations | |
delta_max = 10 # max rudder angle (deg) | |
Ddelta_max = 5 # max rudder rate (deg/s) | |
# States and inputs | |
delta_c = ui | |
v = x[1,0]; y = x[4,0]; | |
r = x[2,0]; psi = x[5,0]; | |
p = x[6,0]; phi = x[7,0]; | |
nu = np.array([[v, r, p]]).T | |
eta = np.array([[y, psi, phi]]).T | |
delta = x[8,0] | |
# Linear model using nondimensional matrices and states with dimension (see Fossen 2002): | |
# TM'inv(T) dv/dt + (U/L) TN'inv(T) v + (U/L)^2 TG'inv(T) eta = (U^2/L) T b' delta | |
T = np.diag([ 1, 1/L, 1/L]); | |
Tinv = np.diag([ 1, L, L ]); | |
M = np.array([[ 0.01497, 0.0003525, -0.0002205], | |
[ 0.0003525, 0.000875, 0], | |
[-0.0002205, 0, 0.0000210 ]]) | |
N = np.array([[ 0.012035, 0.00522, 0], | |
[ 0.0038436, 0.00243, -0.000213], | |
[-0.000314, 0.0000692, 0.0000075]]) | |
G = np.array([[ 0, 0, 0.0000704], | |
[ 0, 0, 0.0001468], | |
[ 0, 0, 0.0004966]]) | |
b = np.array([[-0.002578, 0.00126, 0.0000855]]).T | |
# Rudder saturation and dynamics | |
if np.abs(delta_c) >= delta_max*math.pi/180: | |
delta_c = np.sign(delta_c)*delta_max*math.pi/180 | |
delta_dot = delta_c - delta | |
if np.abs(delta_dot) >= Ddelta_max*math.pi/180: | |
delta_dot = np.sign(delta_dot)*Ddelta_max*math.pi/180 | |
# TM'inv(T) dv/dt + (U/L) TN'inv(T) v + (U/L)^2 TG'inv(T) eta = (U^2/L) T b' delta | |
nudot = inv(T @ M @ Tinv) @ ((U**2/L)*T@b*delta - (U/L)*T@N@Tinv@nu - (U/L)**2*T@G@Tinv@eta) | |
# Dimensional state derivatives xdot = [ u v r x y psi p phi delta ]' | |
xdot =np.array([[ 0, | |
nudot[0,0], | |
nudot[1,0], | |
math.cos(psi)*U0-math.sin(psi)*math.cos(phi)*v, | |
math.sin(psi)*U0+math.cos(psi)*math.cos(phi)*v, | |
math.cos(phi)*r, | |
nudot[2,0], | |
p, | |
delta_dot ]]).T | |
return xdot, U | |
def euler2(xdot,x,h): | |
''' | |
EULER2 Integrate a system of ordinary differential equations using | |
Euler's 2nd-order method. | |
xnext = euler2(xdot,x,h) | |
xdot - dx/dt(k) = f(x(k) | |
x - x(k) | |
xnext - x(k+1) | |
h - step size | |
Author: Thor I. Fossen | |
Date: 14th June 2001 | |
Revisions: | |
''' | |
xnext = x + h*xdot; | |
return xnext | |
def zigzag(ship,x,ui,t_final,t_rudderexecute,h,maneuver=[20,20]): | |
''' | |
ZIGZAG [t,u,v,r,x,y,psi,U] = zigzag(ship,x,ui,t_final,t_rudderexecute,h,maneuver) | |
performs the zig-zag maneuver, see ExZigZag.m | |
Inputs : | |
'ship' = ship model. Compatible with the models under .../gnc/VesselModels/ | |
x = initial state vector for ship model | |
ui = [delta,:] where delta=0 and the other values are non-zero if any | |
t_final = final simulation time | |
t_rudderexecute = time control input is activated | |
h = sampling time | |
maneuver = [rudder angle, heading angle]. Default 20-20 deg that is: maneuver = [20, 20] | |
rudder is changed to maneuver(1) when heading angle is larger than maneuver(2) | |
Outputs : | |
t = time vector | |
u,v,r,x,y,psi,U = time series | |
Author: Thor I. Fossen | |
Date: 22th July 2001 | |
Revisions: 15th July 2002, switching logic has been modified to handle arbitrarily maneuvers | |
''' | |
assert (t_final>t_rudderexecute),'t_final must be larger than t_rudderexecute'; | |
N = round(t_final/h) # number of samples | |
xout = np.zeros((N+1,9)) # memory allocation | |
print('Simulating...') | |
u_ship=ui | |
for i in range(0,N+1): | |
time = i*h; | |
psi = x[5]*180/math.pi | |
r = x[2] | |
if round(time)==t_rudderexecute: | |
u_ship[0]=maneuver[0]*math.pi/180 | |
if round(time) > t_rudderexecute: | |
if (psi>=maneuver[1] and r>0): | |
u_ship[0] = -maneuver[0]*math.pi/180 | |
elif (psi<=-maneuver[1] and r<0): | |
u_ship[0] = maneuver[0]*math.pi/180 | |
xdot,U, X, Y, K, N = container(x,ui) # ship model | |
xout[i,:] = np.hstack((time,x[0:6],U,u_ship[0])) | |
x = euler2(xdot,x,h) # Euler integration | |
# time-series | |
t = xout[:,0]; | |
u = xout[:,1]; | |
v = xout[:,2]; | |
r = xout[:,3]*180/math.pi; | |
x = xout[:,4]; | |
y = xout[:,5]; | |
psi = xout[:,6]*180/math.pi; | |
U = xout[:,7]; | |
delta_c = xout[:,8]*180/math.pi; | |
return t,u,v,r,x,y,psi,U,delta_c |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment