Skip to content

Commit aece232

Browse files
Enable force laws defined by functions in Bushing
- Enable force law functions. - Enable unique symbol for SpringDamperPtP force law functions. - Update test models and docu.
1 parent 49ad6c5 commit aece232

File tree

5 files changed

+95
-39
lines changed

5 files changed

+95
-39
lines changed

src/Composition/ForceElements/Bushing.jl

Lines changed: 87 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11

22
"""
33
force = Bushing(; obj1, obj2,
4-
nominalForce = Modia3D.ZeroVector3D,
5-
stiffness = Modia3D.ZeroVector3D,
6-
damping = Modia3D.ZeroVector3D,
7-
nominalTorque = Modia3D.ZeroVector3D,
8-
rotStiffness = Modia3D.ZeroVector3D,
9-
rotDamping = Modia3D.ZeroVector3D,
10-
largeAngles = false )
4+
nominalForce = Modia3D.ZeroVector3D,
5+
springForceLaw = Modia3D.ZeroVector3D,
6+
damperForceLaw = Modia3D.ZeroVector3D,
7+
nominalTorque = Modia3D.ZeroVector3D,
8+
rotSpringForceLaw = Modia3D.ZeroVector3D,
9+
rotDamperForceLaw = Modia3D.ZeroVector3D,
10+
largeAngles = false )
1111
1212
Return a `force` acting as bushing between `obj1::`[`Object3D`](@ref) and
1313
`obj2::`[`Object3D`](@ref). The force directions are defined by `obj1`,
@@ -18,16 +18,28 @@ i.e. the orientation of `obj2` does not influence the resulting forces.
1818
- `nominalForce` defines the nominal force vector, i.e. the force that
1919
acts when spring and damper forces are zero. Positive values act in
2020
positive axis directions at `obj1` and in opposite directions at `obj2`.
21-
- `stiffness` defines linear stiffness coefficients in x-, y- and
22-
z-direction.
23-
- `damping` defines linear damping coefficients in x-, y- and
24-
z-direction.
21+
- `springForceLaw` defines the force law of the spring in x-, y- and
22+
z-direction:
23+
- A `Float64` value represents a linear stiffness coefficient.
24+
- An univariate `Function` is used to compute the spring force
25+
dependent of its deflection.
26+
- `damperForceLaw` defines the force law of the damper in x-, y- and
27+
z-direction:
28+
- A `Float64` value represents a linear damping coefficient.
29+
- An univariate `Function` is used to compute the damper force
30+
dependent of its deflection velocity.
2531
- `nominalTorque` defines nominal torques about alpha, beta and gamma
2632
directions.
27-
- `rotStiffness` defines linear stiffness coefficients about alpha-,
28-
beta- and gamma-direction.
29-
- `rotDamping` defines linear damping coefficients about alpha-,
30-
beta- and gamma-direction.
33+
- `rotSpringForceLaw` defines the force law of the rotational spring
34+
about alpha-, beta- and gamma-direction:
35+
- A `Float64` value represents a linear damping coefficient.
36+
- An univariate `Function` is used to compute the spring force
37+
dependent of its deflection.
38+
- `rotDamperForceLaw` defines the force law of the rotational damper
39+
about alpha-, beta- and gamma-direction:
40+
- A `Float64` value represents a linear damping coefficient.
41+
- An univariate `Function` is used to compute the damper force
42+
dependent of its deflection velocity.
3143
- `largeAngles` can be used to enable large angle mode.
3244
- When disabled, small deformation angles (< 10°) are assumed. This
3345
option deals equally with rotations [alpha, beta gamma] about the
@@ -46,32 +58,68 @@ mutable struct Bushing <: Modia3D.AbstractForceElement
4658
obj2::Object3D
4759

4860
nominalForce::SVector{3,Float64}
49-
stiffness::SVector{3,Float64}
50-
damping::SVector{3,Float64}
61+
springForceFunction::SVector{3,Function}
62+
damperForceFunction::SVector{3,Function}
5163
nominalTorque::SVector{3,Float64}
52-
rotStiffness::SVector{3,Float64}
53-
rotDamping::SVector{3,Float64}
64+
rotSpringForceFunction::SVector{3,Function}
65+
rotDamperForceFunction::SVector{3,Function}
5466
largeAngles::Bool
5567

5668
function Bushing(; obj1::Object3D,
5769
obj2::Object3D,
5870
nominalForce::AbstractVector = Modia3D.ZeroVector3D,
59-
stiffness::AbstractVector = Modia3D.ZeroVector3D,
60-
damping::AbstractVector = Modia3D.ZeroVector3D,
71+
springForceLaw::AbstractVector = Modia3D.ZeroVector3D,
72+
damperForceLaw::AbstractVector = Modia3D.ZeroVector3D,
6173
nominalTorque::AbstractVector = Modia3D.ZeroVector3D,
62-
rotStiffness::AbstractVector = Modia3D.ZeroVector3D,
63-
rotDamping::AbstractVector = Modia3D.ZeroVector3D,
74+
rotSpringForceLaw::AbstractVector = Modia3D.ZeroVector3D,
75+
rotDamperForceLaw::AbstractVector = Modia3D.ZeroVector3D,
6476
largeAngles::Bool = false )
77+
for dir in 1:3
78+
@assert(typeof(springForceLaw[dir]) == Float64 || typeof(springForceLaw[dir]) == Function)
79+
@assert(typeof(damperForceLaw[dir]) == Float64 || typeof(damperForceLaw[dir]) == Function)
80+
@assert(typeof(rotSpringForceLaw[dir]) == Float64 || typeof(rotSpringForceLaw[dir]) == Function)
81+
@assert(typeof(rotDamperForceLaw[dir]) == Float64 || typeof(rotDamperForceLaw[dir]) == Function)
82+
end
6583

66-
nomForce = Modia3D.convertAndStripUnit(SVector{3,Float64}, u"N" , nominalForce)
67-
stiff = Modia3D.convertAndStripUnit(SVector{3,Float64}, u"N/m" , stiffness)
68-
damp = Modia3D.convertAndStripUnit(SVector{3,Float64}, u"N*s/m" , damping)
69-
nomTorque = Modia3D.convertAndStripUnit(SVector{3,Float64}, u"N*m" , nominalTorque)
70-
rotStiff = Modia3D.convertAndStripUnit(SVector{3,Float64}, u"N*m/rad" , rotStiffness)
71-
rotDamp = Modia3D.convertAndStripUnit(SVector{3,Float64}, u"N*m*s/rad", rotDamping)
72-
73-
return new(obj1, obj2, nomForce, stiff, damp, nomTorque, rotStiff, rotDamp, largeAngles)
84+
nomForce = Modia3D.convertAndStripUnit(SVector{3,Float64}, u"N" , nominalForce)
85+
nomTorque = Modia3D.convertAndStripUnit(SVector{3,Float64}, u"N*m", nominalTorque)
86+
springForceFunction = Vector{Function}(undef, 3)
87+
damperForceFunction = Vector{Function}(undef, 3)
88+
rotSpringForceFunction = Vector{Function}(undef, 3)
89+
rotDamperForceFunction = Vector{Function}(undef, 3)
90+
irand = rand(Int)
91+
for dir in 1:3
92+
if (typeof(springForceLaw[dir]) == Float64)
93+
stiffness = Modia3D.convertAndStripUnit(Float64, u"N/m", springForceLaw[dir])
94+
fsymb = Symbol("fc", dir, "_", irand) # todo: replace irand by force.path
95+
springForceFunction[dir] = eval(:($fsymb(pos) = $stiffness * pos))
96+
else
97+
springForceFunction[dir] = springForceLaw[dir]
98+
end
99+
if (typeof(damperForceLaw[dir]) == Float64)
100+
damping = Modia3D.convertAndStripUnit(Float64, u"N*s/m", damperForceLaw[dir])
101+
fsymb = Symbol("fd", dir, "_", irand) # todo: replace irand by force.path
102+
damperForceFunction[dir] = eval(:($fsymb(vel) = $damping * vel))
103+
else
104+
damperForceFunction[dir] = damperForceLaw[dir]
105+
end
106+
if (typeof(rotSpringForceLaw[dir]) == Float64)
107+
stiffness = Modia3D.convertAndStripUnit(Float64, u"N*m/rad", rotSpringForceLaw[dir])
108+
fsymb = Symbol("mc", dir, "_", irand) # todo: replace irand by force.path
109+
rotSpringForceFunction[dir] = eval(:($fsymb(ang) = $stiffness * ang))
110+
else
111+
rotSpringForceFunction[dir] = rotSpringForceLaw[dir]
112+
end
113+
if (typeof(rotDamperForceLaw[dir]) == Float64)
114+
damping = Modia3D.convertAndStripUnit(Float64, u"N*m*s/rad", rotDamperForceLaw[dir])
115+
fsymb = Symbol("md", dir, "_", irand) # todo: replace irand by force.path
116+
rotDamperForceFunction[dir] = eval(:($fsymb(angd) = $damping * angd))
117+
else
118+
rotDamperForceFunction[dir] = rotDamperForceLaw[dir]
119+
end
120+
end
74121

122+
return new(obj1, obj2, nomForce, springForceFunction, damperForceFunction, nomTorque, rotSpringForceFunction, rotDamperForceFunction, largeAngles)
75123
end
76124
end
77125

@@ -135,11 +183,15 @@ function evaluateForceElement(force::Bushing)
135183
v12 = measFrameTransVelocity(force.obj2; frameOrig=force.obj1, frameCoord=force.obj1, frameObsrv=force.obj1)
136184
(ang, angd, sico) = anglesFromRotation(force.largeAngles, R12, w12)
137185

138-
f12 = force.stiffness .* r12 + force.damping .* v12 + force.nominalForce
139-
mom = force.rotStiffness .* ang + force.rotDamping .* angd + force.nominalTorque
140-
t12 = torqueFromMoments(force.largeAngles, mom, sico)
186+
f12 = Vector{Float64}(undef, 3)
187+
mom = Vector{Float64}(undef, 3)
188+
for dir in 1:3
189+
f12[dir] = force.springForceFunction[dir](r12[dir]) + force.damperForceFunction[dir](v12[dir]) + force.nominalForce[dir]
190+
mom[dir] = force.rotSpringForceFunction[dir](ang[dir]) + force.rotDamperForceFunction[dir](angd[dir]) + force.nominalTorque[dir]
191+
end
192+
t12 = torqueFromMoments(force.largeAngles, SVector{3}(mom), sico)
141193

142-
applyFrameForcePair!(force.obj2, force.obj1, f12; frameCoord=force.obj1)
194+
applyFrameForcePair!(force.obj2, force.obj1, SVector{3}(f12); frameCoord=force.obj1)
143195
applyFrameTorquePair!(force.obj2, force.obj1, t12; frameCoord=force.obj1)
144196
return nothing
145197
end

src/Composition/ForceElements/SpringDamperPtP.jl

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,12 +44,15 @@ mutable struct SpringDamperPtP <: Modia3D.AbstractForceElement
4444

4545
nomLength = Modia3D.convertAndStripUnit(Float64, u"m", nominalLength)
4646
nomForce = Modia3D.convertAndStripUnit(Float64, u"N", nominalForce)
47+
irand = rand(Int)
4748
if (typeof(springForceLaw) == Float64)
4849
stiffness = Modia3D.convertAndStripUnit(Float64, u"N/m", springForceLaw)
49-
springForceLaw = eval(:(fc(pos) = $stiffness * pos))
50+
fsymb = Symbol("fc", "_", irand) # todo: replace irand by force.path
51+
springForceLaw = eval(:($fsymb(pos) = $stiffness * pos))
5052
end
5153
if (typeof(damperForceLaw) == Float64)
5254
damping = Modia3D.convertAndStripUnit(Float64, u"N*s/m", damperForceLaw)
55+
fsymb = Symbol("fd", "_", irand) # todo: replace irand by force.path
5356
damperForceLaw = eval(:(fd(vel) = $damping * vel))
5457
end
5558

test/ForceElements/BoxBushing.jl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,8 @@ BoxBushing = Model(
2525
visualMaterial=:(visualMaterial))),
2626
joint = FreeMotion(obj1=:world, obj2=:box, r=Var(init=[0.2, 0.1, 0.05]), rot=Var(init=startAngles)),
2727
force = Bushing(obj1=:world, obj2=:box,
28-
stiffness=[50.0, 100.0, 200.0], damping=[1.0, 2.0, 4.0],
29-
rotStiffness=[5.0, 10.0, 20.0], rotDamping=[0.1, 0.2, 0.4], largeAngles=largeAngles)
28+
springForceLaw=[50.0, 100.0, 200.0], damperForceLaw=[1.0, 2.0, 4.0],
29+
rotSpringForceLaw=[5.0, 10.0, 20.0], rotDamperForceLaw=[0.1, 0.2, 0.4], largeAngles=largeAngles)
3030
)
3131

3232
boxBushing = @instantiateModel(buildModia3D(BoxBushing), aliasReduction=false, unitless=true)

test/ForceElements/HarmonicOscillator.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ Oscillator = Model(
1919
massProperties=MassProperties(; mass=:Mass, Ixx=0.1, Iyy=0.1, Izz=0.1),
2020
visualMaterial=:(visualMaterial))),
2121
joint = Prismatic(obj1=:world, obj2=:oscillator, axis=3, s=Var(init=0.0), v=Var(init=0.0)),
22-
force = Bushing(obj1=:world, obj2=:oscillator, nominalForce=:[0.0, 0.0, nomForce], stiffness=:[0.0, 0.0, Stiffness], damping=:[0.0, 0.0, Damping])
22+
force = Bushing(obj1=:world, obj2=:oscillator, nominalForce=:[0.0, 0.0, nomForce], springForceLaw=:[0.0, 0.0, Stiffness], damperForceLaw=:[0.0, 0.0, Damping])
2323
)
2424

2525
oscillator = @instantiateModel(buildModia3D(Oscillator), aliasReduction=false, unitless=true)

test/includeTests.jl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ end
2020

2121
Test.@testset "Force Elements" begin
2222
include(joinpath("ForceElements", "HarmonicOscillator.jl"))
23+
include(joinpath("ForceElements", "BoxBushing.jl"))
2324
include(joinpath("ForceElements", "BoxSpringDamperPtP.jl"))
2425
include(joinpath("ForceElements", "BoxNonLinearSpringDamperPtP.jl"))
2526
end

0 commit comments

Comments
 (0)