composing Euler rotation matrices

classic Classic list List threaded Threaded
7 messages Options
Seb
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

composing Euler rotation matrices

Seb
Hello,

I'm trying to compose Euler rotation matrices shown in
https://en.wikipedia.org/wiki/Euler_angles#Rotation_matrix.  For
example, The Z1Y2X3 Tait-Bryan rotation shown in the table can be
represented in Numpy using the function:

def z1y2x3(alpha, beta, gamma):
    """Rotation matrix given Euler angles"""
    return np.array([[np.cos(alpha) * np.cos(beta),
                      np.cos(alpha) * np.sin(beta) * np.sin(gamma) -
                      np.cos(gamma) * np.sin(alpha),
                      np.sin(alpha) * np.sin(gamma) +
                      np.cos(alpha) * np.cos(gamma) * np.sin(beta)],
                     [np.cos(beta) * np.sin(alpha),
                      np.cos(alpha) * np.cos(gamma) +
                      np.sin(alpha) * np.sin(beta) * np.sin(gamma),
                      np.cos(gamma) * np.sin(alpha) * np.sin(beta) -
                      np.cos(alpha) * np.sin(gamma)],
                     [-np.sin(beta), np.cos(beta) * np.sin(gamma),
                      np.cos(beta) * np.cos(gamma)]])

which given alpha, beta, gamma as:

angles = np.radians(np.array([30, 20, 10]))

returns the following matrix:

In [31]: z1y2x3(angles[0], angles[1], angles[2])
Out[31]:

array([[ 0.81379768, -0.44096961,  0.37852231],
       [ 0.46984631,  0.88256412,  0.01802831],
       [-0.34202014,  0.16317591,  0.92541658]])

If I understand correctly, one should be able to compose this matrix by
multiplying the rotation matrices that it is made of.  However, I cannot
reproduce this matrix via composition; i.e. by multiplying the
underlying rotation matrices.  Any tips would be appreciated.

--
Seb

_______________________________________________
NumPy-Discussion mailing list
[hidden email]
https://mail.scipy.org/mailman/listinfo/numpy-discussion
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: composing Euler rotation matrices

Joseph Fox-Rabinovitz
Could you show what you are doing to get the statement "However, I cannot reproduce this matrix via composition; i.e. by multiplying the underlying rotation matrices.". I would guess something involving the `*` operator instead of `@`, but guessing probably won't help you solve your issue.

    -Joe



On Tue, Jan 31, 2017 at 7:56 PM, Seb <[hidden email]> wrote:
Hello,

I'm trying to compose Euler rotation matrices shown in
https://en.wikipedia.org/wiki/Euler_angles#Rotation_matrix.  For
example, The Z1Y2X3 Tait-Bryan rotation shown in the table can be
represented in Numpy using the function:

def z1y2x3(alpha, beta, gamma):
    """Rotation matrix given Euler angles"""
    return np.array([[np.cos(alpha) * np.cos(beta),
                      np.cos(alpha) * np.sin(beta) * np.sin(gamma) -
                      np.cos(gamma) * np.sin(alpha),
                      np.sin(alpha) * np.sin(gamma) +
                      np.cos(alpha) * np.cos(gamma) * np.sin(beta)],
                     [np.cos(beta) * np.sin(alpha),
                      np.cos(alpha) * np.cos(gamma) +
                      np.sin(alpha) * np.sin(beta) * np.sin(gamma),
                      np.cos(gamma) * np.sin(alpha) * np.sin(beta) -
                      np.cos(alpha) * np.sin(gamma)],
                     [-np.sin(beta), np.cos(beta) * np.sin(gamma),
                      np.cos(beta) * np.cos(gamma)]])

which given alpha, beta, gamma as:

angles = np.radians(np.array([30, 20, 10]))

returns the following matrix:

In [31]: z1y2x3(angles[0], angles[1], angles[2])
Out[31]:

array([[ 0.81379768, -0.44096961,  0.37852231],
       [ 0.46984631,  0.88256412,  0.01802831],
       [-0.34202014,  0.16317591,  0.92541658]])

If I understand correctly, one should be able to compose this matrix by
multiplying the rotation matrices that it is made of.  However, I cannot
reproduce this matrix via composition; i.e. by multiplying the
underlying rotation matrices.  Any tips would be appreciated.

--
Seb

