Skip to content

Commit 4f200c3

Browse files
Merge pull request #123 from ModiaSim/gh_resultElements
Gh result elements
2 parents e93763b + 3ff5852 commit 4f200c3

File tree

15 files changed

+331
-74
lines changed

15 files changed

+331
-74
lines changed

docs/make.jl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ makedocs(
2222
"Components/Materials.md"
2323
"Components/GravityField.md"
2424
"Components/ForceElements.md"
25+
"Components/ResultElements.md"
2526
],
2627
"Functions" => "Functions.md",
2728
"Internal" => [
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
# Result Elements
2+
3+
```@meta
4+
CurrentModule = Modia3D.Composition
5+
```
6+
7+
## ContactResult
8+
9+
```@docs
10+
ContactResult
11+
```
Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
2+
"""
3+
result = ContactResult(; object1, object2, objectCoordinateRef)
4+
5+
Return a `result` providing results of elastic MPR contacts between
6+
`object1::`[`Object3D`](@ref) and `object2::`[`Object3D`](@ref).
7+
If `objectCoordinateRef::`[`Object3D`](@ref) is defined, all vector
8+
results are resolved in `objectCoordinateRef`, otherwise in world.
9+
10+
# Results
11+
12+
- `penetration` is the normal contact penetration (positive in case of contact).
13+
- `penetrationVelocity` is the normal contact penetration velocity (positive for compression).
14+
- `tangentialVelocity` is the absolute value of the tangential relative velocity.
15+
- `angularVelocity` it the absolute value of the relative angular velocity.
16+
- `normalForce` is the normal contact force (positive for pressure).
17+
- `tangentialForce` is the absolute value of the tangential contact force.
18+
- `torque` is the absolute value of the contact torque.
19+
- `positionVector` is the absolute position vector of the contact point, resolved in `objectCoordinateRef`.
20+
- `normalVector` is the unit vector in contact normal direction, pointing into `object1`, resolved in `objectCoordinateRef`.
21+
- `forceVector` is the total contact force vector acting at the contact point on object1, resolved in `objectCoordinateRef`.
22+
On `object2` the same force vector is applied in inverse direction.
23+
- `torqueVector` is the total contact torque vector acting at the contact point on object1, resolved in `objectCoordinateRef`.
24+
On `object2` the same torque vector is applied in inverse direction.
25+
"""
26+
mutable struct ContactResult{F <: Modia3D.VarFloatType} <: Modia3D.AbstractResultElement
27+
28+
path::String
29+
30+
object1::Object3D{F}
31+
object2::Object3D{F}
32+
objectCoordinateRef::Union{Object3D{F}, Nothing}
33+
34+
penetrationResultIndex::Int
35+
penetrationVelocityResultIndex::Int
36+
tangentialVelocityResultIndex::Int
37+
angularVelocityResultIndex::Int
38+
normalForceResultIndex::Int
39+
tangentialForceResultIndex::Int
40+
torqueResultIndex::Int
41+
positionVectorResultIndex::Int
42+
normalVectorResultIndex::Int
43+
forceVectorResultIndex::Int
44+
torqueVectorResultIndex::Int
45+
46+
function ContactResult{F}(; path::String = "",
47+
object1::Object3D{F},
48+
object2::Object3D{F},
49+
objectCoordinateRef::Union{Object3D{F}, Nothing}=nothing ) where F <: Modia3D.VarFloatType
50+
return new(path, object1, object2, objectCoordinateRef)
51+
end
52+
end
53+
ContactResult(; kwargs...) = ContactResult{Float64}(; kwargs...)
54+
55+
56+
function initializeResultElement(model::Modia.InstantiatedModel{F,TimeType}, result::ContactResult{F}) where {F <: Modia3D.VarFloatType, TimeType <: AbstractFloat}
57+
58+
result.penetrationResultIndex = Modia.new_w_segmented_variable!(model, result.path*".penetration" , F(0), "m")
59+
result.penetrationVelocityResultIndex = Modia.new_w_segmented_variable!(model, result.path*".penetrationVelocity", F(0), "m/s")
60+
result.tangentialVelocityResultIndex = Modia.new_w_segmented_variable!(model, result.path*".tangentialVelocity" , F(0), "m/s")
61+
result.angularVelocityResultIndex = Modia.new_w_segmented_variable!(model, result.path*".angularVelocity" , F(0), "rad/s")
62+
result.normalForceResultIndex = Modia.new_w_segmented_variable!(model, result.path*".normalForce" , F(0), "N")
63+
result.tangentialForceResultIndex = Modia.new_w_segmented_variable!(model, result.path*".tangentialForce" , F(0), "N")
64+
result.torqueResultIndex = Modia.new_w_segmented_variable!(model, result.path*".torque" , F(0), "N*m")
65+
result.positionVectorResultIndex = Modia.new_w_segmented_variable!(model, result.path*".positionVector" , SVector{3,F}(0, 0, 0), "m")
66+
result.normalVectorResultIndex = Modia.new_w_segmented_variable!(model, result.path*".normalVector" , SVector{3,F}(0, 0, 0))
67+
result.forceVectorResultIndex = Modia.new_w_segmented_variable!(model, result.path*".forceVector" , SVector{3,F}(0, 0, 0), "N")
68+
result.torqueVectorResultIndex = Modia.new_w_segmented_variable!(model, result.path*".torqueVector" , SVector{3,F}(0, 0, 0), "N*m")
69+
70+
return nothing
71+
end
72+
73+
function evaluateResultElement(model::Modia.InstantiatedModel{F,TimeType}, scene::Modia3D.Composition.Scene{F}, result::ContactResult{F}, time::TimeType) where {F <: Modia3D.VarFloatType, TimeType <: AbstractFloat}
74+
75+
(contactPair, converse) = getElasticContactPair(scene, result.object1, result.object2)
76+
if !isnothing(contactPair)
77+
pair::ContactPair{F} = contactPair
78+
penetration = pair.results.penetration
79+
penetrationVelocity = pair.results.penetrationVelocity
80+
tangentialVelocity = pair.results.tangentialVelocity
81+
angularVelocity = pair.results.angularVelocity
82+
normalForce = pair.results.normalForce
83+
tangentialForce = pair.results.tangentialForce
84+
torque = pair.results.torque
85+
positionVector = pair.results.positionVector
86+
normalVector = pair.results.normalVector
87+
forceVector = pair.results.forceVector
88+
torqueVector = pair.results.torqueVector
89+
if converse
90+
normalVector = -normalVector
91+
forceVector = -forceVector
92+
torqueVector = -torqueVector
93+
end
94+
if !isnothing(result.objectCoordinateRef)
95+
positionVector = result.objectCoordinateRef.R_abs * positionVector
96+
normalVector = result.objectCoordinateRef.R_abs * normalVector
97+
forceVector = result.objectCoordinateRef.R_abs * forceVector
98+
torqueVector = result.objectCoordinateRef.R_abs * torqueVector
99+
end
100+
else
101+
penetration = F(0)
102+
penetrationVelocity = F(0)
103+
tangentialVelocity = F(0)
104+
angularVelocity = F(0)
105+
normalForce = F(0)
106+
tangentialForce = F(0)
107+
torque = F(0)
108+
positionVector = SVector{3,F}(0, 0, 0)
109+
normalVector = SVector{3,F}(0, 0, 0)
110+
forceVector = SVector{3,F}(0, 0, 0)
111+
torqueVector = SVector{3,F}(0, 0, 0)
112+
end
113+
114+
if Modia.storeResults(model)
115+
Modia.copy_w_segmented_value_to_result(model, result.penetrationResultIndex, penetration)
116+
Modia.copy_w_segmented_value_to_result(model, result.penetrationVelocityResultIndex, penetrationVelocity)
117+
Modia.copy_w_segmented_value_to_result(model, result.tangentialVelocityResultIndex, tangentialVelocity)
118+
Modia.copy_w_segmented_value_to_result(model, result.angularVelocityResultIndex, angularVelocity)
119+
Modia.copy_w_segmented_value_to_result(model, result.normalForceResultIndex, normalForce)
120+
Modia.copy_w_segmented_value_to_result(model, result.tangentialForceResultIndex, tangentialForce)
121+
Modia.copy_w_segmented_value_to_result(model, result.torqueResultIndex, torque)
122+
Modia.copy_w_segmented_value_to_result(model, result.positionVectorResultIndex, positionVector)
123+
Modia.copy_w_segmented_value_to_result(model, result.normalVectorResultIndex, normalVector)
124+
Modia.copy_w_segmented_value_to_result(model, result.forceVectorResultIndex, forceVector)
125+
Modia.copy_w_segmented_value_to_result(model, result.torqueVectorResultIndex, torqueVector)
126+
end
127+
128+
return nothing
129+
end
130+
131+
function terminateResultElement(result::ContactResult{F}) where F <: Modia3D.VarFloatType
132+
return nothing
133+
end

src/Composition/_module.jl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,7 @@ include("scene.jl") # must be included after superObjects.jl
117117
include(joinpath("joints", "joints.jl"))
118118
include(joinpath("joints", "changeJointState.jl"))
119119

120+
include(joinpath("ResultElements", "ContactResult.jl"))
120121
include("sensors.jl")
121122
include("frameMeasurements.jl")
122123
include("frameForceTorque.jl")

src/Composition/dynamicCollision.jl

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -49,8 +49,8 @@ function dealWithContacts!(sim::Modia.InstantiatedModel{F, T}, scene::Scene{F},
4949

5050
for (pairID::Int64, pair::ContactPair{F}) in ch.contactDict
5151
obj1 = pair.obj1
52-
obj2= pair.obj2
53-
rContact= (pair.contactPoint1 + pair.contactPoint2)/F(2.0)
52+
obj2 = pair.obj2
53+
rContact = (pair.contactPoint1 + pair.contactPoint2)/F(2.0)
5454
contactNormal = pair.contactNormal
5555
if Modia.isEvent(sim)
5656
# println("$(sim.time): ", obj1.path, " ", obj2.path)
@@ -65,7 +65,7 @@ function dealWithContacts!(sim::Modia.InstantiatedModel{F, T}, scene::Scene{F},
6565
pair.distanceWithHysteresis, time, file, sim)
6666
elseif pair.pairKind == Modia3D.ElasticContactPairKind
6767
elasticContactPairMaterial::Composition.ElasticContactPairResponseMaterial = pair.contactPairMaterial
68-
(f1,f2,t1,t2) = responseCalculation(elasticContactPairMaterial, obj1, obj2,
68+
(f1,f2,t1,t2,pair.results) = responseCalculation(elasticContactPairMaterial, obj1, obj2,
6969
rContact, contactNormal,
7070
pair.distanceWithHysteresis, time, file, sim)
7171
elseif pair.pairKind == Modia3D.ObserverContactPairKind
@@ -245,3 +245,21 @@ function setVisualizationContactProperties!(obj::Composition.Object3D{F}, transp
245245
obj.feature.visualMaterial.transparency = transparency
246246
return nothing
247247
end
248+
249+
250+
function getElasticContactPair(scene::Scene{F}, obj1::Composition.Object3D{F}, obj2::Composition.Object3D{F}) where F <: Modia3D.VarFloatType
251+
252+
if scene.options.enableContactDetection
253+
for (pairID::Int64, pair::ContactPair{F}) in scene.options.contactDetection.contactDict
254+
if pair.pairKind == Modia3D.ElasticContactPairKind
255+
if (obj1 === pair.obj1 && obj2 === pair.obj2)
256+
return (pair, false) # object 1/2 assignment consistent
257+
elseif (obj2 === pair.obj1 && obj1 === pair.obj2)
258+
return (pair, true) # object 1/2 assignment converse
259+
end
260+
end
261+
end
262+
end
263+
264+
return (nothing, false)
265+
end

0 commit comments

Comments
 (0)