Skip to content

Commit

Permalink
move rendering to ext
Browse files Browse the repository at this point in the history
  • Loading branch information
baggepinnen committed Oct 26, 2023
1 parent 4ed4807 commit 3082eab
Show file tree
Hide file tree
Showing 11 changed files with 100 additions and 18 deletions.
8 changes: 7 additions & 1 deletion Manifest.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

julia_version = "1.10.0-beta3"
manifest_format = "2.0"
project_hash = "2722c4c20f9f37455cc8e5e8d1b1a81036c80f24"
project_hash = "214cc8fea2909c2dc41d280131bd19bf33b2b5df"

[[deps.ADTypes]]
git-tree-sha1 = "5d2e21d7b0d8c22f67483ef95ebdc39c0e6b6003"
Expand Down Expand Up @@ -183,6 +183,12 @@ weakdeps = ["IntervalSets", "StaticArrays"]
ConstructionBaseIntervalSetsExt = "IntervalSets"
ConstructionBaseStaticArraysExt = "StaticArrays"

[[deps.CoordinateTransformations]]
deps = ["LinearAlgebra", "StaticArrays"]
git-tree-sha1 = "f9d7112bfff8a19a3a4ea4e03a8e6a91fe8456bf"
uuid = "150eb455-5306-5404-9cee-2592286d6298"
version = "0.6.3"

[[deps.CpuId]]
deps = ["Markdown"]
git-tree-sha1 = "fcbb72b032692610bfbdb15018ac16a36cf2e406"
Expand Down
8 changes: 8 additions & 0 deletions Project.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,25 @@ authors = ["JuliaHub Inc."]
version = "0.1.0"

[deps]
CoordinateTransformations = "150eb455-5306-5404-9cee-2592286d6298"
DataInterpolations = "82cc6244-b520-54b8-b5a6-8a565e85f1d0"
JuliaSimCompiler = "8391cb6b-4921-5777-4e45-fd9aab8cb88d"
LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e"
ModelingToolkit = "961ee093-0014-501f-94e3-6117800e7a78"
ModelingToolkitStandardLibrary = "16a59e39-deab-5bd0-87e4-056b12336739"
Rotations = "6038ab10-8711-5258-84ad-4b1120ba62dc"

[weakdeps]
Makie = "ee78f7c6-11fb-53f2-987a-cfe4a2b5a57a"

[extensions]
Render = ["Makie"]

[compat]
ModelingToolkit = "8.30"
ModelingToolkitStandardLibrary = "2"
Rotations = "1.4"
CoordinateTransformations = "0.6"
julia = "1"