_______________________________________________
NumPy-Discussion mailing list
[hidden email]
https://mail.scipy.org/mailman/listinfo/numpy-discussion


_______________________________________________
NumPy-Discussion mailing list
[hidden email]
https://mail.scipy.org/mailman/listinfo/numpy-discussion
Seb
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: composing Euler rotation matrices

Seb
On Tue, 31 Jan 2017 21:23:55 -0500,
Joseph Fox-Rabinovitz <[hidden email]> wrote:

> Could you show what you are doing to get the statement "However, I
> cannot reproduce this matrix via composition; i.e. by multiplying the
> underlying rotation matrices.". I would guess something involving the
> `*` operator instead of `@`, but guessing probably won't help you
> solve your issue.

Sure, although composition is not something I can take credit for, as
it's a well-described operation for generating linear transformations.
It is the matrix multiplication of two or more transformation matrices.
In the case of Euler transformations, it's matrices specifying rotations
around 3 orthogonal axes by 3 given angles.  I'm using `numpy.dot' to
perform matrix multiplication on 2D arrays representing matrices.

However, it's not obvious from the link I provided what particular
rotation matrices are multiplied and in what order (i.e. what
composition) is used to arrive at the Z1Y2X3 rotation matrix shown.
Perhaps I'm not understanding the conventions used therein.  This is one
of my attempts at reproducing that rotation matrix via composition:

---<--------------------cut here---------------start------------------->---
import numpy as np

angles = np.radians(np.array([30, 20, 10]))

def z1y2x3(alpha, beta, gamma):
    """Z1Y2X3 rotation matrix given Euler angles"""
    return np.array([[np.cos(alpha) * np.cos(beta),
                      np.cos(alpha) * np.sin(beta) * np.sin(gamma) -
                      np.cos(gamma) * np.sin(alpha),
                      np.sin(alpha) * np.sin(gamma) +
                      np.cos(alpha) * np.cos(gamma) * np.sin(beta)],
                     [np.cos(beta) * np.sin(alpha),
                      np.cos(alpha) * np.cos(gamma) +
                      np.sin(alpha) * np.sin(beta) * np.sin(gamma),
                      np.cos(gamma) * np.sin(alpha) * np.sin(beta) -
                      np.cos(alpha) * np.sin(gamma)],
                     [-np.sin(beta), np.cos(beta) * np.sin(gamma),
                      np.cos(beta) * np.cos(gamma)]])

euler_mat = z1y2x3(angles[0], angles[1], angles[2])

## Now via composition

def rotation_matrix(theta, axis, active=False):
    """Generate rotation matrix for a given axis

    Parameters
    ----------

    theta: numeric, optional
        The angle (degrees) by which to perform the rotation.  Default is
        0, which means return the coordinates of the vector in the rotated
        coordinate system, when rotate_vectors=False.
    axis: int, optional
        Axis around which to perform the rotation (x=0; y=1; z=2)
    active: bool, optional
        Whether to return active transformation matrix.

    Returns
    -------
    numpy.ndarray
    3x3 rotation matrix
    """
    theta = np.radians(theta)
    if axis == 0:
        R_theta = np.array([[1, 0, 0],
                            [0, np.cos(theta), -np.sin(theta)],
                            [0, np.sin(theta), np.cos(theta)]])
    elif axis == 1:
        R_theta = np.array([[np.cos(theta), 0, np.sin(theta)],
                            [0, 1, 0],
                            [-np.sin(theta), 0, np.cos(theta)]])
    else:
        R_theta = np.array([[np.cos(theta), -np.sin(theta), 0],
                            [np.sin(theta), np.cos(theta), 0],
                            [0, 0, 1]])
    if active:
        R_theta = np.transpose(R_theta)
    return R_theta

## The rotations are given as active
xmat = rotation_matrix(angles[2], 0, active=True)
ymat = rotation_matrix(angles[1], 1, active=True)
zmat = rotation_matrix(angles[0], 2, active=True)
## The operation seems to imply this composition
euler_comp_mat = np.dot(xmat, np.dot(ymat, zmat))
---<--------------------cut here---------------end--------------------->---

I believe the matrices `euler_mat' and `euler_comp_mat' should be the
same, but they aren't, so it's unclear to me what particular composition
is meant to produce the matrix specified by this Z1Y2X3 transformation.
What am I missing?

--
Seb

