11
22"""
33 force = Bushing(; obj1, obj2,
4- nominalForce = Modia3D.ZeroVector3D,
5- stiffness = Modia3D.ZeroVector3D,
6- damping = Modia3D.ZeroVector3D )
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 )
711
812Return a `force` acting as bushing between `obj1::`[`Object3D`](@ref) and
9- `obj2::`[`Object3D`](@ref). Vectors `stiffness`, `damping` and
10- `nominalForce` define the stiffness, damping and nominal force values in
11- x, y and z direction of `obj1`. The orientation of `obj2` does not
12- influence the resulting forces.
13+ `obj2::`[`Object3D`](@ref). The force directions are defined by `obj1`,
14+ i.e. the orientation of `obj2` does not influence the resulting forces.
15+
16+ # Arguments
17+
18+ - `nominalForce` defines the nominal force vector, i.e. the force that
19+ acts when spring and damper forces are zero. Positive values act in
20+ 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.
25+ - `nominalTorque` defines nominal torques about alpha, beta and gamma
26+ 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.
31+ - `largeAngles` can be used to enable large angle mode.
32+ - When disabled, small deformation angles (< 10°) are assumed. This
33+ option deals equally with rotations [alpha, beta gamma] about the
34+ axes [x, y, z] of `obj1`, but causes approximation errors for
35+ larger angles.
36+ - When enabled, the deformation angles and torque directions are
37+ calculated as [Cardan (Tait–Bryan) angles](https://en.wikipedia.org/wiki/Euler_angles#Chained_rotations_equivalence)
38+ (rotation sequence x-y-z from `obj1` to `obj2`). This option
39+ supports angles up to nearly 90°, but introduces local rotation
40+ directions [alpha, beta gamma] which differ from the axes [x, y, z]
41+ of `obj1` and increases computation effort.
1342"""
1443mutable struct Bushing <: Modia3D.AbstractForceElement
1544
@@ -19,19 +48,76 @@ mutable struct Bushing <: Modia3D.AbstractForceElement
1948 nominalForce:: SVector{3,Float64}
2049 stiffness:: SVector{3,Float64}
2150 damping:: SVector{3,Float64}
51+ nominalTorque:: SVector{3,Float64}
52+ rotStiffness:: SVector{3,Float64}
53+ rotDamping:: SVector{3,Float64}
54+ largeAngles:: Bool
2255
2356 function Bushing (; obj1:: Object3D ,
2457 obj2:: Object3D ,
2558 nominalForce:: AbstractVector = Modia3D. ZeroVector3D,
2659 stiffness:: AbstractVector = Modia3D. ZeroVector3D,
27- damping:: AbstractVector = Modia3D. ZeroVector3D)
60+ damping:: AbstractVector = Modia3D. ZeroVector3D,
61+ nominalTorque:: AbstractVector = Modia3D. ZeroVector3D,
62+ rotStiffness:: AbstractVector = Modia3D. ZeroVector3D,
63+ rotDamping:: AbstractVector = Modia3D. ZeroVector3D,
64+ largeAngles:: Bool = false )
65+
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)
2872
29- nomForce = Modia3D. convertAndStripUnit (SVector{3 ,Float64}, u " N" , nominalForce)
30- stiff = Modia3D. convertAndStripUnit (SVector{3 ,Float64}, u " N/m" , stiffness)
31- damp = Modia3D. convertAndStripUnit (SVector{3 ,Float64}, u " N*s/m" , damping)
73+ return new (obj1, obj2, nomForce, stiff, damp, nomTorque, rotStiff, rotDamp, largeAngles)
3274
33- return new (obj1, obj2, nomForce, stiff, damp)
75+ end
76+ end
77+
78+
79+ # Compute deformation angles from rotation matrix
80+ function anglesFromRotation (largeAngles:: Bool , R12:: SMatrix{3,3,Float64} , w12:: SVector{3,Float64} )
81+ if largeAngles
82+ sbe = clamp (R12[3 ,1 ], - 1.0 , 1.0 )
83+ cbe = sqrt (1.0 - sbe* sbe)
84+ if (cbe > 1e-12 )
85+ sal = - R12[3 ,2 ]/ cbe
86+ cal = R12[3 ,3 ]/ cbe
87+ al = atan (- R12[3 ,2 ], R12[3 ,3 ])
88+ be = asin (sbe)
89+ ga = atan (- R12[2 ,1 ], R12[1 ,1 ])
90+ ald = w12[1 ] + (sal* w12[2 ] - cal* w12[3 ])* sbe/ cbe
91+ bed = cal* w12[2 ] + sal* w12[3 ]
92+ gad = (- sal* w12[2 ] + cal* w12[3 ])/ cbe
93+ return (@SVector [al, be, ga], @SVector [ald, bed, gad], @SMatrix [sal sbe; cal cbe])
94+ else
95+ @error (" Gimbal lock of Bushing transformation." )
96+ return (@SVector [0.0 , 0.0 , 0.0 ], @SVector [0.0 , 0.0 , 0.0 ], @SMatrix [0.0 0.0 ; 0.0 0.0 ])
97+ end
98+ else
99+ al = R12[2 ,3 ]
100+ be = R12[3 ,1 ]
101+ ga = R12[1 ,2 ]
102+ ald = w12[1 ]
103+ bed = w12[2 ]
104+ gad = w12[3 ]
105+ if (max (abs (al), abs (be), abs (ga)) > 0.174 )
106+ @warn (" Bushing angle exceeds 10 deg." )
107+ end
108+ return (@SVector [al, be, ga], @SVector [ald, bed, gad], @SMatrix [0.0 0.0 ; 0.0 0.0 ])
109+ end
110+ end
34111
112+ # Compute torque vector from force law moments
113+ function torqueFromMoments (largeAngles:: Bool , moments:: SVector{3,Float64} , sico:: SMatrix{2,2,Float64,4} )
114+ if largeAngles
115+ tx = moments[1 ] + sico[1 ,2 ]* moments[3 ]
116+ ty = sico[2 ,1 ]* moments[2 ] - sico[1 ,1 ]* sico[2 ,2 ]* moments[3 ]
117+ tz = sico[1 ,1 ]* moments[2 ] + sico[2 ,1 ]* sico[2 ,2 ]* moments[3 ]
118+ return @SVector [tx, ty, tz]
119+ else
120+ return moments
35121 end
36122end
37123
@@ -43,12 +129,18 @@ function initializeForceElement(force::Bushing)
43129end
44130
45131function evaluateForceElement (force:: Bushing )
132+ R12 = measFrameRotation (force. obj2; frameOrig= force. obj1)
46133 r12 = measFramePosition (force. obj2; frameOrig= force. obj1, frameCoord= force. obj1)
134+ w12 = measFrameRotVelocity (force. obj2; frameOrig= force. obj1, frameCoord= force. obj1)
47135 v12 = measFrameTransVelocity (force. obj2; frameOrig= force. obj1, frameCoord= force. obj1, frameObsrv= force. obj1)
136+ (ang, angd, sico) = anglesFromRotation (force. largeAngles, R12, w12)
48137
49138 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)
50141
51142 applyFrameForcePair! (force. obj2, force. obj1, f12; frameCoord= force. obj1)
143+ applyFrameTorquePair! (force. obj2, force. obj1, t12; frameCoord= force. obj1)
52144 return nothing
53145end
54146
0 commit comments