# import Pkg; Pkg.update
# import Pkg; Pkg.add("ParameterizedFunctions")
# Pkg.add("PyDSTool")
# Pkg.add("Dierckx")
# import Pkg; Pkg.add("ParameterizedFunctions")
using Dierckx
using ParameterizedFunctions
# using PyDSTool
using Distributions, Compat
using StatsBase
using MultivariateStats
using StaticArrays, BenchmarkTools
using DifferentialEquations
using LinearAlgebra
using Plots
# import Pkg; Pkg.add("ImageView")
using Images
# using TestImages, Colors
# import Pkg; Pkg.add("PyPlot")
using Random
# import Pkg; Pkg.add("ODE")
using ODE
rng = MersenneTwister(1234);
$e$ matrix exponential $$ \dot{y}=A y =Ae^x $$ $$ t= n\delta t $$ $$ x_n= e^{A \delta t} x(n-1)$$
True System:
$$\dot{x}=F (x;\alpha)$$$$x(0)=x_0$$$$y_n=Hx_n+\xi$$$H$ incidence matrix $$H x_n= \begin{pmatrix} 1 & 0 & 0 & 0 \\ 0 & 0 & 1 & 0 \end {pmatrix} \begin{pmatrix} \theta_1 \\ \omega_1 \\ \theta_2 \\ \omega_2 \end {pmatrix}$$ $$J= \sum_{n=1}^{N} \frac{1}{2} [y_n-z_n]^2+ \lambda_n^T [z_n-Az_{n-1}]$$
$\Sigma_{n n}$ information matrix
Forward: $$\Sigma_{n+1,n+1}=A \Sigma_{n n}A_n^{T} $$ Backward: $$J_{nn}=A_n^{T}J_{n+1,n+1} A_n$$
State Estimation: $$x_n=x_n+\Sigma_{nn}(\Sigma_nn+R)^{-1}(y_n-x_n)$$ Hessian of J: $$\Sigma_{nn}=R^{-1}+\Sigma_{nn}^{-1}$$ $$J_{nn}=J_R+J_{nn}$$
# Differential equations describing the system
function double_pendulum(du,u,p,t)
# du = derivatives
# u = variables
# p = parameters
# t = time variable
m1 = p[1];
m2 = p[2];
L1 = p[3];
L2 = p[4];
g = p[5];
c = cos(u[1]-u[3]); # intermediate variables
s = sin(u[1]-u[3]); # intermediate variables
du[1] = u[2]; # d(theta 1)
du[2] = ( m2*g*sin(u[3])*c - m2*s*(L1*c*u[2]^2 + L2*u[4]^2) - (m1+m2)*g*sin(u[1]) ) /( L1 *(m1+m2*s^2) );
du[3] = u[4]; # d(theta 2)
du[4] = ((m1+m2)*(L1*u[2]^2*s - g*sin(u[3]) + g*sin(u[1])*c) + m2*L2*u[4]^2*s*c) / (L2 * (m1 + m2*s^2));
end
println("linearized simulation with uncertainty propagation")
function DoPeLDM( par,dt )
# UNTITLED Summary of this function goes here
# Detailed explanation goes here
m1 = par[1] #First mass
m2 = par[3] #Second mass
l1 = par[2] #First length
l2 = par[4] #Second length
g = par[5] #meters/sec^2
p1 = (m1+m2)*l1*l1
p2 = m2*l2*l2
p3 = m2*l1*m2
p4 = (m1+m2)*l1
p5=m2*l2
LHS = [p1 p3; p3 p2];
RHS = -[p4*g 0; 0 p5*g];
Jac = inv(LHS)*RHS;
A = [ 0 1 0 0;
Jac[1,1] 0 Jac[1,2] 0;
0 0 0 1;
Jac[2,1] 0 Jac[2,2] 0];
TL = exp(A*dt);
return TL
end
function DoPeLDMForward(xl0,Cii,TLM,nsteps)
xl=xl0
solution=zeros(4,nsteps)
for i in 1:nsteps
xl = TLM*xl
Cii = TLM*Cii*TLM
solution[1,i]=xl[1] # phi1
solution[2,i]=xl[2] # dtphi1
solution[3,i]=xl[3] # phi2
solution[4,i]=xl[4] # dtphi2
end
return solution,Cii
end
# linSol,Cii= DoPeLDMForward(xl0,C00,TLM,length(sol.t))
function plotSolution(sol,linSol,par)
# Extract the variables from the solution
L1 = par[2] #First length
L2 = par[4] #Second length
tm = sol.t;
# Mapping from polar to Cartesian
x1_u = L1 *sin.(sol[1,:]); # First Pendulum
y1_u = -L1 *cos.(sol[1,:]);
x2_u = x1_u + L2*sin.(sol[3,:]); # Second Pendulum
y2_u = y1_u - L2*cos.(sol[3,:]);
x1_u1 = L1 *sin.(linSol[1,:]); # First Pendulum
y1_u1 = -L1 *cos.(linSol[1,:]);
x2_u1 = x1_u1 + L2*sin.(linSol[3,:]); # Second Pendulum
y2_u1 = y1_u1 - L2*cos.(linSol[3,:]);
L = L1 + L2;
axis_lim = L*1.2; # defining the limits of the axes
anim = Animation()
i=1
extrasteps=10
for j in 1:extrasteps
str = string("Time = ", round(tm[i],digits=1), " sec");
plot([0,x1_u1[i]], [0,y1_u1[i]],size=(400,300),markersize = 10, markershape = :circle,label ="Fitted",axis = [],color = :orange);
plot!([x1_u1[i],x2_u1[i]], [y1_u1[i],y2_u1[i]],markersize = 10, markershape = :circle,label ="",title = str, title_location = :left, aspect_ratio = :equal,color = :orange);
plot!([0,x1_u[i]], [0,y1_u[i]],size=(400,300),xlim=(-axis_lim,axis_lim),ylim=(-axis_lim,1),markersize = 10, markershape = :circle,label ="Real",axis = [],color = :blue);
plot!([x1_u[i],x2_u[i]], [y1_u[i],y2_u[i]],markersize = 10, markershape = :circle,label ="",title = str, title_location = :left, aspect_ratio = :equal,color = :blue);
frame(anim)
end
ev=10
laststep=0
for i =1:ev:length(sol.t)
str = string("Time = ", round(tm[i],digits=1), " sec");
plot([0,x1_u1[i]], [0,y1_u1[i]],size=(400,300),markersize = 10, markershape = :circle,label ="Fitted",axis = [],color = :orange);
plot!([x1_u1[i],x2_u1[i]], [y1_u1[i],y2_u1[i]],markersize = 10, markershape = :circle,label ="",title = str, title_location = :left, aspect_ratio = :equal,color = :orange);
plot!([0,x1_u[i]], [0,y1_u[i]],size=(400,300),xlim=(-axis_lim,axis_lim),ylim=(-axis_lim,1),markersize = 10, markershape = :circle,label ="Real",axis = [],color = :blue);
plot!([x1_u[i],x2_u[i]], [y1_u[i],y2_u[i]],markersize = 10, markershape = :circle,label ="",title = str, title_location = :left, aspect_ratio = :equal,color = :blue);
if i > 9*ev
plot!([x2_u[i-3*ev:i]], [y2_u[i-3*ev:i]] ,alpha = 0.15,linewidth = 2, color = :blue,label ="");
plot!([x2_u[i-5*ev:i-3*ev]], [y2_u[i-5*ev:i-3*ev]],alpha = 0.08,linewidth = 2, color = :blue,label ="");
plot!([x2_u[i-7*ev:i-5*ev]], [y2_u[i-7*ev:i-5*ev]],alpha = 0.04,linewidth = 2, color = :blue, label ="");
plot!([x2_u[i-9*ev:i-7*ev]], [y2_u[i-9*ev:i-7*ev]],alpha = 0.01,linewidth = 2, color = :blue, label="");
plot!([x2_u1[i-3*ev:i]], [y2_u1[i-3*ev:i]],alpha = 0.15,linewidth = 2, color = :orange,label ="");
plot!([x2_u1[i-5*ev:i-3*ev]], [y2_u1[i-5*ev:i-3*ev]],alpha = 0.08,linewidth = 2, color = :orange,label ="");
plot!([x2_u1[i-7*ev:i-5*ev]], [y2_u1[i-7*ev:i-5*ev]],alpha = 0.04,linewidth = 2, color = :orange, label ="");
plot!([x2_u1[i-9*ev:i-7*ev]], [y2_u1[i-9*ev:i-7*ev]],alpha = 0.01,linewidth = 2, color = :orange, label="");
end
laststep=i
frame(anim)
end
i=laststep
extrasteps=20
for j in 1:extrasteps
str = string("Time = ", round(tm[i],digits=1), " sec");
plot([0,x1_u1[i]], [0,y1_u1[i]],size=(400,300),markersize = 10, markershape = :circle,label ="Fitted",axis = [],color = :orange);
plot!([x1_u1[i],x2_u1[i]], [y1_u1[i],y2_u1[i]],markersize = 10, markershape = :circle,label ="",title = str, title_location = :left, aspect_ratio = :equal,color = :orange);
plot!([0,x1_u[i]], [0,y1_u[i]],size=(400,300),xlim=(-axis_lim,axis_lim),ylim=(-axis_lim,1),markersize = 10, markershape = :circle,label ="Real",axis = [],color = :blue);
plot!([x1_u[i],x2_u[i]], [y1_u[i],y2_u[i]],markersize = 10, markershape = :circle,label ="",title = str, title_location = :left, aspect_ratio = :equal,color = :blue);
if i > 9*ev
plot!([x2_u[i-3*ev:i]], [y2_u[i-3*ev:i]] ,alpha = 0.15,linewidth = 2, color = :blue,label ="");
plot!([x2_u[i-5*ev:i-3*ev]], [y2_u[i-5*ev:i-3*ev]],alpha = 0.08,linewidth = 2, color = :blue,label ="");
plot!([x2_u[i-7*ev:i-5*ev]], [y2_u[i-7*ev:i-5*ev]],alpha = 0.04,linewidth = 2, color = :blue, label ="");
plot!([x2_u[i-9*ev:i-7*ev]], [y2_u[i-9*ev:i-7*ev]],alpha = 0.01,linewidth = 2, color = :blue, label="");
plot!([x2_u1[i-3*ev:i]], [y2_u1[i-3*ev:i]],alpha = 0.15,linewidth = 2, color = :orange,label ="");
plot!([x2_u1[i-5*ev:i-3*ev]], [y2_u1[i-5*ev:i-3*ev]],alpha = 0.08,linewidth = 2, color = :orange,label ="");
plot!([x2_u1[i-7*ev:i-5*ev]], [y2_u1[i-7*ev:i-5*ev]],alpha = 0.04,linewidth = 2, color = :orange, label ="");
plot!([x2_u1[i-9*ev:i-7*ev]], [y2_u1[i-9*ev:i-7*ev]],alpha = 0.01,linewidth = 2, color = :orange, label="");
end
frame(anim)
end
return anim
end
m1 = 1; # mass of pendulum 1 (in kg)
m2 = 1; # mass of pendulum 2 (in kg)
L1 = 1; # length of pendulum 1 (in meter)
L2 = 1; # length of pendulum 2 (in meter)
g = 9.8; # gravitatioanl acceleration constant (m/s^2)
duration = 5;
dt = 0.01;
u0 = [pi/2+randn()*pi/40; 0;pi/2+randn()*pi/40; 0]; # initial conditions.
# u[1] = angle of the first pendulum
# u[2] = angular velocity of the first pendulum
# u[3] = angle of the second pendulum
# u[4] = angular velocity of the second pendulum
tfinal = duration; # Final time. Simulation time = 0 to tfinal.
# Solving the system
p = [m1; m2; L1; L2; g];
tspan = (0.0,tfinal); # Time span (limits). The actual time variable is automatically set by solve().
prob = ODEProblem(double_pendulum,u0,tspan,p);
sol = solve(prob,Vern7(),dt=dt,minstep=dt,dtmax=dt);
#sol[1,:] = u1 = Θ_1
#sol[2,:] = u2 = ω_1
#sol[3,:] = u3 = Θ_2
#sol[4,:] = u4 = ω_2
#sol.t = t = time variable. The ODE solver automatically chooses the time steps. Note that t is not uniformly spaced.
obs=zeros(length(sol.t),2)
for i in 1:length(sol.t)
obs[i,1]=sol[1,i]+randn()*pi/40;
obs[i,2]=sol[3,i]+randn()*pi/50;
obs[i,1]=sol[1,i];
obs[i,2]=sol[3,i];
end
C00 = [(2/180*pi)^2 0 0 0;
0 (2/180*pi)^2 0 0;
0 0 (2/180*pi)^2 0;
0 0 0 (2/180*pi)^2]
TLM= DoPeLDM(p,0.01)
xl0 = u0[1:4].+ pi ./20 .*randn(4,1)
Cii = C00
nsteps=length(sol.t)
linSol,Cii= DoPeLDMForward(xl0,Cii,TLM,nsteps)
println(linSol[:,end])
anim=plotSolution(sol,linSol,p)
gif(anim,fps=10)
function forwardBackward(maxIter,nsteps,xl0,TLM,C00)
Cii=C00
linSol=0
for jj in 1:maxIter
# println("It: $jj")
#forward run
xl=xl0
linSol,Cii= DoPeLDMForward(xl0,Cii,TLM,nsteps)
xl=linSol[:,end]
#Backward Run
R=C00
iR = inv(R)
#Cii=convert(Array{Float64},Cii)
Jii = inv(Cii) +iR
dxl = xl
dxl[[2,4]] .= 0
dxl[[1,3]] .= obs[end,:] - xl[[1,3]]
for i in nsteps:-1:1
dxl = TLM' *(dxl);
Jii = TLM' *Jii*TLM;
end
xl0 = xl0 + dxl;
# Cii = inv(Jii)
if(det(Jii)!=0)
Cii = inv(Jii)
else
# return linSol
end
end
return linSol
end
linSol=forwardBackward(100,length(sol.t),xl0,TLM,C00)
anim=plotSolution(sol,linSol,p)
gif(anim,fps=10)