_______________________________________________
NumPy-Discussion mailing list
[hidden email]
https://mail.scipy.org/mailman/listinfo/numpy-discussion
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: composing Euler rotation matrices

Robert McLeod
Instead of trying to decipher what someone wrote on a Wikipedia, why don't you look at a working piece of source code?

e.g.


Robert


On Wed, Feb 1, 2017 at 4:27 AM, Seb <[hidden email]> wrote:
On Tue, 31 Jan 2017 21:23:55 -0500,
Joseph Fox-Rabinovitz <[hidden email]> wrote:

> Could you show what you are doing to get the statement "However, I
> cannot reproduce this matrix via composition; i.e. by multiplying the
> underlying rotation matrices.". I would guess something involving the
> `*` operator instead of `@`, but guessing probably won't help you
> solve your issue.

Sure, although composition is not something I can take credit for, as
it's a well-described operation for generating linear transformations.
It is the matrix multiplication of two or more transformation matrices.
In the case of Euler transformations, it's matrices specifying rotations
around 3 orthogonal axes by 3 given angles.  I'm using `numpy.dot' to
perform matrix multiplication on 2D arrays representing matrices.

However, it's not obvious from the link I provided what particular
rotation matrices are multiplied and in what order (i.e. what
composition) is used to arrive at the Z1Y2X3 rotation matrix shown.
Perhaps I'm not understanding the conventions used therein.  This is one
of my attempts at reproducing that rotation matrix via composition:

---<--------------------cut here---------------start------------------->---
import numpy as np

angles = np.radians(np.array([30, 20, 10]))

def z1y2x3(alpha, beta, gamma):
    """Z1Y2X3 rotation matrix given Euler angles"""
    return np.array([[np.cos(alpha) * np.cos(beta),
                      np.cos(alpha) * np.sin(beta) * np.sin(gamma) -
                      np.cos(gamma) * np.sin(alpha),
                      np.sin(alpha) * np.sin(gamma) +
                      np.cos(alpha) * np.cos(gamma) * np.sin(beta)],
                     [np.cos(beta) * np.sin(alpha),
                      np.cos(alpha) * np.cos(gamma) +
                      np.sin(alpha) * np.sin(beta) * np.sin(gamma),
                      np.cos(gamma) * np.sin(alpha) * np.sin(beta) -
                      np.cos(alpha) * np.sin(gamma)],
                     [-np.sin(beta), np.cos(beta) * np.sin(gamma),
                      np.cos(beta) * np.cos(gamma)]])

euler_mat = z1y2x3(angles[0], angles[1], angles[2])

## Now via composition

def rotation_matrix(theta, axis, active=False):
    """Generate rotation matrix for a given axis

    Parameters
    ----------

    theta: numeric, optional
        The angle (degrees) by which to perform the rotation.  Default is
        0, which means return the coordinates of the vector in the rotated
        coordinate system, when rotate_vectors=False.
    axis: int, optional
        Axis around which to perform the rotation (x=0; y=1; z=2)
    active: bool, optional
        Whether to return active transformation matrix.

    Returns
    -------
    numpy.ndarray
    3x3 rotation matrix
    """
    theta = np.radians(theta)
    if axis == 0:
        R_theta = np.array([[1, 0, 0],
                            [0, np.cos(theta), -np.sin(theta)],
                            [0, np.sin(theta), np.cos(theta)]])
    elif axis == 1:
        R_theta = np.array([[np.cos(theta), 0, np.sin(theta)],
                            [0, 1, 0],
                            [-np.sin(theta), 0, np.cos(theta)]])
    else:
        R_theta = np.array([[np.cos(theta), -np.sin(theta), 0],
                            [np.sin(theta), np.cos(theta), 0],
                            [0, 0, 1]])
    if active:
        R_theta = np.transpose(R_theta)
    return R_theta

## The rotations are given as active
xmat = rotation_matrix(angles[2], 0, active=True)
ymat = rotation_matrix(angles[1], 1, active=True)
zmat = rotation_matrix(angles[0], 2, active=True)
## The operation seems to imply this composition
euler_comp_mat = np.dot(xmat, np.dot(ymat, zmat))
---<--------------------cut here---------------end--------------------->---

I believe the matrices `euler_mat' and `euler_comp_mat' should be the
same, but they aren't, so it's unclear to me what particular composition
is meant to produce the matrix specified by this Z1Y2X3 transformation.
What am I missing?

--
Seb

