Skip to content

Commit 7114e47

Browse files
Merge pull request #41 from ModiaSim/gh_freeMotionAdaptiveRotationSequence
Gh free motion adaptive rotation sequence
2 parents 1c100de + 82de5d6 commit 7114e47

File tree

12 files changed

+115
-18
lines changed

12 files changed

+115
-18
lines changed

src/Composition/dynamics.jl

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ struct MultibodyData{FloatType}
9393
jointObjects::Vector{Object3D} # References to Object3Ds that have a joint
9494
jointStartIndex::Vector{Int} # Start index of joint in qdd
9595
jointNdof::Vector{Int} # Number-of-degrees-of-freedom of joint
96-
zStartIndex::Int # eventHandler.z[zStartIndex] is first index of crossing function
96+
zStartIndex::Int # eventHandler.z[zStartIndex] is first index of crossing functions for contact detection
9797
# (or zero, if nableContactDetection=false)
9898
nz::Int # Number of used zero crossing functions
9999
residuals::Vector{FloatType} # Residuals - length(residuals) = nqdd
@@ -141,6 +141,7 @@ function setModiaJointVariables!(id::Int, _leq_mode, instantiatedModel::ModiaLan
141141
if scene.options.enableContactDetection
142142
nz = 2
143143
zStartIndex = ModiaLang.addZeroCrossings(instantiatedModel, nz)
144+
scene.zStartIndex = zStartIndex
144145
else
145146
nz = 0
146147
zStartIndex = 0

src/Composition/joints/joints.jl

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -314,7 +314,7 @@ function computeKinematics!(scene::Scene, tree::Vector{Object3D}, time)::Nothing
314314
freeMotion = scene.freeMotion[obj.jointIndex]
315315

316316
obj.r_rel = freeMotion.r
317-
obj.R_rel = Rfromrot123(freeMotion.rot)
317+
obj.R_rel = freeMotion.isrot123 ? Rfromrot123(freeMotion.rot) : Rfromrot132(freeMotion.rot)
318318

319319
obj.r_abs = obj.r_rel
320320
obj.R_abs = obj.R_rel
@@ -329,7 +329,7 @@ function computeKinematics!(scene::Scene, tree::Vector{Object3D}, time)::Nothing
329329
freeMotion = scene.freeMotion[obj.jointIndex]
330330

331331
obj.r_rel = freeMotion.r
332-
obj.R_rel = Rfromrot123(freeMotion.rot)
332+
obj.R_rel = freeMotion.isrot123 ? Rfromrot123(freeMotion.rot) : Rfromrot132(freeMotion.rot)
333333

334334
obj.r_abs = parent.r_abs + parent.R_abs'*obj.r_rel
335335
obj.R_abs = obj.R_rel*parent.R_abs
@@ -489,7 +489,8 @@ function setJointVariables_q_qd_f!(scene::Scene, objects::Vector{Object3D}, star
489489
freeMotion.rot = SVector{3,Float64}(args_i[2])
490490
freeMotion.v = SVector{3,Float64}(args_i[3])
491491
freeMotion.w = SVector{3,Float64}(args_i[4])
492-
492+
freeMotion.isrot123 = args_i[5]
493+
493494
else
494495
error("Bug in Modia3D/src/Composition/specifics/specifics.jl (setJointVariables!): jointKind = $jointKind is not known")
495496
end

src/Composition/joints/object3DMotion.jl

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,8 @@ mutable struct FreeMotion <: Modia3D.AbstractJoint
3232
ndof::Int
3333

3434
r::SVector{3,Float64}
35-
rot::SVector{3,Float64} # cardan angles (rotation sequence x-y-z)
35+
rot::SVector{3,Float64} # cardan angles
36+
isrot123::Bool # = true: rotation sequence x-y-z, otherwise x-z-y
3637

3738
v::SVector{3,Float64}
3839
w::SVector{3,Float64} # angular velocity vector
@@ -49,7 +50,8 @@ mutable struct FreeMotion <: Modia3D.AbstractJoint
4950
r::AbstractVector = Modia3D.ZeroVector3D,
5051
rot::AbstractVector = Modia3D.ZeroVector3D,
5152
v::AbstractVector = Modia3D.ZeroVector3D,
52-
w::AbstractVector = Modia3D.ZeroVector3D)
53+
w::AbstractVector = Modia3D.ZeroVector3D,
54+
next_isrot123::Bool = true) # dummy argument, is ignored
5355

