using Pkg # Auto install packages if missing for p in ["GLMakie", "FFMPEG"] try Base.require(Symbol(p)) catch Pkg.add(p) end end using GLMakie using FFMPEG ############################################################ # SETTINGS ############################################################ const FPS = 60 const DURATION = 20 const FRAMES = FPS * DURATION const OUTFILE = "4gear_log_energy.gif" ############################################################ # GEAR SHAPE ############################################################ function gearshape(r, teeth, angle, cx, cy=0.0) pts = Point2f[] for i in 0:(teeth * 2 - 1) a = angle + i * π / teeth rr = iseven(i) ? r * 1.14 : r push!(pts, Point2f( cx + rr * cos(a), cy + rr * sin(a) )) end pts end ############################################################ # MAIN ############################################################ function main() fig = Figure(resolution=(1850, 950), fontsize=18) ######################################################## # LEFT PANEL ######################################################## ax = Axis( fig[1:2, 1], title="2 Large Gears + 2 Small Gears", aspect=DataAspect() ) limits!(ax, -15, 15, -6, 6) ######################################################## # TOP RIGHT = ENERGY LOG SCALE ######################################################## axE = Axis( fig[1, 2], title="Realtime Energy (Log Scale)", yscale = log10 ) ######################################################## # BOTTOM RIGHT = FRICTION ######################################################## axF = Axis( fig[2, 2], title="Realtime Tooth Friction" ) ######################################################## # OBSERVABLES ######################################################## t = Observable(Float64[]) eBig = Observable(Float64[]) eSmall = Observable(Float64[]) fBig = Observable(Float64[]) fSmall = Observable(Float64[]) ######################################################## # ENERGY GRAPH ######################################################## lines!(axE, t, eBig, linewidth=8, label="Large Pair Energy" ) lines!(axE, t, eSmall, linewidth=5, label="Small Pair Energy" ) axislegend(axE, position=:rt) ######################################################## # FRICTION GRAPH ######################################################## lines!(axF, t, fBig, linewidth=3, linestyle=:dash, label="Large Teeth Friction" ) lines!(axF, t, fSmall, linewidth=3, linestyle=:dot, label="Small Teeth Friction" ) axislegend(axF, position=:rb) ######################################################## # GEARS ######################################################## big1 = Observable(gearshape(2.5, 18, 0.0, -10)) big2 = Observable(gearshape(2.5, 18, 0.0, -5.0)) small1 = Observable(gearshape(1.25, 10, 0.0, 6.0)) small2 = Observable(gearshape(1.25, 10, 0.0, 8.7)) poly!(ax, big1) poly!(ax, big2) poly!(ax, small1) poly!(ax, small2) display(fig) ######################################################## # RECORD ######################################################## println("Rendering MP4...") record(fig, OUTFILE, 1:FRAMES; framerate=FPS) do i tt = i / FPS #################################################### # SPEEDS #################################################### ω_big = exp(-0.01 * tt) ω_small = 2.45 * exp(-0.03 * tt) θ1 = tt * ω_big θ2 = -tt * ω_big θ3 = tt * ω_small θ4 = -tt * ω_small #################################################### # UPDATE GEARS #################################################### big1[] = gearshape(2.5, 18, θ1, -10) big2[] = gearshape(2.5, 18, θ2, -5.0) small1[] = gearshape(1.25, 10, θ3, 6.0) small2[] = gearshape(1.25, 10, θ4, 8.7) #################################################### # ENERGY #################################################### I_big = 2.5^2 I_small = 1.25^2 E_big = 2 * 0.5 * I_big * ω_big^2 E_small = 2 * 0.5 * I_small * ω_small^2 # avoid log(0) E_big = max(E_big, 1e-6) E_small = max(E_small, 1e-6) #################################################### # FRICTION #################################################### FR_big = abs(sin(tt * 1.4)) * 0.10 FR_small = abs(cos(tt * 2.2)) * 0.08 #################################################### # PUSH #################################################### push!(t[], tt) push!(eBig[], E_big) push!(eSmall[], E_small) push!(fBig[], FR_big) push!(fSmall[], FR_small) #################################################### # REFRESH #################################################### notify(t) notify(eBig) notify(eSmall) notify(fBig) notify(fSmall) autolimits!(axE) autolimits!(axF) end println("Saved => $OUTFILE") println("Press ENTER to close") readline() end main()