_______________________________________________
NumPy-Discussion mailing list
[hidden email]
https://mail.scipy.org/mailman/listinfo/numpy-discussion



--
Robert McLeod, Ph.D.
Center for Cellular Imaging and Nano Analytics (C-CINA)
Biozentrum der Universität Basel
Mattenstrasse 26, 4058 Basel
Work: +41.061.387.3225
[hidden email]

_______________________________________________
NumPy-Discussion mailing list
[hidden email]
https://mail.scipy.org/mailman/listinfo/numpy-discussion
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: composing Euler rotation matrices

Matthew Brett
Hi,

On Wed, Feb 1, 2017 at 8:28 AM, Robert McLeod <[hidden email]> wrote:
> Instead of trying to decipher what someone wrote on a Wikipedia, why don't
> you look at a working piece of source code?
>
> e.g.
>
> https://github.com/3dem/relion/blob/master/src/euler.cpp

Also - have a look at https://pypi.python.org/pypi/transforms3d - and
in particular you might get some use from symbolic versions of the
transformations, e.g. here :
https://github.com/matthew-brett/transforms3d/blob/master/transforms3d/derivations/eulerangles.py

It's really easy to mix up the conventions, as I'm sure you know - see
http://matthew-brett.github.io/transforms3d/reference/transforms3d.euler.html

Cheers,

Matthew
_______________________________________________
NumPy-Discussion mailing list
[hidden email]
https://mail.scipy.org/mailman/listinfo/numpy-discussion
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: composing Euler rotation matrices

Stuart Reynolds
[off topic]
Nothing good ever comes from using Euler matrices. All the cool kids a using quaternions these days. They're (in some ways) simpler, can be interpolated easily, don't suffer from gimbal lock (discontinuity), and are not confused about which axis rotation is applied first (for Euler you much decide whether you want to apply x.y.z or z.y.x).

They'd be a good addition to numpy.



On Wed, Feb 1, 2017 at 1:42 AM, Matthew Brett <[hidden email]> wrote:
Hi,

On Wed, Feb 1, 2017 at 8:28 AM, Robert McLeod <[hidden email]> wrote:
> Instead of trying to decipher what someone wrote on a Wikipedia, why don't
> you look at a working piece of source code?
>
> e.g.
>
> https://github.com/3dem/relion/blob/master/src/euler.cpp

Also - have a look at https://pypi.python.org/pypi/transforms3d - and
in particular you might get some use from symbolic versions of the
transformations, e.g. here :
https://github.com/matthew-brett/transforms3d/blob/master/transforms3d/derivations/eulerangles.py

It's really easy to mix up the conventions, as I'm sure you know - see
http://matthew-brett.github.io/transforms3d/reference/transforms3d.euler.html

Cheers,

Matthew
_______________________________________________
NumPy-Discussion mailing list
[hidden email]
https://mail.scipy.org/mailman/listinfo/numpy-discussion


_______________________________________________
NumPy-Discussion mailing list
[hidden email]
https://mail.scipy.org/mailman/listinfo/numpy-discussion
Seb
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: composing Euler rotation matrices

Seb
In reply to this post by Matthew Brett
On Wed, 1 Feb 2017 09:42:15 +0000,
Matthew Brett <[hidden email]> wrote:

> Hi,
> On Wed, Feb 1, 2017 at 8:28 AM, Robert McLeod <[hidden email]> wrote:
>> Instead of trying to decipher what someone wrote on a Wikipedia, why
>> don't you look at a working piece of source code?

>> e.g.

>> https://github.com/3dem/relion/blob/master/src/euler.cpp

> Also - have a look at https://pypi.python.org/pypi/transforms3d - and
> in particular you might get some use from symbolic versions of the
> transformations, e.g. here :
> https://github.com/matthew-brett/transforms3d/blob/master/transforms3d/derivations/eulerangles.py

> It's really easy to mix up the conventions, as I'm sure you know - see
> http://matthew-brett.github.io/transforms3d/reference/transforms3d.euler.html

Thank you very much for providing this package.  It looks like this is
exactly what I was trying to do (learn).  The symbolic versions really
help show what is going on in the derivations sub-package by showing how
each of the 9 matrix elements are found.  I'll try to hack it to use
active rotations.

--
Seb

_______________________________________________
NumPy-Discussion mailing list
[hidden email]
https://mail.scipy.org/mailman/listinfo/numpy-discussion
Loading...