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…

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

1 Like

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.

5 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!