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

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?

Have a good weekend
Leonard

## Question information

Language:
English Edit question
Status:
Solved
For:
Assignee:
No assignee Edit question
Solved by:
Jan Stránský
Solved:
2020-07-26
Last query:
2020-07-26
2020-07-26
 Jan Stránský (honzik) said on 2020-07-25: #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 . it is angle equivalent of state.displ() , 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  (from comment #14 on) if this your case

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

cheers
Jan

 Leonard (z2521899293) said on 2020-07-25: #2

Hi Jan,

>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 on 2020-07-25: #3

> How to calculate this incremental rotation angle?

see  for discussion (code below)

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) < 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 on 2020-07-25: #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 or (axis) < 0 or (axis) < 0:
angle *= -1
.....

Many thanks
Leonard Jan Stránský (honzik) said on 2020-07-26: #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 on 2020-07-26: #6

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