[extras]
Expand Down
4 changes: 4 additions & 0 deletions docs/Project.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
[deps]
Documenter = "e30172f5-a6a5-5a46-863b-614d45cd2de4"
GLMakie = "e9467ef8-e4e7-5192-8a1a-b1aee30e663a"
JuliaSimCompiler = "8391cb6b-4921-5777-4e45-fd9aab8cb88d"
Makie = "ee78f7c6-11fb-53f2-987a-cfe4a2b5a57a"
ModelingToolkit = "961ee093-0014-501f-94e3-6117800e7a78"
ModelingToolkitStandardLibrary = "16a59e39-deab-5bd0-87e4-056b12336739"
Multibody = "e1cad5d1-98ef-44f9-a79a-9ca4547f95b9"
OrdinaryDiffEq = "1dea7af3-3e70-54e6-95c3-0bf5283fa5ed"
Plots = "91a5bcdd-55d7-5caf-9e0b-520d859cae80"
WGLMakie = "276b4fcb-3e11-5398-bf8b-a0c2d153d008"
10 changes: 10 additions & 0 deletions docs/src/examples/pendulum.md
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,16 @@ plot(sol, idxs = joint.phi, title="Pendulum")
```
The solution `sol` can be plotted directly if the Plots package is loaded. The figure indicates that the pendulum swings back and forth without any damping. To add damping as well, we could add a `Damper` from the `ModelingToolkitStandardLibrary.Mechanical.Rotational` module to the revolute joint. We do this below

## 3d Animation
Multibody.jl supports automatic 3D rendering of mechanisms, we use this feature to illustrate the result of the simulation below:

```@example spring_mass_system
import WGLMakie
Multibody.render(model, sol; z = -5, filename = "pendulum.gif") # Use "pendulum.mp4" for a video file
```

![animation](spherical.gif)

## Adding damping
To add damping to the pendulum such that the pendulum will eventually come to rest, we add a [`Damper`](@ref) to the revolute joint. The damping coefficient is given by `d`, and the damping force is proportional to the angular velocity of the joint. To add the damper to the revolute joint, we must create the joint with the keyword argument `useAxisFlange = true`, this adds two internal flanges to the joint to which you can attach components from the `ModelingToolkitStandardLibrary.Mechanical.Rotational` module. We then connect one of the flanges of the damper to the axis flange of the joint, and the other damper flange to the support flange which is rigidly attached to the world.
```@example pendulum
Expand Down
11 changes: 11 additions & 0 deletions docs/src/examples/spherical_pendulum.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,3 +32,14 @@ sol = solve(prob, Rodas4())
plot(sol, idxs = [body.r_0...])
```


## Render
Multibody.jl supports automatic 3D rendering of mechanisms, we use this feature to illustrate the result of the simulation below:

```@example spring_mass_system
import WGLMakie
Multibody.render(model, sol; z = -5, filename = "spherical.gif") # Use "spherical.mp4" for a video file
```

![animation](spherical.gif)
13 changes: 12 additions & 1 deletion docs/src/examples/spring_damper_system.md
Original file line number Diff line number Diff line change
Expand Up @@ -73,4 +73,15 @@ plot(
This example has two parallel spring-mass parts, the first body (`body1`) is attached directly to the spring, with no joint in parallel with the spring. In this situation, we have to set `isroot=true` for `body1` to indicate that we want to use the body variables as state. The second body (`body2`) is attached to the spring with a joint in parallel with the spring, so we can use the joint variables as state, hence `isroot=false` for `body2`.


In this example we used separate springs and dampers, see also the component [`SpringDamperParallel`](@ref) which combines the two in one component.
In this example we used separate springs and dampers, see also the component [`SpringDamperParallel`](@ref) which combines the two in one component.


## Render
Multibody.jl supports automatic 3D rendering of mechanisms, we use this feature to illustrate the result of the simulation below:

```@example spring_mass_system
import WGLMakie
Multibody.render(model, sol; z = -5, filename = "springdamper.gif") # Use "springdamper.mp4" for a video file
```

![animation](springdamper.gif)
17 changes: 14 additions & 3 deletions docs/src/examples/spring_mass_system.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@ This example mirrors that of the [modelica spring-mass system](https://doc.model
using Multibody
using ModelingToolkit
using Plots
using SymbolicIR
using JuliaSimCompiler
using ModelingToolkitStandardLibrary.Mechanical.TranslationalModelica
using OrdinaryDiffEq
t = Multibody.t
Expand All @@ -19,7 +20,7 @@ world = Multibody.world
systems = @named begin
p1 = Prismatic(n = [0, -1, 0], s0 = 0.1, useAxisFlange = true)
spring1 = Translational.Spring(30, s_rel0 = 0.1)
spring1 = TranslationalModelica.Spring(c=30, s_rel0 = 0.1)
spring2 = Multibody.Spring(c = 30, s_unstretched = 0.1)
body1 = Body(m = 1, r_cm = [0, 0, 0])
bar1 = FixedTranslation(r = [0.3, 0, 0])
Expand Down Expand Up @@ -55,4 +56,14 @@ sol = solve(prob, Rodas4())
plot(sol, idxs = [body1.r_0[2], body2.r_0[2]])
```
The plot indicates that the two systems behave identically.
The plot indicates that the two systems behave identically.

## Render
Multibody.jl supports automatic 3D rendering of mechanisms, we use this feature to illustrate the result of the simulation below:

```@example spring_mass_system
import WGLMakie
Multibody.render(model, sol; z = -5, filename = "springmass.gif") # Use "springmass.mp4" for a video file
```

