Skip to content

Commit 017f80a

Browse files
committed
add path tracing option to animations
1 parent 8756b32 commit 017f80a

File tree

5 files changed

+35
-7
lines changed

5 files changed

+35
-7
lines changed

docs/src/examples/pendulum.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -225,9 +225,10 @@ sol = solve(prob, Rodas4())
225225
plot(sol, layout=4)
226226
```
227227

228+
In the animation below, we visualize the path that the origin of the pendulum tip traces by providing the tip frame in a vector of frames passed to `traces`
228229
```@example pendulum
229230
import GLMakie
230-
Multibody.render(model, sol, filename = "furuta.gif")
231+
Multibody.render(model, sol, filename = "furuta.gif", traces=[model.tip.frame_a])
231232
nothing # hide
232233
```
233234
![furuta](furuta.gif)

docs/src/rendering.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,10 @@ Many components allows the user to select with which color it is rendered. This
2424
## Rendering the world frame
2525
The display of the world frame can be turned off by setting `world.render => false` in the variable map.
2626

27+
## Tracing the path of a frame in 3D visualizations
28+
The path that a frame traces out during simulation can be visualized by passing a vector of frames to the `render` function using the `traces` keyword, e.g., `render(..., traces=[frame1, frame2])`.
29+
See the Furuta-pendulum demonstration [Going 3D](@ref) for an example of this.
30+
2731

2832
## Rendering API
2933

ext/Render.jl

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,7 @@ function render(model, sol,
129129
up = Vec3f(0,1,0),
130130
show_axis = false,
131131
timescale = 1.0,
132+
traces = nothing,
132133
kwargs...
133134
)
134135
scene, fig = default_scene(x,y,z; lookat,up,show_axis)
@@ -139,27 +140,49 @@ function render(model, sol,
139140
t = Observable(timevec[1])
140141

141142
recursive_render!(scene, complete(model), sol, t)
143+
144+
if traces !== nothing
145+
tvec = range(sol.t[1], stop=sol.t[end], length=500)
146+
for frame in traces
147+
(frame.metadata !== nothing && get(frame.metadata, :frame, false)) || error("Only frames can be traced in animations.")
148+
points = get_trans(sol, frame, tvec) |> Matrix
149+
Makie.lines!(scene, points)
150+
end
151+
end
152+
142153
fn = record(fig, filename, timevec; framerate) do time
143154
t[] = time/timescale
144155
end
145156
fn, scene, fig
146157
end
147158

148159
function render(model, sol, time::Real;
160+
traces = nothing,
161+
x = 2,
162+
y = 0.5,
163+
z = 2,
149164
kwargs...,
150165
)
151166

152167
# fig = Figure()
153168
# scene = LScene(fig[1, 1]).scene
154169
# cam3d!(scene)
155-
scene, fig = default_scene(0,0,10; kwargs...)
170+
scene, fig = default_scene(x,y,z; kwargs...)
156171
# mesh!(scene, Rect3f(Vec3f(-5, -3.6, -5), Vec3f(10, 0.1, 10)), color=:gray) # Floor
157172

158173
steps = range(sol.t[1], sol.t[end], length=3000)
159174

160175
t = Slider(fig[2, 1], range = steps, startvalue = time).value
161-
162176
recursive_render!(scene, complete(model), sol, t)
177+
178+
if traces !== nothing
179+
tvec = range(sol.t[1], stop=sol.t[end], length=500)
180+
for frame in traces
181+
(frame.metadata !== nothing && get(frame.metadata, :frame, false)) || error("Only frames can be traced in animations.")
182+
points = get_trans(sol, frame, tvec) |> Matrix
183+
Makie.lines!(scene, points)
184+
end
185+
end
163186
fig, t
164187
end
165188

src/Multibody.jl

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ export Rotational, Translational
1111
export render, render!
1212

1313
"""
14-
scene, time = render(model, sol, t::Real; framerate = 30)
14+
scene, time = render(model, sol, t::Real; framerate = 30, traces = [])
1515
path = render(model, sol, timevec = range(sol.t[1], sol.t[end], step = 1 / framerate); framerate = 30, timescale=1)
1616
1717
Create a 3D animation of a multibody system
@@ -24,6 +24,7 @@ Create a 3D animation of a multibody system
2424
- `framerate`: Number of frames per second.
2525
- `timescale`: Scaling of the time vector. This argument can be made to speed up animations (`timescale < 1`) or slow them down (`timescale > 1`). A value of `timescale = 2` will be 2x slower than real time.
2626
- `filename` controls the name and the file type of the resulting animation
27+
- `traces`: An optional array of frames to show the trace of.
2728
2829
# Camera control
2930
The following keyword arguments are available to control the camera pose:

src/orientation.jl

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -381,9 +381,8 @@ end
381381
Extract the translational part of a frame from a solution at time `t`.
382382
See also [`get_rot`](@ref), [`get_frame`](@ref), [Orientations and directions](@ref) (docs section).
383383
"""
384-
function get_trans(sol, frame, t)
385-
SVector{3}(sol(t, idxs = collect(frame.r_0)))
386-
end
384+
get_trans(sol, frame, t::Number) = SVector{3}(sol(t, idxs = collect(frame.r_0)))
385+
get_trans(sol, frame, t::AbstractArray) = sol(t, idxs = collect(frame.r_0))
387386

388387
"""
389388
T_W_F = get_frame(sol, frame, t)

0 commit comments

Comments
 (0)