Converting from a different rotation system.

Need help, or want to share a macro? Post here!
Forum rules
Be nice to others! Respect the FreeCAD code of conduct!
openBrain
Veteran
Posts: 9041
Joined: Fri Nov 09, 2018 5:38 pm
Contact:

Re: Converting from a different rotation system.

Post by openBrain »

ickby wrote: Fri Feb 05, 2021 7:35 pm So two totally different thing and hence you cannot compare the results (except for some lucky cases)
While it may not be intuitive, these are actually not so different things. Indeed an extrinsic XYZ rotation (what you called 'fixed frame') is equivalent to an intrinsic zy'x'' one (what you called 'internal frame'). ;)
onekk wrote: Fri Feb 05, 2021 7:39 pm When specificing three values for rotation FreeCAD is usign euler angles,

To be precise, it isn't Euler angles. It's Tait-Bryan angles. Euler angles use twice the same axis (for first and third rotation). But this is a general confusion. :)

under Yaw-Pitch and Roll it show this example

Here is something really disturbing in FreeCAD. Actually this isn't yaw/pitch/roll. These terms are to be specifically used for intrinsic angles used in a zy'x'' rotation. As FC uses xy'z'', they shall not be used. But I've already grumbled too much about that. :P
keithsloan52 wrote: Fri Feb 05, 2021 8:20 pm What I really still need is a way getting from am existing placement back to the three angles
Formulas exist, but you absolutely have to determine in which rotation system you want the angles.
ickby
Veteran
Posts: 3116
Joined: Wed Oct 05, 2011 7:36 am

Re: Converting from a different rotation system.

Post by ickby »

Code: Select all

 What I really still need is a way getting from am existing placement back to the three angles 
Rotation class has method toEuler().
keithsloan52
Veteran
Posts: 2764
Joined: Mon Feb 27, 2012 5:31 pm

Re: Converting from a different rotation system.

Post by keithsloan52 »

ickby wrote: Fri Feb 05, 2021 9:00 pm

Code: Select all

 What I really still need is a way getting from am existing placement back to the three angles 
Rotation class has method toEuler().
toEuler() does not seem to produce the rights angles, I think its is assuming FreeCAD intrinsic angles.

Here is some imported objects using ( which displays correctly )

Code: Select all

        rotX = FreeCAD.Rotation(FreeCAD.Vector(1,0,0), -x)
        rotY = FreeCAD.Rotation(FreeCAD.Vector(0,1,0), -y)
        rotZ = FreeCAD.Rotation(FreeCAD.Vector(0,0,1), -z)

        rot = rotX.multiply(rotY).multiply(rotZ)
        placement = FreeCAD.Placement(base, FreeCAD.Rotation(rot))
3A345D19-D265-4A36-B5F0-E0F46E74709D_4_5005_c.jpeg
3A345D19-D265-4A36-B5F0-E0F46E74709D_4_5005_c.jpeg (11.82 KiB) Viewed 1422 times
Exporting using toEuler and then importing gives
1F21EB01-018E-4481-8575-E81FC4B2C0E6_4_5005_c.jpeg
1F21EB01-018E-4481-8575-E81FC4B2C0E6_4_5005_c.jpeg (7.58 KiB) Viewed 1422 times
Works for some Objects but not for others
keithsloan52
Veteran
Posts: 2764
Joined: Mon Feb 27, 2012 5:31 pm

Re: Converting from a different rotation system.

Post by keithsloan52 »

For example if I import an Object with unit="deg" x="10" y="20" z="30" code as above and then export using toEuler I get unit="deg" x="-1.1160546770046433" y="22.24218091030951" z="28.45177525658553"/>
I suspect that as I have

Code: Select all

rotX = FreeCAD.Rotation(FreeCAD.Vector(1,0,0), -x)
        rotY = FreeCAD.Rotation(FreeCAD.Vector(0,1,0), -y)
        rotZ = FreeCAD.Rotation(FreeCAD.Vector(0,0,1), -z)

        rot = rotX.multiply(rotY).multiply(rotZ)
        placement = FreeCAD.Placement(base, FreeCAD.Rotation(rot))
The fact that I have to use -x, -y, -z there is a difference in Axis that is throwing toEuler out?
User avatar
onekk
Veteran
Posts: 6222
Joined: Sat Jan 17, 2015 7:48 am
Contact:

Re: Converting from a different rotation system.

Post by onekk »

