Last active
April 28, 2017 16:48
-
-
Save cormullion/f2b2d7504eb906342ec658317cd0aa2a to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env julia | |
# inspired by http://stackoverflow.com/questions/40031913/simulate-a-bouncing-ball | |
# and the inspired Chris Rackauckas | |
using DifferentialEquations, ParameterizedFunctions, NLsolve, Luxor | |
f = @ode_def BallBounce begin | |
dy = v | |
dv = -g | |
end g=9.81 | |
function event_f(t, u) # Event when event_f(t, u, k) == 0 | |
u[1] | |
end | |
function apply_event!(u,cache) | |
u[2] = -u[2] - 3.5 | |
end | |
# You put these functions together to build the callback using the macros: | |
function condition(t,u,integrator) # Event when event_f(t,u) == 0 | |
u[1] | |
end | |
function affect!(integrator) | |
integrator.u[2] = -integrator.u[2] | |
end | |
cb = ContinuousCallback(condition, affect!) | |
#Now you solve as usual. You define the ODEProblem using f and the initial condition, and | |
#you call solve on a timespan. The only thing extra is you pass the callback along with the | |
#solver: | |
u0 = [30.0,0.0] | |
tspan = (0.0,15.0) | |
prob = ODEProblem(f,u0,tspan) | |
sol = solve(prob, Tsit5(), callback=cb) | |
# create animation | |
width, height = 300, 300 | |
ballradius = 20 | |
ground = 100 | |
demomovie = Movie(width, height, "test", 1:100) | |
function backdrop_f(scene::Scene, framenumber) | |
background("skyblue") | |
sethue("darkgreen") | |
box(Point(-width/2, ground), Point(width/2, height/2), :fill) | |
end | |
function frame_f(scene::Scene, framenumber) | |
ballsize = 10 | |
yvals = sol(rescale(framenumber, 0, scene.movie.movieframerange.stop, 0, 15)) | |
ypos = rescale(yvals[1], 0, 50, ground - ballradius, -height/2) | |
xpos = rescale(framenumber, 0, scene.movie.movieframerange.stop, -width/2, width/2) | |
translate(xpos, ypos + 1.5ballsize) | |
juliacircles(ballsize) | |
end | |
Luxor.animate(demomovie, [Scene(demomovie, backdrop_f), Scene(demomovie, frame_f)], framerate=20, creategif=true) |
Author
cormullion
commented
Mar 29, 2017
•
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment