using Dierckx
using ParameterizedFunctions
using Distributions, Compat
using StatsBase
using MultivariateStats
using StaticArrays, BenchmarkTools
using DifferentialEquations
using LinearAlgebra
using Plots
using Images
using Random
using ODE
rng = MersenneTwister(1234);
# 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
function plotSolution(sol,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,:]);
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_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_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="");
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_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="");
end
frame(anim)
end
return anim
end
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 = 10.0;
dt = 0.01;
u0 = [pi/2; 0;pi/2; 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);
sol0 = 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.
ph1 = sol0[1,:]
ph1dot = sol0[2,:]
ph2 = sol0[3,:]
ph2dot = sol0[4,:]
x = Array(sol0)'
size(x)[1]
anim=plotSolution(sol0,p)
gif(anim,fps=10)
# Measurements
H = 5:5:(size(x)[1]);
lH = length(H);
ph1_obs = ph1[H]+randn(lH,1)*5/180*pi;
ph2_obs = ph2[H]+randn(lH,1)*5/180*pi;
ph_obs = [ph1_obs ph2_obs];
# Random Ensemble Simulation
xinit_ens = u0[1:4] .+ randn(4,100) .* 5.0 ./ 180.0 .*pi
# xinit_ens = [xinit_ens; repeat(p[1:4],1,100)]
plot(ph1,ph2,label="True")
scatter!(ph1_obs,ph2_obs,label="Obs")
scatter!(xinit_ens[1,:], xinit_ens[3,:],label="Ens")
x_ens=zeros(size(x)[1],size(xinit_ens)[1],size(xinit_ens)[2])
for ens in 1:size(xinit_ens)[2]
prob = ODEProblem(double_pendulum,xinit_ens[:,ens],tspan,p);
sol=solve(prob,Vern7(),dt=dt,minstep=dt,dtmax=dt);
x = Array(sol)'
x_ens[:,:,ens] .= x;
end
size(x_ens)
H[1]
anim=Animation()
for tm in 1:size(x_ens)[1]
x_this =x_ens[tm,:,:]
plot(ph1,ph2,label="",xlims = (-3,3),ylims = (-4,6))
scatter!(x_this[1,:],x_this[3,:],label="")
frame(anim)
end
gif(anim,fps=30)
Prediction Error: $$ \delta Y= (Y-E_z) $$ Correction: $$ \delta E_z=E_z E_z^T[E_z E_z^T+R]^{-1}\delta Y $$
Empirical Adjoint: $$ \delta E_1=E_1 E_2^T[E_2 E_2^T+R]^{-1}\delta E_2 $$
$E_1 \leftarrow E_2$ using $F()$ the go back with the adjoint $$E_{\alpha}M_2$$
x_ens[H[1],:,:]
H_obs = [1 0 0 0; 0 0 1 0];
x_ens_meas = x_ens[H[1],:,:]
x = u0;
anim=Animation()
sta_upd=[]
for tm in 1:2:length(H)
plot(ph1,ph2,label="",xlims = (-2,2),ylims = (-2,4))
scatter!(x_ens_meas[1,:], x_ens_meas[3,:],label="")
frame(anim)
sta_var = x_ens_meas[1:4,:];
covstat = cov(sta_var');
sta_upd = sta_var + (covstat *H_obs') * (pinv(H_obs*covstat*H_obs' +(zeros(2,2) + I)*(2/180*pi)^2) * (ph_obs[tm,:] .- (H_obs*sta_var)))
# sta_upd = sta_var;
for ens in 1:size(sta_upd)[2]
# println(sta_upd[:,ens])
prob = ODEProblem(double_pendulum,sta_upd[:,ens],(0.0,0.1),p);
sol=solve(prob,Vern7(),saveat=0.1);
x = Array(sol)
x_ens_meas[:,ens] .= x[:,end]
end
# print(x_ens_meas[1,:])
end
gif(anim,fps=5)
x_ens
Array(sol0)
sta_upd
u0
sta_var
x
tspan = (0.0,tfinal); # Time span (limits). The actual time variable is automatically set by solve().
# prob = ODEProblem(double_pendulum,mean(sta_upd,dims=2),tspan,p);
prob = ODEProblem(double_pendulum,mean(sta_upd,dims=2),tspan,p);
sol = solve(prob,Vern7(),dt=dt,minstep=dt,dtmax=dt);
anim=plotSolution(sol0,sol,p)
gif(anim,fps=10)
using DataDrivenDiffEq
using ModelingToolkit
using DiffEqSensitivity
function pendulum(u, p, t)
x = u[2]
y = -9.81sin(u[1]) - 0.1u[2]
return [x;y]
end
u0 = [0.4π; 1.0]
tspan = (0.0, 20.0)
problem = ODEProblem(pendulum, u0, tspan)
solution = solve(problem, Tsit5(), atol = 1e-8, rtol = 1e-8, saveat = 0.001)
X = Array(solution)
DX = solution(solution.t, Val{1});
plot(X[1,:])
plot!(X[2,:])
@variables u[1:2]
h = Operation[u; u.^2; u.^3; sin.(u); cos.(u); 1]
basis = Basis(h, u)
opt = SR3(3e-1, 1.0)
Ψ = SInDy(X[:, 1:1000], DX[:, 1:1000], basis, maxiter = 10000, opt = opt, normalize = true)
sys = ODESystem(Ψ)
p = parameters(Ψ)
dudt = ODEFunction(sys)
estimator = ODEProblem(dudt, u0, tspan, p)
estimation = solve(estimator, Tsit5(), saveat = solution.t);
Xest=Array(estimation)
println(Ψ)
plot(X[1,:])
plot!(X[2,:])
plot!(Xest[1,:],linestyle = :dash)
plot!(Xest[2,:],linestyle = :dash)
# 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
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 = 20.0;
dt = 0.001;
u0 = [pi/2; 0;pi/2; 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().
problem = ODEProblem(double_pendulum,u0,tspan,p);
solution = solve(problem,Vern7(),saveat=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.
ph1 = solution[1,:]
ph1dot = solution[2,:]
ph2 = solution[3,:]
ph2dot = solution[4,:]
# anim=plotSolution(solution,p)
# gif(anim,fps=10)
solution = solve(problem, Tsit5(), saveat = dt)
X = Array(solution)
DX = solution(solution.t, Val{1});
plot(X[1,:])
plot!(X[2,:])
plot!(X[3,:])
plot!(X[4,:])
X[:, 1:length(solution.t)]
u0
DX[:, 1:length(solution.t)]
@variables u[1:4]
h = Operation[u; sin.(u); cos.(u); sin.(u.^2); cos.(u.^2); 1]
basis = Basis(h, u)
opt = SR3(3e-1, 1.0)
Ψ = SInDy(X[:, :], DX[:, :], basis, maxiter = 1000000, opt = opt, normalize = true)
println(Ψ)
sys = ODESystem(Ψ)
p = parameters(Ψ)
dudt = ODEFunction(sys)
estimator = ODEProblem(dudt, u0, tspan, p)
estimation = solve(estimator, Tsit5(), saveat = solution.t);
Xest=Array(estimation)
println(Ψ)
plot(X[1,1:10000])
plot!(X[2,1:10000])
# plot!(X[3,:])
# plot!(X[4,:])
plot!(Xest[1,1:10000],linestyle = :dash)
plot!(Xest[2,1:10000],linestyle = :dash)
# plot!(Xest[3,:],linestyle = :dash)
# plot!(Xest[4,:],linestyle = :dash)