Euler angles in FreeCAD could be specified in many ways (24 if i didn't go wrong), I don't recall well the forum post, but one of the main developer has improved the "euler" angles specifications to include all this

see: https://forum.freecadweb.org/viewtopic. ... er#p358663

All the thread could be interesting.

To complicate things, if you are copying or doing some operation on a object the Placement position is copied but is set as the Base property so the Placement property will read all zero, not all "trasformations" are doing this "incorporation" but some have this peculiarity, you have to inspect objects for the different things.

Below this line is some mumbling about Rotation, they are an illustration on how to dig into FreeCAD sources to put together some informations.

This is more an illustration of my way of insepcting sources than an autoritathive explnanation. Take it as it is some thingking about an argument, maybe you will find something useful, maybe not.

Placement is somewhat a mess, as it internally store the combination of translation and rotation as a quaternion.

see FreeCAD/src/Base/PlacementPy.xml

Code: Select all

   		<UserDocu>Placement
A placement defines an orientation (rotation) and a position (base) in 3D space.
It is used when no scaling or other distortion is needed.

The following constructors are supported:
Placement() -- empty constructor
Placement(Placement) -- copy constructor
Placement(Matrix) -- 4D matrix consisting of rotation and translation
Placement(Base, Rotation) -- define position and rotation
Placement(Base, Rotation,Center) -- define position and rotation with center
Placement(Base, Axis, Angle) -- define position and rotation
		</UserDocu>
but note that:

Code: Select all

print(pl)
Placement [Pos=(0,0,0), Yaw-Pitch-Roll=(0,0,0)]
>>> print(pl.Matrix)
Matrix ((1,0,0,0),(0,1,0,0),(0,0,1,0),(0,0,0,1))
>>> print(dir(pl.Matrix))
['A', 'A11', 'A12', 'A13', 'A14', 'A21', 'A22', 'A23', 'A24', 'A31', 'A32', 'A33', 'A34', 'A41', 'A42', 'A43', 'A44', '__abs__', '__add__', '__and__', '__bool__', '__class__', '__delattr__', '__dir__', '__divmod__', '__doc__', '__eq__', '__float__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__int__', '__invert__', '__le__', '__lshift__', '__lt__', '__mod__', '__mul__', '__ne__', '__neg__', '__new__', '__or__', '__pos__', '__pow__', '__radd__', '__rand__', '__rdivmod__', '__reduce__', '__reduce_ex__', '__repr__', '__rlshift__', '__rmod__', '__rmul__', '__ror__', '__rpow__', '__rrshift__', '__rshift__', '__rsub__', '__rtruediv__', '__rxor__', '__setattr__', '__sizeof__', '__str__', '__sub__', '__subclasshook__', '__truediv__', '__xor__', 'analyze', 'determinant', 'hasScale', 'inverse', 'invert', 'isOrthogonal', 'move', 'multVec', 'multiply', 'rotateX', 'rotateY', 'rotateZ', 'scale', 'submatrix', 'transform', 'transpose', 'transposed', 'unity']
>>> print(dir(pl.Rotation))
['Angle', 'Axis', 'Q', 'RawAxis', '__abs__', '__add__', '__and__', '__bool__', '__class__', '__delattr__', '__dir__', '__divmod__', '__doc__', '__eq__', '__float__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__int__', '__invert__', '__le__', '__lshift__', '__lt__', '__mod__', '__mul__', '__ne__', '__neg__', '__new__', '__or__', '__pos__', '__pow__', '__radd__', '__rand__', '__rdivmod__', '__reduce__', '__reduce_ex__', '__repr__', '__rlshift__', '__rmod__', '__rmul__', '__ror__', '__rpow__', '__rrshift__', '__rshift__', '__rsub__', '__rtruediv__', '__rxor__', '__setattr__', '__sizeof__', '__str__', '__sub__', '__subclasshook__', '__truediv__', '__xor__', 'invert', 'inverted', 'isIdentity', 'isNull', 'isSame', 'multVec', 'multiply', 'slerp', 'toEuler', 'toMatrix']
>>> 

and in https://github.com/FreeCAD/FreeCAD/blob ... nPyImp.cpp

Code: Select all

PyObject* RotationPy::toEuler(PyObject * args)
{
    if (!PyArg_ParseTuple(args, ""))
        return NULL;
    double A,B,C;
    this->getRotationPtr()->getYawPitchRoll(A,B,C);

    Py::Tuple tuple(3);
    tuple.setItem(0, Py::Float(A));
    tuple.setItem(1, Py::Float(B));
    tuple.setItem(2, Py::Float(C));
    return Py::new_reference_to(tuple);
}

and from https://github.com/FreeCAD/FreeCAD/blob ... tionPy.xml

Code: Select all

<UserDocu>
				A Rotation using a quaternion.
				The Rotation object can be created by:
				-- an empty parameter list
				-- a Rotation object
				-- a Vector (axis) and a float (angle)
				-- two Vectors (rotation from/to vector)
				-- three floats (Euler angles) as yaw-pitch-roll in XY'Z'' convention
				-- four floats (Quaternion) where the quaternion is specified as:
				   q=xi+yj+zk+w, i.e. the last parameter is the real part
				-- three vectors that define rotated axes directions + an optional
				   3-characher string of capital letters 'X', 'Y', 'Z' that sets the
				   order of importance of the axes (e.g., 'ZXY' means z direction is
				   followed strictly, x is used but corrected if necessary, y is ignored).
			</UserDocu>
but also in the same file the "help" form the programmer that explains some things.

This is what there is in the source inspected today.

All the documentation on the wiki is to be considered a primer, when doing something more advanced, better to "go to the source", many gems are hidden maybe in a comment or a commented out part of code.

Hope it will help and to add more confusion.

Regards

Carlo D.
GitHub page: https://github.com/onekk/freecad-doc.
- In deep articles on FreeCAD.
- Learning how to model with scripting.
- Various other stuffs.

Blog: https://okkmkblog.wordpress.com/
openBrain
Veteran
Posts: 9041
Joined: Fri Nov 09, 2018 5:38 pm
Contact:

Re: Converting from a different rotation system.

Post by openBrain »

onekk wrote: Sat Feb 06, 2021 10:46 am Euler angles in FreeCAD could be specified in many ways (24 if i didn't go wrong), I don't recall well the forum post, but one of the main developer has improved the "euler" angles specifications to include all this

see: https://forum.freecadweb.org/viewtopic. ... er#p358663
I know this thread quite well. :)
I think there is a confusion. In the help message you quoted, the rotation (in the case where you can specify an axis order) is specified as 3 vectors, and not as 3 angles. I admit I have no clue how it can relate to Euler angles, and maybe even it doesn't directly.
Also notice that the 24 cases aren't covered.
First, it doesn't accept twice the same axis, thus the 12 real Euler angles aren't supported.
Also it doesn't support both intrinsic & extrinsic systems (I don't know which one it accepts, my guess is extrinsic), so again 6 Tait-Bryan angles aren't supported.
Finally only 6 variations of Tait-Bryan angles are supported (among 24 possible "Euler" angles). ;)

