Double Pendulum Animation with Julia

Hi all,

I saw this webpages:

https://math24.net/double-pendulum.html

https://www.myphysicslab.com/pendulum/double-pendulum-en.html

and wonder how to create the double pendulum animation with its track in Julia?

If possible 3 pendulum will be more fun…

There is a Python code on this page:

But, Python is silly and every update make old codes obsolete, so I want Julia to animate this…

1 Like

This will probably be problematic with Makie.jl as well.

2 Likes

Here are four double pendulums:

This was written in Luxor.jl, but you can use the amazing DynamicalSystems package for all kinds of chaotic and dynamic animations.

(Old) code here and here.

6 Likes

There is an example in the Plots user gallery here: Double Pendulum Problem · Plots

4 Likes

Thank you @cormullion but @BeastyBlacksmith Pendulum is faster in moving around…

Why I get an error on the first code when I use JupyterNotebook?

Capture d’écran_2022-10-27_15-57-11

Info: Precompiling OrdinaryDiffEq [1dea7af3-3e70-54e6-95c3-0bf5283fa5ed]
└ @ Base loading.jl:1423
ERROR: LoadError: TypeError: in CartesianVIndex, in T, expected T<:Tuple{Vararg{Union{VectorizationBase.NullStep, Integer}, N}}, got Type{NTuple{4, Static.StaticInt{1}}}
Stacktrace:
[1] precompile()
@ LoopVectorization ~/.julia/packages/LoopVectorization/kVenK/src/precompile.jl:52
[2] top-level scope
@ ~/.julia/packages/LoopVectorization/kVenK/src/LoopVectorization.jl:116
[3] include
@ ./Base.jl:418 [inlined]
[4] include_package_for_output(pkg::Base.PkgId, input::String, depot_path::Vector{String}, dl_load_path::Vector{String}, load_path::Vector{String}, concrete_deps::Vector{Pair{Base.PkgId, UInt64}}, source::String)
@ Base ./loading.jl:1318
[5] top-level scope
@ none:1
[6] eval
@ ./boot.jl:373 [inlined]
[7] eval(x::Expr)
@ Base.MainInclude ./client.jl:453
[8] top-level scope
@ none:1
in expression starting at /home/browni/.julia/packages/LoopVectorization/kVenK/src/LoopVectorization.jl:1
ERROR: LoadError: Failed to precompile LoopVectorization [bdcacae8-1622-11e9-2a5c-532679323890] to /home/browni/.julia/compiled/v1.7/LoopVectorization/jl_idB3MM.
Stacktrace:
[1] error(s::String)
@ Base ./error.jl:33
[2] compilecache(pkg::Base.PkgId, path::String, internal_stderr::IO, internal_stdout::IO, ignore_loaded_modules::Bool)
@ Base ./loading.jl:1466
[3] compilecache(pkg::Base.PkgId, path::String)
@ Base ./loading.jl:1410
[4] _require(pkg::Base.PkgId)
@ Base ./loading.jl:1120
[5] require(uuidkey::Base.PkgId)
@ Base ./loading.jl:1013
[6] require(into::Module, mod::Symbol)
@ Base ./loading.jl:997
[7] include(mod::Module, _path::String)
@ Base ./Base.jl:418
[8] include(x::String)
@ RecursiveFactorization ~/.julia/packages/RecursiveFactorization/jZvER/src/RecursiveFactorization.jl:1
[9] top-level scope
@ ~/.julia/packages/RecursiveFactorization/jZvER/src/RecursiveFactorization.jl:3
[10] include
@ ./Base.jl:418 [inlined]
[11] include_package_for_output(pkg::Base.PkgId, input::String, depot_path::Vector{String}, dl_load_path::Vector{String}, load_path::Vector{String}, concrete_deps::Vector{Pair{Base.PkgId, UInt64}}, source::String)
@ Base ./loading.jl:1318
[12] top-level scope
@ none:1
[13] eval
@ ./boot.jl:373 [inlined]
[14] eval(x::Expr)
@ Base.MainInclude ./client.jl:453
[15] top-level scope
@ none:1
in expression starting at /home/browni/.julia/packages/RecursiveFactorization/jZvER/src/lu.jl:1
in expression starting at /home/browni/.julia/packages/RecursiveFactorization/jZvER/src/RecursiveFactorization.jl:1
ERROR: LoadError: Failed to precompile RecursiveFactorization [f2c3362d-daeb-58d1-803e-2bc74f2840b4] to /home/browni/.julia/compiled/v1.7/RecursiveFactorization/jl_50TvTX.
Stacktrace:
[1] error(s::String)
@ Base ./error.jl:33
[2] compilecache(pkg::Base.PkgId, path::String, internal_stderr::IO, internal_stdout::IO, ignore_loaded_modules::Bool)
@ Base ./loading.jl:1466
[3] compilecache(pkg::Base.PkgId, path::String)
@ Base ./loading.jl:1410
[4] _require(pkg::Base.PkgId)
@ Base ./loading.jl:1120
[5] require(uuidkey::Base.PkgId)
@ Base ./loading.jl:1013
[6] require(into::Module, mod::Symbol)
@ Base ./loading.jl:997
[7] include
@ ./Base.jl:418 [inlined]
[8] include_package_for_output(pkg::Base.PkgId, input::String, depot_path::Vector{String}, dl_load_path::Vector{String}, load_path::Vector{String}, concrete_deps::Vector{Pair{Base.PkgId, UInt64}}, source::String)
@ Base ./loading.jl:1318
[9] top-level scope
@ none:1
[10] eval
@ ./boot.jl:373 [inlined]
[11] eval(x::Expr)
@ Base.MainInclude ./client.jl:453
[12] top-level scope
@ none:1
in expression starting at /home/browni/.julia/packages/DiffEqBase/S7V8q/src/DiffEqBase.jl:1
ERROR: LoadError: Failed to precompile DiffEqBase [2b5f629d-d688-5b77-993f-72d75c75574e] to /home/browni/.julia/compiled/v1.7/DiffEqBase/jl_vPkzY4.
Stacktrace:
[1] error(s::String)
@ Base ./error.jl:33
[2] compilecache(pkg::Base.PkgId, path::String, internal_stderr::IO, internal_stdout::IO, ignore_loaded_modules::Bool)
@ Base ./loading.jl:1466
[3] compilecache(pkg::Base.PkgId, path::String)
@ Base ./loading.jl:1410
[4] _require(pkg::Base.PkgId)
@ Base ./loading.jl:1120
[5] require(uuidkey::Base.PkgId)
@ Base ./loading.jl:1013
[6] require(into::Module, mod::Symbol)
@ Base ./loading.jl:997
[7] include
@ ./Base.jl:418 [inlined]
[8] include_package_for_output(pkg::Base.PkgId, input::String, depot_path::Vector{String}, dl_load_path::Vector{String}, load_path::Vector{String}, concrete_deps::Vector{Pair{Base.PkgId, UInt64}}, source::Nothing)
@ Base ./loading.jl:1318
[9] top-level scope
@ none:1
[10] eval
@ ./boot.jl:373 [inlined]
[11] eval(x::Expr)
@ Base.MainInclude ./client.jl:453
[12] top-level scope
@ none:1
in expression starting at /home/browni/.julia/packages/OrdinaryDiffEq/QXAKd/src/OrdinaryDiffEq.jl:1

