Skip to content

Commit a36390e

Browse files
authored
Merge pull request #108 from ModiaSim/mo_animation_dict
New function get_animationHistory(..)
2 parents d835812 + 22dedf5 commit a36390e

File tree

9 files changed

+152
-10
lines changed

9 files changed

+152
-10
lines changed

Project.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
authors = ["Andrea Neumayr <[email protected]>", "Martin Otter <[email protected]>", "Gerhard Hippmann <[email protected]>"]
22
name = "Modia3D"
33
uuid = "07f2c1e0-90b0-56cf-bda7-b44b56e34eed"
4-
version = "0.10.2"
4+
version = "0.10.3-dev"
55

66
[compat]
77
Colors = "0.12, 0.11, 0.10"

src/Composition/assignObjects.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ end
5555

5656

5757
function fillVisuElements!(scene::Scene, obj::Object3D, world::Object3D)
58-
if scene.options.enableVisualization || scene.exportAnimation
58+
if scene.options.enableVisualization || scene.provideAnimationData
5959
if isNotCoordinateSystem(obj) && obj.visualizeFrame != Modia3D.False &&
6060
((scene.options.visualizeFrames && obj.visualizeFrame == Modia3D.Inherited) || obj.visualizeFrame == Modia3D.True)
6161
name = Symbol(obj.path, ".", "visualizationFrame")

src/Composition/dynamics.jl

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -368,6 +368,7 @@ function computeGeneralizedForces!(mbs::MultibodyData{F,TimeType}, _leq)::Multib
368368
forceElements = scene.forceElements
369369
visualize = scene.visualize # && sim.model.visualiz
370370
exportAnimation = scene.exportAnimation
371+
provideAnimationData = scene.provideAnimationData
371372

372373
if isTerminal #if Modia.isTerminalOfAllSegments(sim)
373374
TimerOutputs.@timeit instantiatedModel.timer "Modia3D_4 isTerminal" begin
@@ -467,7 +468,7 @@ function computeGeneralizedForces!(mbs::MultibodyData{F,TimeType}, _leq)::Multib
467468
elseif leq_mode == -2
468469
# Compute only terms needed at a communication point (currently: Only visualization + export animation)
469470
TimerOutputs.@timeit instantiatedModel.timer "Modia3D_3" begin
470-
if storeResult && !isTerminal && (visualize || exportAnimation)
471+
if storeResult && !isTerminal && (visualize || provideAnimationData)
471472
if abs(instantiatedModel.options.startTime + scene.outputCounter*instantiatedModel.options.interval - time) < 1.0e-6*(abs(time) + 1.0)
472473
# Visualize at a communication point
473474
scene.outputCounter += 1
@@ -497,8 +498,8 @@ function computeGeneralizedForces!(mbs::MultibodyData{F,TimeType}, _leq)::Multib
497498
Modia3D.visualize!(Modia3D.renderer[1], time)
498499
end
499500
end
500-
if exportAnimation
501-
TimerOutputs.@timeit instantiatedModel.timer "Modia3D_3 exportAnimation" begin
501+
if provideAnimationData
502+
TimerOutputs.@timeit instantiatedModel.timer "Modia3D_3 provideAnimationData" begin
502503
objectData = []
503504
for obj in scene.allVisuElements
504505
pos = Modia3D.convertToFloat64(obj.r_abs)

