Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

improve spring animations #180

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions docs/src/examples/three_springs.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,9 @@ systems = @named begin
bar1 = FixedTranslation(r = [0.3, 0, 0])
bar2 = FixedTranslation(r = [0, 0, 0.3])
spring1 = Multibody.Spring(c = 20, m = 0, s_unstretched = 0.1, fixed_rotation_at_frame_b=true,
r_rel_0 = [-0.2, -0.2, 0.2], radius=0.05, num_windings=10)
spring2 = Multibody.Spring(c = 40, m = 0, s_unstretched = 0.1, color=[0,0,0.3,1])
spring3 = Multibody.Spring(c = 20, m = 0, s_unstretched = 0.1, radius=0.05, num_windings=10)
r_rel_0 = [-0.2, -0.2, 0.2], radius=0.05, num_windings=10, end_ratio=0.1)
spring2 = Multibody.Spring(c = 40, m = 0, s_unstretched = 0.1, color=[0,0,0.3,1], end_ratio=0.1)
spring3 = Multibody.Spring(c = 20, m = 0, s_unstretched = 0.1, radius=0.05, num_windings=10, end_ratio=0.1)
end
eqs = [connect(world.frame_b, bar1.frame_a)
connect(world.frame_b, bar2.frame_a)
Expand Down
24 changes: 14 additions & 10 deletions ext/Render.jl
Original file line number Diff line number Diff line change
Expand Up @@ -661,7 +661,7 @@ function render!(scene, ::typeof(BodyShape), sys, sol, t)
Makie.transform!(m, translation=r1, rotation=Q)
end
else
error("Shape $shape not supported")
error("""Shape $shape not supported, currently only supports "cylinder" and "box".""")
end
else
T = get_frame_fun(sol, sys.frame_a)
Expand Down Expand Up @@ -834,12 +834,13 @@ function render!(scene, ::Union{typeof(Spring), typeof(SpringDamperParallel)}, s
n_wind = sol(sol.t[1], idxs=sys.num_windings)
radius = sol(sol.t[1], idxs=sys.radius) |> Float32
N = round(Int, sol(sol.t[1], idxs=sys.N))
end_ratio = sol(sol.t[1], idxs=sys.end_ratio) |> Float32
thing = @lift begin
r1 = Point3f(r_0a($t))
r2 = Point3f(r_0b($t))
spring_mesh(r1,r2; n_wind, radius, N)
spring_mesh(r1,r2; n_wind, radius, N, end_ratio)
end
plot!(scene, thing; color)
plot!(scene, thing; color, transparency=true)
true
end

Expand Down Expand Up @@ -894,16 +895,18 @@ function render!(scene, ::Function, sys, sol, t, args...) # Fallback for systems
false
end

function spring_mesh(p1, p2; n_wind=6, radius=0.1f0, N=200)
function spring_mesh(p1, p2; n_wind=6, radius=0.1f0, N=200, end_ratio = 0.1)
phis = range(0, n_wind*2π, length=N)
d = p2 - p1
z = range(0, norm(d), length=N) # Correct length
dn = d ./ norm(d)
R = rot_from_line(dn)

points = map(enumerate(phis)) do (i,phi)
x = radius*cos(phi)
y = radius*sin(phi)
n_ramp = N * end_ratio
ri = i <= n_ramp ? i/n_ramp : i > N-n_ramp ? (N-i)/n_ramp : 1
x = ri*radius*cos(phi)
y = ri*radius*sin(phi)
pᵢ = Point3f(x, y, z[i])

R * pᵢ + p1
Expand Down Expand Up @@ -1041,12 +1044,13 @@ function render!(scene, ::Union{typeof(P.Spring), typeof(P.SpringDamper)}, sys,
n_wind = sol(sol.t[1], idxs=sys.num_windings)
radius = sol(sol.t[1], idxs=sys.radius) |> Float32
N = sol(sol.t[1], idxs=sys.N) |> Int
end_ratio = sol(sol.t[1], idxs=sys.end_ratio) |> Float32
thing = @lift begin
r1 = Point3f(r_0a($t)..., 0)
r2 = Point3f(r_0b($t)..., 0)
spring_mesh(r1,r2; n_wind, radius, N)
spring_mesh(r1,r2; n_wind, radius, N, end_ratio, end_ratio)
end
plot!(scene, thing; color)
plot!(scene, thing; color, transparency=true)
true
end

Expand Down Expand Up @@ -1108,8 +1112,8 @@ function render!(scene, ::typeof(Multibody.BoxVisualizer), sys, sol, t)
height = Float32(sol(sol.t[1], idxs=sys.height))
length = Float32(sol(sol.t[1], idxs=sys.length))

length_dir = sol(sol.t[1], idxs=collect(sys.render_length_dir))
width_dir = sol(sol.t[1], idxs=collect(sys.render_width_dir))
length_dir = sol(sol.t[1], idxs=collect(sys.length_direction))
width_dir = sol(sol.t[1], idxs=collect(sys.width_direction))
height_dir = normalize(cross(normalize(length_dir), normalize(width_dir)))
width_dir = normalize(cross(height_dir, length_dir))

Expand Down
4 changes: 4 additions & 0 deletions src/PlanarMechanics/components.jl
Original file line number Diff line number Diff line change
Expand Up @@ -215,6 +215,7 @@ Linear 2D translational spring
- `render = true` Render the spring in animations
- `radius = 0.1` Radius of spring when rendered
- `N = 200` Number of points in mesh when rendered
- `end_ratio = 0.0`: Ratio of the length of the spring [0, 0.5] that is rendered with decreasing radius at the ends. Set this to 0 to have uniform radius along the entire spring.

# Connectors:
- `frame_a` [Frame](@ref) Coordinate system fixed to the component with one cut-force and cut-torque
Expand All @@ -239,6 +240,7 @@ Linear 2D translational spring
render = true, [description = "Render the spring in animations"]
radius = 0.1, [description = "Radius of spring when rendered"]
N = 200, [description = "Number of points in mesh when rendered"]
end_ratio = 0.0
end

@variables begin
Expand Down Expand Up @@ -352,6 +354,7 @@ Linear 2D translational spring damper model
- `render = true` Render the spring in animations
- `radius = 0.1` Radius of spring when rendered
- `N = 200` Number of points in mesh when rendered
- `end_ratio = 0.0`: Ratio of the length of the spring that is rendered with decreasing radius at the ends.

# Connectors:
- `frame_a` [Frame](@ref) Coordinate system fixed to the component with one cut-force and cut-torque
Expand Down Expand Up @@ -379,6 +382,7 @@ Linear 2D translational spring damper model
render = true, [description = "Render the spring in animations"]
radius = 0.1, [description = "Radius of spring when rendered"]
N = 200, [description = "Number of points in mesh when rendered"]
end_ratio = 0.0
end

@variables begin
Expand Down
7 changes: 5 additions & 2 deletions src/forces.jl
Original file line number Diff line number Diff line change
Expand Up @@ -388,10 +388,11 @@ additional equations to handle the mass are removed.
- `color = [0,0,1,1]`: Color of the spring when rendered
- `radius = 0.1`: Radius of spring when rendered
- `N = 200`: Number of points in mesh when rendered. Rendering time can be reduced somewhat by reducing this number.
- `end_ratio = 0.0`: Ratio of the length of the spring [0, 0.5] that is rendered with decreasing radius at the ends. Set this to 0 to have uniform radius along the entire spring.

See also [`SpringDamperParallel`](@ref)
"""
@component function Spring(; c, name, m = 0, lengthfraction = 0.5, s_unstretched = 0, num_windings=6, color=[0,0,1,1], radius=0.1, N=200, kwargs...)
@component function Spring(; c, name, m = 0, lengthfraction = 0.5, s_unstretched = 0, num_windings=6, color=[0,0,1,1], radius=0.1, N=200, end_ratio = 0.0, kwargs...)
@named ptf = PartialTwoFrames()
@unpack frame_a, frame_b = ptf
pars = @parameters begin
Expand All @@ -401,6 +402,7 @@ See also [`SpringDamperParallel`](@ref)
bounds = (0, Inf),
]
num_windings = num_windings, [description = "Number of windings of the coil when rendered"]
end_ratio = 0.0
color[1:4] = color
radius = radius, [description = "Radius of spring when rendered"]
N = N, [description = "Number of points in mesh when rendered"]
Expand Down Expand Up @@ -501,7 +503,7 @@ f = c (s - s_{unstretched}) + d \\cdot D(s)
where `c`, `s_unstretched` and `d` are parameters, `s` is the distance between the origin of `frame_a` and the origin of `frame_b` and `D(s)` is the time derivative of `s`.
"""
@component function SpringDamperParallel(; name, c, d, s_unstretched=0,
color = [0, 0, 1, 1], radius = 0.1, N = 200, num_windings = 6, kwargs...)
color = [0, 0, 1, 1], radius = 0.1, N = 200, num_windings = 6, end_ratio = 0.0, kwargs...)
@named plf = PartialLineForce(; kwargs...)
@unpack s, f = plf

Expand All @@ -516,6 +518,7 @@ where `c`, `s_unstretched` and `d` are parameters, `s` is the distance between t
radius = radius, [description = "Radius of spring when rendered"]
N = N, [description = "Number of points in mesh when rendered"]
num_windings = num_windings, [description = "Number of windings of the coil when rendered"]
end_ratio = end_ratio
end
# pars = collect_all(pars)

Expand Down
Loading