Failed to precompile OrdinaryDiffEq [1dea7af3-3e70-54e6-95c3-0bf5283fa5ed] to /home/browni/.julia/compiled/v1.7/OrdinaryDiffEq/jl_kvch8x.

Stacktrace:
** [1] error(s::String)**
** @ Base ./error.jl:33**
** [2] compilecache(pkg::Base.PkgId, path::String, internal_stderr::IO, internal_stdout::IO, ignore_loaded_modules::Bool)**
** @ Base ./loading.jl:1466**
** [3] compilecache(pkg::Base.PkgId, path::String)**
** @ Base ./loading.jl:1410**
** [4] _require(pkg::Base.PkgId)**
** @ Base ./loading.jl:1120**
** [5] require(uuidkey::Base.PkgId)**
** @ Base ./loading.jl:1013**
** [6] require(into::Module, mod::Symbol)**
** @ Base ./loading.jl:997**
** [7] eval**
** @ ./boot.jl:373 [inlined]**

True. But in the description:

The simulation uses a small term for friction, and the value of gravity is 1.62, so the pendulums behave as if they were on the moon (it’s much more relaxing than Earth gravity!:).

2 Likes

This looks like a version mismatch/ wrong compat between LoopVectorization and OrdinaryDiffEq to me. Maybe its better on julia 1.8?
Otherwise worth to open an issue with versions specified about it.

1 Like

Yes, but after see the video with Goldberg Variation, I think yours have more implicit advantages…

It works on REPL, but not on Jupyter Notebook, thanks anyway!

Since this link is popular but broken, here is the new one Double Pendulum Problem · Plots

3 Likes