src/Composition/scene.jl

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -213,6 +213,7 @@ struct SceneOptions{F <: Modia3D.VarFloatType}
213213
### Animation and Visualization ###
214214
enableVisualization::Bool # = true, if online animation is enabled
215215
animationFile::Union{Nothing,String} # path&name of animation file
216+
provideAnimationHistory::Bool # = true, if animationDict shall be provided
216217
visualizeFrames::Bool # = true, if all frames shall be visualized
217218
visualizeBoundingBox::Bool # = true, if AABB's are visualized
218219
visualizeContactPoints::Bool # = true, if contact points shall be visualized
@@ -238,6 +239,7 @@ struct SceneOptions{F <: Modia3D.VarFloatType}
238239
gap = 0.001,
239240
enableVisualization = true,
240241
animationFile = nothing,
242+
provideAnimationHistory = false,
241243
visualizeFrames = false,
242244
visualizeBoundingBox = false,
243245
visualizeContactPoints = false,
@@ -271,6 +273,7 @@ struct SceneOptions{F <: Modia3D.VarFloatType}
271273
gap,
272274
enableVisualization,
273275
animationFile,
276+
provideAnimationHistory,
274277
visualizeFrames,
275278
visualizeBoundingBox,
276279
visualizeContactPoints,
@@ -315,6 +318,7 @@ Defines global properties of the system, such as the gravity field. Exactly one
315318
| `gravityField` | UniformGravity(g=9.81, n=[0,-1,0]) |
316319
| `enableVisualization` | true |
317320
| `animationFile` | nothing (e.g. animationFile = "animation.json") |
321+
| `provideAnimationHistory` | false |
318322
| `enableContactDetection` | true |
319323
| `elasticContactReductionFactor` | 1.0 (> 0.0, <= 1.0) |
320324
| `maximumContactDamping` | 2000.0 |
@@ -423,10 +427,11 @@ mutable struct Scene{F <: Modia3D.VarFloatType} <: Modia3D.AbstractScene
423427
AABB::Vector{Vector{Basics.BoundingBox{F}}} # Bounding boxes of elements that can collide
424428
zStartIndex::Int # start index of collision zero crossing functions
425429
forceElements::Vector{Modia3D.AbstractForceElement}
430+
provideAnimationData::Bool # = true, if animation data shall be provided
426431
exportAnimation::Bool # animation file export is enabled
427432
animation::Vector{animationStep} # animation data of visible Object3Ds
428433
outputCounter::Int64 # animation/visualization output step counter
429-
434+
430435
# Data specific to a particular joint type
431436
revolute::Vector{Revolute{F}}
432437
prismatic::Vector{Prismatic{F}}
@@ -442,6 +447,7 @@ mutable struct Scene{F <: Modia3D.VarFloatType} <: Modia3D.AbstractScene
442447
gap = 0.001,
443448
enableVisualization = true,
444449
animationFile = nothing,
450+
provideAnimationHistory = false,
445451
visualizeFrames = false,
446452
visualizeBoundingBox = false,
447453
visualizeContactPoints = false,
@@ -470,6 +476,7 @@ mutable struct Scene{F <: Modia3D.VarFloatType} <: Modia3D.AbstractScene
470476
defaultFrameLength = defaultFrameLength,
471477
enableVisualization = enableVisualization,
472478
animationFile = animationFile,
479+
provideAnimationHistory = provideAnimationHistory,
473480
visualizeFrames = visualizeFrames,
474481
visualizeBoundingBox = visualizeBoundingBox,
475482
visualizeContactPoints = visualizeContactPoints,
@@ -482,10 +489,12 @@ mutable struct Scene{F <: Modia3D.VarFloatType} <: Modia3D.AbstractScene
482489
lightLatitude = lightLatitude)
483490

484491
exportAnimation = false
492+
provideAnimationData = provideAnimationHistory
485493
if !isnothing(sceneOptions.animationFile)
486494
(base, ext) = splitext(sceneOptions.animationFile)
487495
if ext == ".json"
488496
exportAnimation = true
497+
provideAnimationData = true
489498
else
490499
@warn("Extension of animationFile=$(sceneOptions.animationFile) is not 'json'.\n-> Animation export is disabled.")
491500
end
@@ -515,6 +524,7 @@ mutable struct Scene{F <: Modia3D.VarFloatType} <: Modia3D.AbstractScene
515524
Vector{Vector{Basics.BoundingBox{F}}}[],
516525
1,
517526
Vector{Modia3D.AbstractForceElement}[],
527+
provideAnimationData,
518528
exportAnimation,
519529
Vector{animationStep}[],
520530
0,

