Skip to content

Commit 47f1be9

Browse files
Enable FreeMotion adaptive rotation sequence
- Implemented by [email protected] - Fix zero crossing function: abs(rot[2]) < 1.5
1 parent 4a5282b commit 47f1be9

File tree

5 files changed

+63
-11
lines changed

5 files changed

+63
-11
lines changed

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/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, 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: 47 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -131,18 +131,62 @@ 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+
J123or132(rot, isrot123) = isrot123 ? J123(rot) : J132(rot)
167+
168+
134169
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),
135170
obj1 = Par(value = obj1),
136171
obj2 = Par(value = obj2),
137172
r = r,
138173
rot = rot,
139174
v = v,
140175
w = w,
176+
177+
next_isrot123 = Var(start=true),
178+
_rotName = "???", # is changed by buildModia3D to the full path name of "rot"
179+
141180
equations = :[
142-
der(r) = v
143-
der(rot) = J123(rot) * w
181+
der(r) = v
182+
183+
isrot123 = pre(next_isrot123)
184+
rot2_singularity = positive( abs(rot[2]) - 1.5 )
185+
next_isrot123 = if rot2_singularity; change_rotSequenceInNextIteration!(rot, isrot123, instantiatedModel, _x, _rotName) else isrot123 end
186+
der(rot) = J123or132(rot,isrot123) * w
187+
144188
der(v) = qdd[1:3]
145189
der(w) = qdd[4:6]
146-
variables = getVariables(r, rot, v, w)
190+
variables = getVariables(r, rot, v, w, isrot123)
147191
]
148192
)

0 commit comments

Comments
 (0)