But what is interesting in @wmayer's post you pointed is that there seems to be all systems available in OCC. Now one has to find ad play with the OCC API. :)
User avatar
onekk
Veteran
Posts: 6222
Joined: Sat Jan 17, 2015 7:48 am
Contact:

Re: Converting from a different rotation system.

Post by onekk »

On some other post if I didn't rember bad, wmayer had told that he has implemented all 24 angles, but maybe the setting is hidden somewhere.

EDIT: after some research i didn't find anything and I've seen that OpenBrain is involved in amost all discussions about this arguments, so no need to complicate things as his knowledge is far more deep than mine.

Follow his advice and sorry for the inconvenience.

Regards

Carlo D.
GitHub page: https://github.com/onekk/freecad-doc.
- In deep articles on FreeCAD.
- Learning how to model with scripting.
- Various other stuffs.

Blog: https://okkmkblog.wordpress.com/
realthunder
Veteran
Posts: 2190
Joined: Tue Jan 03, 2017 10:55 am

Re: Converting from a different rotation system.

Post by realthunder »

keithsloan52 wrote: Fri Feb 05, 2021 2:31 pm I am trying to deal with some software that specifies rotation as x=<value> y=<value> z=<value>, where the values are passes as either degrees or radians ( Different parameter). As it is possible for more than one axis to be specified the order is important and this system does x rotation, then y, then z. What is the best way to go from the three values x,y,z to a FreeCAD placement rotation? Do I have to go via three separate rotations?
I have just added this capability to FreeCAD.Rotation.

Use FreeCAD.Rotation(seq, a, b, c) to create a rotation with rotation sequence 'seq', and angles a, b, c in degree. Use function Rotation.toEulerAngles(seq) to obtain the angles. Call this function without argument to obtain all possible sequence types. Intrinsic sequences is prefixed with 'i', while extrinsic ones has no prefix. Your pattern looks like an intrinsic rotation sequence with order xyz, so seq='ixyz'. I'll make a new release of my branch with the feature. I'll also submit a PR for this soon.

I borrow the code from OCCT gp_Quaternion::Get/SetEulerAngles().

The following Python code can be used for verification, e.g. checkRot('ixyz', 10, 20, 30)