src/Modia3D.jl

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@
44
module Modia3D
55

66
const path = dirname(dirname(@__FILE__)) # Absolute path of package directory
7-
const Version = "0.10.2"
8-
const Date = "2022-03-26"
7+
const Version = "0.10.3-dev"
8+
const Date = "2022-03-29"
99

1010
println("\nImporting Modia3D Version $Version ($Date)")
1111

@@ -40,7 +40,7 @@ import MonteCarloMeasurements
4040
import Measurements
4141
import Unitful
4242
import Modia
43-
43+
import JSON
4444

4545
@reexport using Modia
4646
const modelsPath = joinpath(Modia.path, "models")

src/ModiaInterface/_module.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ export Prismatic, PrismaticWithFlange
1919
export J123, J132, J123or132, singularRem, FreeMotion, change_rotSequenceInNextIteration!
2020
export Bushing, SpringDamperPtP
2121

22-
export buildModia3D!
22+
export buildModia3D!, get_animationHistory
2323

2424
import OrderedCollections
2525
import Modia3D

src/ModiaInterface/buildModia3D.jl

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -284,3 +284,74 @@ function getJointInfo!(model, jointInfo; path=nothing)::Nothing
284284
end
285285
return nothing
286286
end
287+
288+
289+
struct AnimationHistoryElement
290+
positions::Vector{ SVector{3,Float64}} # abs. Object3D position
291+
quaternions::Vector{SVector{4,Float64}} # abs. Object3D quaternion
292+
end
293+
294+
295+
"""
296+
animationHistory = get_animationHistory(instantiatedModel, modelPathAsString)
297+
298+
After a simulation, return an ordered dictionary of the positions and orientations of all visual Object3D
299+
present in `instantiatedModel` with respect to the `modelPathAsString` of a `Model3D(..)` model.
300+
The time vector is provided as `animationHistory["time"]`.
301+
The animation history of an Object3D with name `"a.b.c"` is provided in the form:
302+
303+
```julia
304+
animationHistory["a.b.c"] = OrdereDict{String,Any}("position" => pos,
305+
"quaternion" => quat)
306+
307+
#= Example
308+
pos = [[1.0, 2.0, 3.0],
309+
[1.1, 2.1, 3.1], # Absolute position [1.1, 2.2, 3.1] at time instant 2.
310+
[1.2, 2.2, 3.2],
311+
[1.3, 2.3, 3.3] ...]
312+
313+
quat = [[0.10, 0.20, 0.30, 0.86],
314+
[0.11, 0.21, 0.31, 0.8477], ...] # Quaternions [0.11, 0.21, 0.31, 0.8477]
315+
# to rotate from world to Object3D at time instant 2.
316+
=#
317+
```
318+
"""
319+
function get_animationHistory(instantiatedModel::Modia.SimulationModel{FloatType,TimeType},
320+
modelPathAsString::String; log::Bool = true)::Union{OrderedDict{String,Any},Nothing} where {FloatType,TimeType}
321+
322+
mbs::Modia3D.Composition.MultibodyData{FloatType,TimeType} = instantiatedModel.buildDict[modelPathAsString].mbs
323+
scene = mbs.scene
324+
allVisuElements = scene.allVisuElements
325+
animation = scene.animation
326+
animationHistory = OrderedDict{String,Any}()
327+
328+
if length(allVisuElements) > 0 && scene.provideAnimationData
329+
if log
330+
println("get_animationHistory(..): Return animation history of ", length(allVisuElements), " Object3Ds at ",
331+
length(animation), " time instants")
332+
end
333+
334+
timeVector = Float64[]
335+
for obj in animation
336+
push!(timeVector, obj.time)
337+
end
338+
animationHistory["time"] = timeVector
339+
340+
for (iobj,obj) in enumerate(allVisuElements)
341+
positions = SVector{3,Float64}[]
342+
quaternions = SVector{4,Float64}[]
343+
for animationStep in animation
344+
push!(positions , animationStep.objectData[iobj].position)
345+
push!(quaternions, animationStep.objectData[iobj].quaternion)
346+
end
347+
animationHistory[obj.path] = AnimationHistoryElement(positions, quaternions)
348+
end
349+
return animationHistory
350+
else
351+
println("\nget_animationHistory(..):\n No animation history stored during simulation.",
352+
"\n Use Object3D(feature=Scene(provideAnimationHistory=true))!!!")
353+
return nothing
354+
end
355+
end
356+
357+

