Can't set rotation for Link correctly

General Information

  • Product: NxLib
  • Ensenso SDK Version: 3.6.1621
  • Operating System: Windows

Problem / Question

Hi,
I’m trying to specify a transformation in the Links node by setting the translation and angle-axis rotation. When I print the resulting link, the rotation axis does not match the specified values, e.g. the third item is 0.471 but should be 0.534. Why does this happen and how can I fix it? I’ve added a piece of code that reproduces the problem.

Edit: this only seems to happen when specifying Inverse = True.

Code

from nxlib import NxLibItem
from nxlib.constants import *
from nxlib.context import NxLib

with NxLib():
    links = NxLibItem()[ITM_LINKS]
    flange = links["Flange"]
    flange[ITM_TARGET] = "Workspace"
    flange[ITM_INVERSE] = True
    flange[ITM_ROTATION][ITM_ANGLE] = 0.23
    flange[ITM_ROTATION][ITM_AXIS][0] = 0.802
    flange[ITM_ROTATION][ITM_AXIS][1] = 0.267
    flange[ITM_ROTATION][ITM_AXIS][2] = 0.534
    flange[ITM_TRANSLATION][0] = 100
    flange[ITM_TRANSLATION][1] = 150
    flange[ITM_TRANSLATION][2] = 180

    print(flange.as_json())

Output

{
        "Inverse": true,
        "Rotation": {
                "Angle": 0.230000000000000204,
                "Axis": [
                        0.852253420868689271,
                        0.227551663371939966,
                        0.471046013797251251
                ]
        },
        "Target": "Workspace",
        "Translation": [
                100.000000000000014211,
                150,
                180
        ]
}

Hi @init,

thank you for posting! This is indeed one of the small caveats when dealing with transformations in Angle/Axis rotation notation in EnsensoSDK.

As stated on the Transformation topic, the Axis vector can be specified unnormalized:

Axis - A Vector specifying the axis of rotation. This vector is normalized when rotations are returned via the API. Although it does not need to be normalized when specifying a rotation.

But that means it will be renormalized after writing any of its components. In your case, after your line flange[ITM_ROTATION][ITM_AXIS][0] = 0.802; the vector will be renormalized with the Y and Z component that was already there from before. Which is likely not what you want.

Of course you want to set all Axis components at once, before the vector is renormalized. To accomplish that you need to set the axis in a single write operation using NxLibItem::setJson(std::string const& jsonValue).

Or when using Eigen as linear algebra library you can also use NxLibItem::set(Eigen::Matrix<double,...> const& matrix) with a three element column vector, to specify the axis in a single, atomic operation.

As an example using the json array notation to specify the axis vector this would look like this:

flange[ITM_ROTATION][ITM_AXIS] << "[0.802, 0.267, 0.534]";

Note that operator<< is just a shorthand for NxLibItem::setJson(...) with onlyWriteableNodes = true.

EDIT

I just checked the operators again, but the Eigen overloads don’t set the elements in an atomic fashion!

or alternatively in Eigen:
flange[ITM_ROTATION][ITM_AXIS] = Eigen::Vector3d(0.802, 0.267, 0.534);