Code: Select all

def checkRot(seq, a, b, c):
    rot = FreeCAD.Rotation()
    if seq[0] == 'i':
        for axis,angle in zip(seq[1:], (a, b, c)):
            if axis == 'x':
                rot *= FreeCAD.Rotation(FreeCAD.Vector(1,0,0), angle)
            elif axis == 'y':
                rot *= FreeCAD.Rotation(FreeCAD.Vector(0,1,0), angle)
            else:
                rot *= FreeCAD.Rotation(FreeCAD.Vector(0,0,1), angle)
    else:
        for axis,angle in zip(seq, (a, b, c)):
            if axis == 'x':
                rot *= FreeCAD.Rotation(rot.inverted()*FreeCAD.Vector(1,0,0), angle)
            elif axis == 'y':
                rot *= FreeCAD.Rotation(rot.inverted()*FreeCAD.Vector(0,1,0), angle)
            else:
                rot *= FreeCAD.Rotation(rot.inverted()*FreeCAD.Vector(0,0,1), angle)

    print(rot.toEulerAngles(seq))
    return FreeCAD.Rotation(seq, a, b, c).isSame(rot, 1e-12)
Try Assembly3 with my custom build of FreeCAD at here.
And if you'd like to show your support, you can donate through patreon, liberapay, or paypal
keithsloan52
Veteran
Posts: 2764
Joined: Mon Feb 27, 2012 5:31 pm

Re: Converting from a different rotation system.

Post by keithsloan52 »

realthunder wrote: Sun Mar 07, 2021 10:17 am
keithsloan52 wrote: Fri Feb 05, 2021 2:31 pm I am trying to deal with some software that specifies rotation as x=<value> y=<value> z=<value>, where the values are passes as either degrees or radians ( Different parameter). As it is possible for more than one axis to be specified the order is important and this system does x rotation, then y, then z. What is the best way to go from the three values x,y,z to a FreeCAD placement rotation? Do I have to go via three separate rotations?
I have just added this capability to FreeCAD.Rotation.

Use FreeCAD.Rotation(seq, a, b, c) to create a rotation with rotation sequence 'seq', and angles a, b, c in degree. Use function Rotation.toEulerAngles(seq) to obtain the angles. Call this function without argument to obtain all possible sequence types. Intrinsic sequences is prefixed with 'i', while extrinsic ones has no prefix. Your pattern looks like an intrinsic rotation sequence with order xyz, so seq='ixyz'. I'll make a new release of my branch with the feature. I'll also submit a PR for this soon.

I borrow the code from OCCT gp_Quaternion::Get/SetEulerAngles().

The following Python code can be used for verification, e.g. checkRot('ixyz', 10, 20, 30)

Code: Select all

def checkRot(seq, a, b, c):
    rot = FreeCAD.Rotation()
    if seq[0] == 'i':
        for axis,angle in zip(seq[1:], (a, b, c)):
            if axis == 'x':
                rot *= FreeCAD.Rotation(FreeCAD.Vector(1,0,0), angle)
            elif axis == 'y':
                rot *= FreeCAD.Rotation(FreeCAD.Vector(0,1,0), angle)
            else:
                rot *= FreeCAD.Rotation(FreeCAD.Vector(0,0,1), angle)
    else:
        for axis,angle in zip(seq, (a, b, c)):
            if axis == 'x':
                rot *= FreeCAD.Rotation(rot.inverted()*FreeCAD.Vector(1,0,0), angle)
            elif axis == 'y':
                rot *= FreeCAD.Rotation(rot.inverted()*FreeCAD.Vector(0,1,0), angle)
            else:
                rot *= FreeCAD.Rotation(rot.inverted()*FreeCAD.Vector(0,0,1), angle)

    print(rot.toEulerAngles(seq))
    return FreeCAD.Rotation(seq, a, b, c).isSame(rot, 1e-12)
Look forward to testing. I guess given feature freeze it will be in 0.20 rather than 0.19, would have been good to have it make production 0.19.
realthunder
Veteran
Posts: 2190
Joined: Tue Jan 03, 2017 10:55 am

Re: Converting from a different rotation system.

Post by realthunder »

keithsloan52 wrote: Sun Mar 07, 2021 4:38 pm Look forward to testing. I guess given feature freeze it will be in 0.20 rather than 0.19, would have been good to have it make production 0.19.
Yes, PR submitted now probably will just be pending till 0.20 starts. You can test it with my release first.
Try Assembly3 with my custom build of FreeCAD at here.
And if you'd like to show your support, you can donate through patreon, liberapay, or paypal
Post Reply