5456
#(parent,obj,cutJoint) = attach(obj1, obj2)
5557
#if cutJoint
@@ -68,18 +70,19 @@ mutable struct FreeMotion <: Modia3D.AbstractJoint
6870
w = Modia3D.convertAndStripUnit(SVector{3,Float64}, u"rad/s", w)
6971
a = Modia3D.ZeroVector3D
7072
z = Modia3D.ZeroVector3D
73+
isrot123 = true # next_isrot123 is ignored.
7174

7275
residue_f = Modia3D.ZeroVector3D
7376
residue_t = Modia3D.ZeroVector3D
7477

75-
obj2.joint = new(path, obj1, obj2, 6, r, rot, v, w, a, z, residue_f, residue_t)
78+
obj2.joint = new(path, obj1, obj2, 6, r, rot, isrot123, v, w, a, z, residue_f, residue_t)
7679
obj2.parent = obj1
7780
obj2.jointKind = FreeMotionKind
7881
obj2.jointIndex = 0
7982
obj2.ndof = 6
8083
obj2.canCollide = true
8184
obj2.r_rel = r
82-
obj2.R_rel = Rfromrot123(rot)
85+
obj2.R_rel = isrot123 ? Rfromrot123(rot) : Rfromrot132(rot)
8386

8487
push!(obj1.children, obj2)
8588

src/Composition/scene.jl

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -405,7 +405,8 @@ mutable struct Scene <: Modia3D.AbstractScene
405405
noCPairs::Vector{Vector{Int64}} # Indices of frames (with respect to collSuperObjs) that can't collide in general (e.g. objects are connected via joints)
406406
noCPairsHelp::Dict{Modia3D.AbstractJoint,Vector{Int64}}
407407
allowedToMove::Vector{Union{Bool,Nothing}}
408-
AABB::Vector{Vector{Basics.BoundingBox}} # Bounding boxes of elements that can collide
408+
AABB::Vector{Vector{Basics.BoundingBox}} # Bounding boxes of elements that can collide
409+
zStartIndex::Int # start index of collision zero crossing functions
409410
#forceElements::Vector{Int64}
410411
exportAnimation::Bool # animation file export is enabled
411412
animation::Vector{animationStep} # animation data of visible Object3Ds
@@ -495,6 +496,7 @@ mutable struct Scene <: Modia3D.AbstractScene
495496
Dict{Modia3D.AbstractJoint,Vector{Int64}}(),
496497
Vector{Union{Bool}}[],
497498
Vector{Vector{Basics.BoundingBox}}[],
499+
1,
498500
exportAnimation,
499501
Vector{animationStep}[],
500502
0,

src/ModiaInterface/_module.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ export multibodyResiduals!, setModiaJointVariables!
1616
export Fix
1717
export Revolute, RevoluteWithFlange
1818
export Prismatic, PrismaticWithFlange
19-
export J123, J132, FreeMotion
19+
export J123, J132, J123or132, singularRem, FreeMotion, change_rotSequenceInNextIteration!
2020

2121
export buildModia3D
2222

src/ModiaInterface/buildModia3D.jl

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,10 @@ function getJointInfo!(model, jointInfo, path)::Nothing
6666
constructor = model[:_constructor]
6767
if typeof(constructor) <: OrderedDict && haskey(constructor, :ndof)
6868
ndof = constructor[:ndof]
69+
if haskey(model, :_rotName)
70+
# Hack to provide the full path name of FreeMotion.rot to the FreeMotion object
71+
model[:_rotName] = string(path)*".rot"
72+
end
6973
push!(jointInfo, (path=path, ndof=ndof))
7074
return
7175
end

src/ModiaInterface/model3D.jl

Lines changed: 48 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -131,18 +131,63 @@ function J132(rot132::AbstractVector)
131131

132132
end
133133