![animation](springmass.gif)
12 changes: 11 additions & 1 deletion docs/src/examples/three_springs.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,5 +42,15 @@ prob = ODEProblem(ssys, [], (0, 10))
sol = solve(prob, Rodas4(), u0=prob.u0 .+ 1e-1*randn(length(prob.u0)))
@assert SciMLBase.successful_retcode(sol)
plot(sol, idxs = [body1.r_0...])
Plots.plot(sol, idxs = [body1.r_0...])
```

## Render
Multibody.jl supports automatic 3D rendering of mechanisms, we use this feature to illustrate the result of the simulation below:

```@example spring_mass_system
import WGLMakie
Multibody.render(model, sol; z = -5, filename = "three_springs.gif") # Use "three_springs.mp4" for a video file
```

![animation](three_springs.gif)
2 changes: 1 addition & 1 deletion render/Project.toml → ext/Project.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
[deps]
CoordinateTransformations = "150eb455-5306-5404-9cee-2592286d6298"
GLMakie = "e9467ef8-e4e7-5192-8a1a-b1aee30e663a"
JuliaSimCompiler = "8391cb6b-4921-5777-4e45-fd9aab8cb88d"
Makie = "ee78f7c6-11fb-53f2-987a-cfe4a2b5a57a"
ModelingToolkit = "961ee093-0014-501f-94e3-6117800e7a78"
Multibody = "e1cad5d1-98ef-44f9-a79a-9ca4547f95b9"
OrdinaryDiffEq = "1dea7af3-3e70-54e6-95c3-0bf5283fa5ed"
Expand Down
29 changes: 18 additions & 11 deletions render/render.jl → ext/Render.jl
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
using GLMakie
module Render
using Makie
using Multibody
import Multibody: render, render!
using Rotations
using LinearAlgebra
using ModelingToolkit
export render

"""
get_frame(sol, frame, t)
Expand All @@ -13,6 +19,14 @@ function get_frame(sol, frame, t)
end


"get_systemtype(sys): Get the constructor of a component for dispatch purposes. This only supports components that have the `gui_metadata` property set. If no metadata is available, nothing is returned."
function get_systemtype(sys)
meta = getfield(sys, :gui_metadata)
meta === nothing && return nothing
eval(meta.type)
end


"""
scene, time = render(model, sol, t::Real; framerate = 30)
path = render(model, sol, timevec = range(sol.t[1], sol.t[end], step = 1 / framerate); framerate = 30)
Expand All @@ -32,6 +46,7 @@ function render(model, sol,
x = 0,
y = 0,
z = -10,
filename = "multibody_$(model.name).mp4",
)
if timevec === nothing
timevec = range(sol.t[1], sol.t[end], step=1/framerate)
Expand All @@ -54,7 +69,7 @@ function render(model, sol,
render!(scene, system_type, subsys, sol, t)
end

record(scene, "multibody_$(model.name).mp4", timevec; framerate) do time
record(scene, filename, timevec; framerate) do time
t[] = time
end
# end
Expand Down Expand Up @@ -243,12 +258,6 @@ function render!(scene, ::typeof(Spring), sys, sol, t)
end


"get_systemtype(sys): Get the constructor of a component for dispatch purposes. This only supports components that have the `gui_metadata` property set. If no metadata is available, nothing is returned."
function get_systemtype(sys)
meta = getfield(sys, :gui_metadata)
meta === nothing && return nothing
eval(meta.type)
end

render!(scene, ::Any, args...) = () # Fallback for systems that have no rendering

Expand All @@ -268,9 +277,6 @@ function render!(scene, ::Function, sys, sol, t, args...) # Fallback for systems
end
end




function spring_mesh(p1, p2; n_wind=6, radius=0.1f0, N=200)
phi = range(0, n_wind*2π, length=N)

Expand Down Expand Up @@ -306,4 +312,5 @@ function rot_from_line(d)
y = cross(d, x)
y = y ./ norm(y)
RotMatrix{3}([x y d])
end
end
4 changes: 4 additions & 0 deletions src/Multibody.jl
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@ import ModelingToolkitStandardLibrary.Mechanical.TranslationalModelica as Transl

export Rotational, Translational

export render
function render end
function render! end

const t = let
(@variables t)[1]
end
Expand Down

0 comments on commit 3082eab

Please sign in to comment.