@@ -40,7 +40,6 @@ function recursive_extract(sol, s, depth=0)
40
40
end
41
41
end
42
42
43
-
44
43
function getu (sol:: FakeSol , syms)
45
44
t-> [recursive_extract (sol, s) for s in syms]
46
45
end
@@ -75,6 +74,82 @@ function Base.getproperty(sol::FakeSol, s::Symbol)
75
74
end
76
75
end
77
76
77
+ mutable struct CacheSol
78
+ model
79
+ sol
80
+ cache:: Dict{Any, Any}
81
+ vars
82
+ last_t:: Float64
83
+ function CacheSol (model, sol)
84
+ vars = get_all_vars (model) |> unique
85
+ Main. vars = vars
86
+ values = sol (0.0 , idxs= vars)
87
+ new (model, sol, Dict (vars .=> values), vars, 0 )
88
+ end
89
+ end
90
+
91
+ function get_all_vars (model, vars = Multibody. collect_all (unknowns (model)))
92
+ for sys in model. systems
93
+ if ModelingToolkit. isframe (sys)
94
+ newvars = Multibody. ModelingToolkit. renamespace .(model. name, Multibody. Symbolics. unwrap .(vec (ori (sys). R)))
95
+ append! (vars, newvars)
96
+ else
97
+ subsys_ns = getproperty (model, sys. name)
98
+ get_all_vars (subsys_ns, vars)
99
+ end
100
+ end
101
+ vars
102
+ end
103
+
104
+
105
+ get_cached (cs:: CacheSol , t:: AbstractArray , idxs) = cs. sol (t; idxs)
106
+ function get_cached (cs:: CacheSol , t:: Real , idxs)
107
+ if ModelingToolkit. isparameter (idxs[1 ])
108
+ return cs. prob. ps[idxs]
109
+ end
110
+ if idxs isa AbstractArray{Num}
111
+ idxs = Multibody. Symbolics. unwrap .(idxs)
112
+ end
113
+ if ! haskey (cs. cache, idxs[1 ])
114
+ # Fallback for things not in cache
115
+ return cs. sol (t; idxs)
116
+ end
117
+ if t != cs. last_t
118
+ values = cs. sol (t, idxs= cs. vars)
119
+ cs. cache = Dict (cs. vars .=> values)
120
+ cs. last_t = t
121
+ end
122
+ if idxs isa Real
123
+ return cs. cache[idxs]
124
+ else
125
+ return [cs. cache[i] for i in idxs]
126
+ end
127
+ end
128
+
129
+
130
+ function getu (cs:: CacheSol , syms)
131
+ t-> get_cached (cs:: CacheSol , t. t, syms)
132
+ end
133
+
134
+ function ModelingToolkit. parameter_values (cs:: CacheSol )
135
+ ModelingToolkit. parameter_values (cs. sol)
136
+ # pars = Multibody.collect_all(parameters(cs.model))
137
+ # cs.prob.ps[pars]
138
+ end
139
+
140
+ function (cs:: CacheSol )(t; idxs= nothing )
141
+ if idxs === nothing
142
+ cs. sol (t)
143
+ else
144
+ get_cached (cs, t, idxs)
145
+ end
146
+ end
147
+
148
+ function Base. getproperty (cs:: CacheSol , s:: Symbol )
149
+ s ∈ fieldnames (typeof (cs)) && return getfield (cs, s)
150
+ return getproperty (getfield (cs, :sol ), s)
151
+ end
152
+
78
153
79
154
80
155
"""
@@ -199,11 +274,15 @@ function render(model, sol,
199
274
traces = nothing ,
200
275
display = false ,
201
276
loop = 1 ,
277
+ cache = true ,
202
278
kwargs...
203
279
)
280
+ ModelingToolkit. iscomplete (model) || (model = complete (model))
204
281
if sol isa ODEProblem
205
282
sol = FakeSol (model, sol)
206
283
return render (model, sol, 0 ; x, y, z, lookat, up, show_axis, kwargs... )[1 ]
284
+ elseif cache
285
+ sol = CacheSol (model, sol)
207
286
end
208
287
scene, fig = default_scene (x,y,z; lookat,up,show_axis)
209
288
if timevec === nothing
@@ -258,14 +337,19 @@ function render(model, sol, time::Real;
258
337
x = 2 ,
259
338
y = 0.5 ,
260
339
z = 2 ,
340
+ cache = true ,
261
341
kwargs... ,
262
342
)
263
343
344
+ ModelingToolkit. iscomplete (model) || (model = complete (model))
264
345
slider = ! (sol isa Union{ODEProblem, FakeSol})
265
346
266
347
if sol isa ODEProblem
267
348
sol = FakeSol (model, sol)
268
349
end
350
+ if cache
351
+ sol = CacheSol (model, sol)
352
+ end
269
353
270
354
# fig = Figure()
271
355
# scene = LScene(fig[1, 1]).scene
@@ -332,13 +416,11 @@ end
332
416
render! (scene, :: Any , args... ) = false # Fallback for systems that have no rendering
333
417
334
418
function render! (scene, :: typeof (Body), sys, sol, t)
335
- sol (sol. t[1 ], idxs= sys. render)== true || return true # yes, == true
419
+ render, radius, length_fraction, cylinder_radius = sol (sol. t[1 ], idxs= [sys. render, sys. radius, sys. length_fraction, sys. cylinder_radius]) .| > Float32
420
+ render== true || return true # yes, == true
336
421
color = get_color (sys, sol, :purple )
337
422
r_cm = get_fun (sol, collect (sys. r_cm))
338
423
framefun = get_frame_fun (sol, sys. frame_a)
339
- radius = sol (sol. t[1 ], idxs= sys. radius) |> Float32
340
- length_fraction = sol (sol. t[1 ], idxs= sys. length_fraction) |> Float32
341
- cylinder_radius = sol (sol. t[1 ], idxs= sys. cylinder_radius) |> Float32
342
424
thing = @lift begin # Sphere
343
425
Ta = framefun ($ t)
344
426
coords = (Ta* [r_cm ($ t); 1 ])[1 : 3 ] # TODO : make use of a proper transformation library instead of rolling own?
504
586
function render! (scene, :: typeof (BodyShape), sys, sol, t)
505
587
color = get_color (sys, sol, :purple )
506
588
shapepath = get_shape (sys, sol)
507
- Tshape = reshape (sol (sol. t[1 ], idxs= sys. shape_transform), 4 , 4 )
508
- scale = Vec3f (Float32 (sol (sol. t[1 ], idxs= sys. shape_scale))* ones (Float32, 3 ))
509
589
if isempty (shapepath)
510
590
radius = Float32 (sol (sol. t[1 ], idxs= sys. radius))
511
591
r_0a = get_fun (sol, collect (sys. frame_a. r_0))
@@ -520,7 +600,9 @@ function render!(scene, ::typeof(BodyShape), sys, sol, t)
520
600
mesh! (scene, thing; color, specular = Vec3f (1.5 ), shininess= 20f0 , diffuse= Vec3f (1 ), transparency= true )
521
601
else
522
602
T = get_frame_fun (sol, sys. frame_a)
523
-
603
+ scale = Vec3f (Float32 (sol (sol. t[1 ], idxs= sys. shape_scale))* ones (Float32, 3 ))
604
+ Tshape = reshape (sol (sol. t[1 ], idxs= sys. shape_transform), 4 , 4 )
605
+
524
606
@info " Loading shape mesh $shapepath "
525
607
shapemesh = FileIO. load (shapepath)
526
608
m = mesh! (scene, shapemesh; color, specular = Vec3f (1.5 ))
@@ -570,9 +652,7 @@ function render!(scene, ::typeof(BodyBox), sys, sol, t)
570
652
571
653
# NOTE: This draws a solid box without the hole in the middle. Cannot figure out how to render a hollow box
572
654
color = get_color (sys, sol, [1 , 0.2 , 1 , 0.9 ])
573
- width = Float32 (sol (sol. t[1 ], idxs= sys. width))
574
- height = Float32 (sol (sol. t[1 ], idxs= sys. height))
575
- length = Float32 (sol (sol. t[1 ], idxs= sys. render_length))
655
+ width, height, length = Float32 .(sol (sol. t[1 ], idxs= [sys. width, sys. height, sys. render_length]))
576
656
577
657
length_dir = sol (sol. t[1 ], idxs= collect (sys. render_length_dir))
578
658
width_dir = sol (sol. t[1 ], idxs= collect (sys. render_width_dir))
782
862
783
863
Multibody. render! (scene, :: typeof (Multibody. URDFRevolute), sys, sol, t) = false
784
864
Multibody. render! (scene, :: typeof (Multibody. URDFPrismatic), sys, sol, t) = false
865
+ Multibody. render! (scene, :: typeof (Multibody. NullJoint), sys, sol, t) = false
785
866
786
867
# ==============================================================================
787
868
# # PlanarMechanics
0 commit comments