134+
135+
136+
"""
137+
next_isrot123 = change_rotSequenceInNextIteration!(rot::AbstractVector, isrot123::Bool, instantiatedModel::SimulationModel, x, rot_name)
138+
139+
Change rotation sequence of `rot` from `x-axis, y-axis, z-axis` to `x-axis, z-axis, y-axis` or visa versa in the next event iteration:
140+
141+
- If `isrot123 = true`, return `next_isrot123 = false` and `x[..] = rot132fromR(Rfromrot123(rot))`
142+
143+
- If `isrot123 = false`, return `next_isrot123 = true` and `x[..] = rot123fromR(Rfromrot132(rot))`
144+
"""
145+
function change_rotSequenceInNextIteration!(rot::AbstractVector, isrot123::Bool, instantiatedModel::SimulationModel, x, rot_name)::Bool
146+
if isrot123
147+
#println(" switch $rot_name 123 -> 132")
148+
next_rot = Modia3D.rot132fromR(Modia3D.Rfromrot123(rot))
149+
next_isrot123 = false
150+
else
151+
#println(" switch $rot_name 132 -> 123")
152+
next_rot = Modia3D.rot123fromR(Modia3D.Rfromrot132(rot))
153+
next_isrot123 = true
154+
end
155+
156+
# Change x-vector with the next_rot values
157+
eqInfo = instantiatedModel.equationInfo
158+
startIndex = eqInfo.x_info[ eqInfo.x_dict[rot_name] ].startIndex
159+
x[startIndex] = next_rot[1]
160+
x[startIndex+1] = next_rot[2]
161+
x[startIndex+2] = next_rot[3]
162+
return next_isrot123
163+
end
164+
165+
166+
singularRem(ang) = abs(rem2pi(ang, RoundNearest)) - 1.5 # is negative/positive in valid/singular angle range
167+
J123or132(rot, isrot123) = isrot123 ? J123(rot) : J132(rot)
168+
169+
134170
FreeMotion(; obj1, obj2, r=Var(init=zeros(3)), rot=Var(init=zeros(3)), v=Var(init=zeros(3)), w=Var(init=zeros(3))) = Model(; _constructor = Par(value = :(Modia3D.FreeMotion), _path = true, ndof = 6),
135171
obj1 = Par(value = obj1),
136172
obj2 = Par(value = obj2),
137173
r = r,
138174
rot = rot,
139175
v = v,
140176
w = w,
177+
178+
next_isrot123 = Var(start=true),
179+
_rotName = "???", # is changed by buildModia3D to the full path name of "rot"
180+
141181
equations = :[
142-
der(r) = v
143-
der(rot) = J123(rot) * w
182+
der(r) = v
183+
184+
isrot123 = pre(next_isrot123)
185+
rot2_singularity = positive(singularRem(rot[2]))
186+
next_isrot123 = if rot2_singularity; change_rotSequenceInNextIteration!(rot, isrot123, instantiatedModel, _x, _rotName) else isrot123 end
187+
der(rot) = J123or132(rot,isrot123) * w
188+
144189
der(v) = qdd[1:3]
145190
der(w) = qdd[4:6]
146-
variables = getVariables(r, rot, v, w)
191+
variables = getVariables(r, rot, v, w, isrot123)
147192
]
148193
)