test/Basic/PendulumWithBar3.jl

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
module PendulumWithBar3
2+
3+
using Modia3D
4+
import Modia3D.JSON
5+
6+
include("$(Modia3D.modelsPath)/Blocks.jl")
7+
include("$(Modia3D.modelsPath)/Electric.jl")
8+
include("$(Modia3D.modelsPath)/Rotational.jl")
9+
10+
Bar = Model(
11+
m = 0.1,
12+
Lx = 0.1,
13+
Ly = Par(value=:(0.2*Lx)),
14+
Lz = Par(value=:(0.2*Lx)),
15+
vmat1 = VisualMaterial(color="DeepSkyBlue2", transparency=0.5),
16+
vmat2 = VisualMaterial(color="Red"),
17+
frame0 = Object3D(feature=Solid(shape=Beam(axis=1, length=:Lx, width=:Ly, thickness=:Lz),
18+
massProperties=MassProperties(mass=:m),
19+
visualMaterial=:(vmat1))),
20+
frame1 = Object3D(parent=:frame0,
21+
translation=:[-Lx/2, 0.0, 0.0],
22+
feature=Visual(shape=Cylinder(axis=3, diameter=:(Ly/2), length=:(1.2*Lz)),
23+
visualMaterial=:(vmat2)))
24+
)
25+
26+
Pendulum = Model3D(
27+
m = 1.0,
28+
Lx = 0.1,
29+
world = Object3D(feature=Scene(provideAnimationHistory=true, enableVisualization=false) ),
30+
worldFrame = Object3D(parent=:world,
31+
feature=Visual(shape=CoordinateSystem(length=:(Lx/2)))),
32+
bar = Bar | Map(m=:m, Lx=:Lx),
33+
rev = RevoluteWithFlange(obj1=:world, obj2=:(bar.frame1))
34+
)
35+
36+
PendulumWithBar = Model(
37+
pendulum = Pendulum | Map(Lx=1.0, m=2.0, rev=Map(phi=Var(init=1.0))),
38+
39+
damper = Damper | Map(d=0.5),
40+
fixed = Fixed,
41+
connect = :[(damper.flange_b, pendulum.rev.flange),
42+
(damper.flange_a, fixed.flange)]
43+
)
44+
45+
pendulumWithBar = @instantiateModel(PendulumWithBar, unitless=true)
46+
47+
algorithm = Tsit5()
48+
simulate!(pendulumWithBar, algorithm, interval=0.1, stopTime=0.3)
49+
50+
# Test generation of animation history
51+
animationHistory = get_animationHistory(pendulumWithBar, "pendulum")
52+
animationHistoryJson = JSON.json(animationHistory,2)
53+
@show animationHistoryJson
54+
@show animationHistory["time"]
55+
@show animationHistory["pendulum.worldFrame"]
56+
@show animationHistory["pendulum.bar.frame0"]
57+
@show animationHistory["pendulum.bar.frame1"]
58+
59+
end

test/includeTests.jl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ Test.@testset "Basic" begin
88
include(joinpath("Basic", "AllShapes.jl"))
99
include(joinpath("Basic", "PendulumWithBar1.jl"))
1010
include(joinpath("Basic", "PendulumWithBar2.jl"))
11+
include(joinpath("Basic", "PendulumWithBar3.jl"))
1112
include(joinpath("Basic", "PendulumWithDamper.jl"))
1213
include(joinpath("Basic", "PendulumWithFix.jl"))
1314
include(joinpath("Basic", "PendulumWithParameterizedDamper.jl"))

0 commit comments

Comments
 (0)