Model root feature orientation


I want to create a model to which I programmatically add frames. To give a bit of context, I will add frames to an object that indicate where it can be grasped by a given gripper.

Everything is up and running, however, I noticed that the frames I import do not have the right orientation. As the frames I add to a model are ‘features’ defined relative w.r.t. a ‘root feature’ I decided to investigate there. What I found was strange to me:

I create a root feature, and it seems that this root feature is located at the world origin. The values are greyed out and cannot be changed, but they are all zero as I would expect:

Comparing to the little world reference frame in the top left corner it indeed seems that the root feature has the same orientation as the world origin:

Now, If I run the following lines of Python code to get the quaternion value of the root feature orientation, I expect to get the quaternion [0, 0, 0, 1], corresponding to the unit rotation.

comp = getComponent()
print('rx: ' + str(getComponent().comp.RootFeature.PositionMatrix.O.X))
print('ry: ' + str(getComponent().comp.RootFeature.PositionMatrix.O.Y))
print('rz: ' + str(getComponent().comp.RootFeature.PositionMatrix.O.Z))
print('rw: ' + str(getComponent().comp.RootFeature.PositionMatrix.O.W))

However, I get the following printed out in the terminal:

I tried to directly change the quaternion values through similar lines of Python code, but I could not bring the quaternion to the unit rotation.

The mismatch I see here in the root feature orientation corresponds to what I see propagated in the orientation of the frames I want to add to my model.

Can someone please help me understand this?

Toon Daemen,
Robotics engineer @Flanders Make, Belgium

See vcMatrix in the Python API help. The O vector is orientation, and there is a getQuaternion() method.

Better test code.

  comp = getComponent()
  pos = comp.RootFeature.NodePositionMatrix
  print('Ox: ' + str(pos.O.X))
  print('Oy: ' + str(pos.O.Y))
  print('Oz: ' + str(pos.O.Z))
  print('Ow: ' + str(pos.O.W))
  rot = pos.getQuaternion()
  print('rx: ' + str(rot.X))
  print('ry: ' + str(rot.Y))
  print('rz: ' + str(rot.Z))
  print('rw: ' + str(rot.W))
  worldPos = comp.localToWorld(pos)
  print('W Ox: ' + str(worldPos.O.X))
  print('W Oy: ' + str(worldPos.O.Y))
  print('W Oz: ' + str(worldPos.O.Z))
  print('W Ow: ' + str(worldPos.O.W))
  worldRot = worldPos.getQuaternion()
  print('W rx: ' + str(worldRot.X))
  print('W ry: ' + str(worldRot.Y))
  print('W rz: ' + str(worldRot.Z))
  print('W rw: ' + str(worldRot.W))


I was considering ‘P’ as position vector and ‘O’ as orientation quaternion vector. I was thinking in the wrong direction, probably since this is a convention we use in one of our own applications.
I understand now that ‘O’ is one of the frame’s unit vectors, along with ‘N’ and ‘A’, in that context my output suddenly comes to make sense.

A huge thank you for pointing me to the Python API documentation in the help section. I did not yet find this one before, but this looks like a bible and will be definitely a great and unmissable tool!


Toon Daemen