src/contactDetection/ContactDetectionMPR/handler.jl

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -74,14 +74,14 @@ function selectContactPairs!(sim, scene::Composition.Scene, ch::Composition.Cont
7474
# z[1] ... zero crossing function from contact to no contact
7575
# max. distance (= min. penetration) of active contact pairs
7676
if isempty(ch.contactDict)
77-
@inbounds simh.z[1] = -42.0
77+
simh.z[scene.zStartIndex] = -42.0
7878
else
7979
(pair, key) = findmax(ch.contactDict)
80-
@inbounds simh.z[1] = pair.distanceWithHysteresis
80+
simh.z[scene.zStartIndex] = pair.distanceWithHysteresis
8181
end
8282
# z[2] ... zero crossing function from no contact to contact
8383
# min. distance of inactive contact pairs
84-
@inbounds simh.z[2] = ch.noContactMinVal
84+
simh.z[1+scene.zStartIndex] = ch.noContactMinVal
8585
end
8686
ch.distanceComputed = true
8787
return nothing
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
module ShaftFreeMotionAdaptiveRotSequence
2+
3+
using ModiaLang
4+
5+
import Modia3D
6+
using Modia3D.ModiaInterface
7+
8+
Shaft = Model(
9+
Length = 1.0,
10+
Diameter = 0.2,
11+
visualMaterial = VisualMaterial(color="IndianRed1", transparency=0.5),
12+
world = Object3D(feature=Scene(gravityField=UniformGravityField(g=0.3, n=[0, 0, -1]))),
13+
worldFrame = Object3D(parent=:world,
14+
feature=Visual(shape=CoordinateSystem(length=:Diameter))),
15+
shaft = Object3D(feature=Solid(shape=Cylinder(axis=3, diameter=:Diameter, length=:Length),
16+
massProperties=MassProperties(; mass=84.7154, Ixx=7.2711, Iyy=7.2711, Izz=0.4230),
17+
visualMaterial=:(visualMaterial))),
18+
shaftFrame = Object3D(parent=:shaft, feature=Visual(shape=CoordinateSystem(length=0.4))),
19+
free = FreeMotion(obj1=:world, obj2=:shaft, v = Var(init = [0.0, 0.1, 0.0]),
20+
rot = Var(start = [deg2rad(30), deg2rad(90), deg2rad(10)]),
21+
w = Var(init = [-2.0, 0.0, 0.0]))
22+
)
23+
24+
#@showModel model
25+
26+
shaft = @instantiateModel(buildModia3D(Shaft), aliasReduction=false, unitless=true, log=false, logStateSelection=false, logCode=true)
27+
28+
#@showModel shaft.p[1]
29+
30+
stopTime = 7.0
31+
dtmax = 0.1
32+
requiredFinalStates = [0.0, 0.7, -7.350074420637136, 0.0, 0.1, -2.1, 0.6981317007977381, 1.4336293856408397, 1.5707963267949017, -2.0, 0.0, 0.0]
33+
simulate!(shaft, stopTime=stopTime, dtmax=dtmax, log=true, logEvents=true, logStates=true, requiredFinalStates=requiredFinalStates)
34+
35+
@usingModiaPlot
36+
plot(shaft, "free.rot", figure=1)
37+
plot(shaft, ["free.r", "free.v", "free.w"], figure=2)
38+
plot(shaft, "free.isrot123", figure=3)
39+
40+
end

test/Collision/BouncingCapsules.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ bouncingCapsules = @instantiateModel(buildModia3D(BouncingCapsules), unitless=tr
7171

7272
stopTime = 1.7
7373
tolerance = 1e-8
74-
requiredFinalStates = [-0.7964014792034407, 1.078911579441921, 0.23035036015771998, -0.10969534535624982, 0.4797449365169936, -0.08174820851332286, 4.48271590323064, 1.340697608488989, -1.5392203655926255, 2.4243895450782937, 0.15531689730526202, -0.03915705292205236, 0.22862079147109046, -0.7970862046473598, 1.0806110815754162, -0.06460242891125959, -0.11431031161481991, 0.4851429973131076, 3.385569081576411, 0.1916283718909546, -1.6236830622142888, -0.06474401604033102, 2.4344556240272657, 0.2553659880626085, 1.0818397597553406, 0.22945140558263866, -0.7966137267737096, 0.4853616788402741, -0.07085422346062514, -0.09972138522555073, -1.5640086933709134, 0.19867779732620508, 3.386466331485274, 0.21808527847860343, -0.05743721435841237, 2.4419014448796816]
74+
requiredFinalStates = [-0.7964020579786201, 1.078911664590739, 0.23035071499249554, -0.11077716509170218, 0.4796475444580211, -0.08226573462808072, 2.944349048428646, -0.22998195076361025, 1.5634033775705642, 2.4243768357473545, 0.1525224150890733, -0.038478509902694046, 0.22862096684511138, -0.7970870633627486, 1.080611113333237, -0.06458397074339108, -0.11429374835354875, 0.4851467302974838, 3.3855692118273724, 0.19162868836235442, -1.6236815609521178, -0.06476968434945787, 2.4344563197987243, 0.25547076791303613, 1.0818397999295593, 0.22945161590171845, -0.7966147351633047, 0.4853706855582012, -0.07080711655835899, -0.09965214358471511, -1.5640102628973194, 0.198677718499869, 3.386466629188658, 0.2183469805758011, -0.05750372064225383, 2.441900102029629]
7575
simulate!(bouncingCapsules, stopTime=stopTime, tolerance=tolerance, log=true, logStates=true, logEvents=true, requiredFinalStates=requiredFinalStates)
7676

7777
@usingModiaPlot

0 commit comments

Comments
 (0)