The meaning of O.bodies.state.ori/refOri

Asked by Leonard on 2020-07-25

Hi,

When I was trying to calculate the rotation angle of spheres, I found the following state parameters may be useful, but I didn't fully understand the meaning of each parameter.
For example, for one typical sphere, I got:

1.O.bodies[i].state.ori
#get current orientation
I got: Quaternion((-0.8571073592023137,0.483498130637521,-0.17775413489215533),2.167483435911097), this quaternion is composed of a unit vector and a value, how to use the vector and the value to represent the orientation?

2.O.bodies[i].state.refOri
# get reference orientation
I got: Quaternion((1,0,0),0)
How yade define the refOri for a particle? I suppose refOri will not change, am I right?

3.O.bodies[i].state.rot()
#Rotation from reference orientation (as rotation vector)
I got: Vector3(-1.8577660038685175,1.0479741894508063,-0.3852791430434534)
How can I use this vector to calculate the rotation angle? Is this vector related to ori and refOri?

4.O.bodies[i].state.refPos
I got: Vector3(0.06797544633577166,0.012988671946374571,0.03281123240261211)
Can the displacement of the sphere be calculated by O.state.pos-O.state.refPos?

Thanks in advance
Have a good weekend
Leonard
https://yade-dem.org/doc/yade.wrapper.html?highlight=state%20ori#yade.wrapper.State.ori

Question information

Language:
English Edit question
Status:
Solved
For:
Yade Edit question
Assignee:
No assignee Edit question
Solved by:
Jan Stránský
Solved:
2020-07-26
Last query:
2020-07-26
Last reply:
2020-07-26
Jan Stránský (honzik) said : #1

Hello,

1.
the quaternion is printed in its axis-angle representation. The orientation is represented as "rotation by the angle around the axis"

2.
Using "utils" particle creation method (e.g. utils.sphere, utils.box, ...), which I suppose, state.refOri is set as the initial value of state.ori

refOri does not change "automatically", but you can change it "manually" if you like.

3.
see the source code [1]. it is angle equivalent of state.displ() [2], i.e. rotation "between" state.refOri and state.ori.
The vector i axis*angle
However, there is a problem for "large rotations", e.g. rolling of particles. Have a look at similar discussion [3] (from comment #14 on) if this your case

4.
yes. This is actually what state.displ() [2] does

cheers
Jan

[1] https://gitlab.com/yade-dev/trunk/-/blob/master/core/State.hpp#L40
[2] https://yade-dem.org/doc/yade.wrapper.html#yade.wrapper.State.displ
[3] https://answers.launchpad.net/yade/+question/688763

Leonard (z2521899293) said : #2

Hi Jan,

Many thanks for your explanation.

>1,2,4 are all clear.

>for question 3 (O.bodies[i].state.rot())

Since O.bodies[i].state.rot().norm() is for getting the rotation angle from reference orientation (b.state.refOri), and it may have "large rotations" issue, so I'd like to gain the incremental rotation angle from one step to another step. How to calculate this incremental rotation angle?

BTW, one thing to confirm: is the angle obtained by O.bodies[i].state.rot().norm() radian or degree?

Thanks
Leonard

Jan Stránský (honzik) said : #3

> How to calculate this incremental rotation angle?

see [3] for discussion (code below)

> ... radian or degree?

radian

cheers
Jan

###
b = facet(((0,0,0),(1,0,0),(0,1,0)))
O.bodies.append(b)
b.state.angVel = (0,0,.1)

rot = 0
ori = b.state.refOri

def updateRot(b,rot,ori): # works for rotation aroud z axis
   relRot = ori.conjugate()*b.state.ori # same as State.rot(), https://gitlab.com/yade-dev/trunk/-/blob/master/core/State.hpp#L40
   axis,angle = relRot.toAxisAngle() # get axis and angle from quaternion
   if (axis[2]) < 0: # "negative" rotation ...
      angle *= -1 # ... negate the positive angle
   rot += angle # updates rotation angle
   ori = b.state.ori # "store" new orientation value
   return rot,ori

for i in range(20):
   O.step()
   rot,ori = updateRot(b,rot,ori)
   print i,rot

b.state.angVel = (0,0,-.3)

for i in range(40):
   O.step()
   rot,ori = updateRot(b,rot,ori)
   print i,rot
###

Leonard (z2521899293) said : #4

Hi Jan,

Thanks for the MWE.

One stupid question:
what is the meaning of each components in the vector of State.rot()?

I am asking this because I notice that "updateRot(b,rot,ori) works for rotation aroud z axis", I know it is for the MWE in which the facet rotates around z axis. For real situation, there could be rotation in all three directions (x,y,z), do we need to set it for all the 3 directions?
My stupid guess as something like:

if (axis[0]) < 0 or (axis[1]) < 0 or (axis[2]) < 0:
      angle *= -1
.....

Many thanks
Leonard

Best Jan Stránský (honzik) said : #5

Ok, the code was meant for the example in the other question related specifically to z axis. General case below.
"rot" is rotation vector, you can convert it back to quaternion with
##
angle = rot.norm()
axis = rot.normalized()
ori = Quaternion(axis,angle)
##

cheers
Jan

###
b = facet(((0,0,0),(1,0,0),(0,1,0)))
O.bodies.append(b)

rot = Vector3.Zero # total rotation Vector
ori = b.state.refOri # last known orientation

def updateRot(b,rot,ori):
   relOri = ori.conjugate()*b.state.ori # same as State.rot(), https://gitlab.com/yade-dev/trunk/-/blob/master/core/State.hpp#L40
   axis,angle = relOri.toAxisAngle() # get axis and angle from quaternion
   relRot = axis*angle # relative rotation vector
   rot += relRot # updates rotation vector
   ori = b.state.ori # "store" new orientation value
   return rot,ori

b.state.angVel = (0,0,.1)
for i in range(20):
   O.step()
   rot,ori = updateRot(b,rot,ori)
   print i,rot

b.state.angVel = (0,0,-.3)
for i in range(40):
   O.step()
   rot,ori = updateRot(b,rot,ori)
   print i,rot

b.state.angVel = (.1,0,0)
for i in range(20):
   O.step()
   rot,ori = updateRot(b,rot,ori)
   print i,rot
###

Leonard (z2521899293) said : #6

Thanks Jan Stránský, that solved my question.