# Rotations & Transformations

The most common representations for 3D rotations are implemented in RobWork. In this page we will consider the Rotation Matrix, Axis-Angle (EAA), Roll Pitch Yaw Angle (RPY), and Quaternion representations, and how to convert between these representations. Finally, Transformations are considered.

## Rotation Matrix

A 3x3 rotation matrix can be constructed using the Rotation3D type. The default Rotation3D<> type uses double precision, while Rotation3D<float> uses float precision. Notice that it is only possible to specify the templated types in C++. The equivalent types in the script interfaces (Python, Java and LUA) is Rotation3Dd and Rotation3Df for double and float precision respectively.

The constructor for Rotation3D takes the elements of the rotation matrix $$\mathbf{R} = \left[\begin{array}{ccc} r_{11} & r_{12} & r_{13} \\ r_{21} & r_{22} & r_{23} \\ r_{31} & r_{32} & r_{33} \end{array} \right]$$

in the following order: Rotation3D($$r_{11},r_{12},r_{13},r_{21},r_{22},r_{23},r_{31},r_{32},r_{33}$$).

Code examples are shown below for different languages.

Warning

There are two functions for finding the inverse rotation matrix, namely inverse(rot) and rot.inverse(). The inverse(rot) returns a new rotation without altering the original rotation, while rot.inverse() calculates the inverse by changing the original rotation matrix.

C++

1#include <rw/math/Rotation3D.hpp>
2
3using rw::math::Rotation3D;
4
5int main(int argc, char** argv) {
6    Rotation3D<> rotd = Rotation3D<>(1,0,0,0,0,-1,0,1,0);
7    Rotation3D<float> rotf = Rotation3D<float>(1,0,0,0,0,-1,0,1,0);
8
9    std::cout << "Rotation double:" << std::endl << rotd << std::endl;
10    std::cout << "Rotation float:" << std::endl << rotf << std::endl;
11    std::cout << "Rotation inverse:" << std::endl << inverse(rotd) << std::endl;
12    std::cout << "Identity:" << std::endl << rotd*inverse(rotd) << std::endl;
13
14    return 0;
15}

API Reference: rw::math::Rotation3D

Python

1from sdurw import *
2
3if __name__ == '__main__':
4    rotd = Rotation3D(1,0,0,0,0,-1,0,1,0);
5    rotf = Rotation3Df(1,0,0,0,0,-1,0,1,0);
6
7    print("Rotation double:");
8    print(str(rotd));
9    print("Rotation float:");
10    print(str(rotf));
11    print("Rotation inverse:");
12    print(str(inverse(rotd)));
13    print("Identity:");
14    print(str(rotd*inverse(rotd)));
15
16    rotd[2,2] = 25;
17    print("Corner = 25")
18    print(str(rotd))
19
20    if rotd[2,2] == 25:
21        exit(0)
22    else:
23        exit(1)

API Reference:

• rw.Rotation3Dd (double precision)

• rw.Rotation3Df (float precision)

Java

2import org.robwork.sdurw.*;
3import static org.robwork.sdurw.sdurw.*;
4
5public class ExRotation3D {
6    public static void main(String[] args) throws Exception {
8
9        Rotation3Dd rotd = new Rotation3Dd(1,0,0,0,0,-1,0,1,0);
10        Rotation3Df rotf = new Rotation3Df(1,0,0,0,0,-1,0,1,0);
11
12        System.out.println("Rotation double:");
13        System.out.println(rotd);
14        System.out.println("Rotation float:");
15        System.out.println(rotf);
16        System.out.println("Rotation inverse:");
17        System.out.println(rotd.inverse());
18        System.out.println("Identity:");
19        System.out.println(rotd.multiply(inverse(rotd)));
20    }
21}

API Reference:

LUA

1require("sdurw_core")
2require("sdurw")
3using("sdurw")
4require("sdurw_math")
5using("sdurw_math")
6
7rotd = Rotation3D(1,0,0,0,0,-1,0,1,0);
8rotf = Rotation3Df(1,0,0,0,0,-1,0,1,0);
9
10print("Rotation double:");
11print(tostring(rotd));
12print("Rotation float:");
13print(tostring(rotf));
14print("Rotation inverse:");
15print(tostring(inverse(rotd)));
16print("Identity:");
17print(tostring(rotd*inverse(rotd)));

Output

Rotation double:
Rotation3D(1, 0, 0, 0, 0, -1, 0, 1, 0)
Rotation float:
Rotation3D(1, 0, 0, 0, 0, -1, 0, 1, 0)
Rotation inverse:
Rotation3D(1, 0, 0, 0, 0, 1, 0, -1, 0)
Identity:
Rotation3D(1, 0, 0, 0, 1, 0, 0, 0, 1)

## Axis-Angle (EAA)

Equivalent Angle-Axis (EAA) is the RobWork type for rotations defined by the product of a unit vector and an angle of rotation. The direction of the vector gives the axis of rotation, and the length of the vector gives the amount of rotation in radians.

C++

1#include <rw/math/Constants.hpp>
2#include <rw/math/EAA.hpp>
3#include <rw/math/Rotation3D.hpp>
4
5using namespace rw::math;
6
7int main(int argc, char** argv) {
8    const EAA<> eaa = EAA<>(sqrt(2)/2*Pi,sqrt(2)/2*Pi,0);
9    std::cout << "EAA: " << eaa << std::endl;
10    std::cout << " angle: " << eaa.angle() << std::endl;
11    std::cout << " axis: " << eaa.axis() << std::endl;
12    const Rotation3D<> rotationFromEAA = eaa.toRotation3D();
13    std::cout << "Rotation from EAA: " << rotationFromEAA << std::endl;
14
15    const Rotation3D<> rot = Rotation3D<>(-1,0,0,0,0,1,0,1,0);
16    std::cout << "Rotation: " << rot << std::endl;
17    const EAA<> eaaFromRotation = EAA<>(rot);
18    std::cout << "EAA from Rotation: " << eaaFromRotation << std::endl;
19    std::cout << " angle: " << eaaFromRotation.angle() << std::endl;
20    std::cout << " axis: " << eaaFromRotation.axis() << std::endl;
21
22    return 0;
23}

API Reference: rw::math::EAA

Python

1from sdurw_math import *
2import math
3
4if __name__ == '__main__':
5    eaa = EAA(math.sqrt(2)/2*math.pi,math.sqrt(2)/2*math.pi,0)
6    print("EAA: " + str(eaa))
7    print(" angle: " + str(eaa.angle()))
8    print(" axis: " + str(eaa.axis()))
9    rotationFromEAA = eaa.toRotation3D()
10    print("Rotation from EAA: " + str(rotationFromEAA))
11
12    rot = Rotation3D(-1,0,0,0,0,1,0,1,0)
13    print("Rotation: " + str(rot))
14    eaaFromRotation = EAA(rot)
15    print("EAA from Rotation: " + str(eaaFromRotation))
16    print(" angle: " + str(eaaFromRotation.angle()))
17    print(" axis: " + str(eaaFromRotation.axis()))

API Reference:

• rw.EAAf (float precision)

Java

2import org.robwork.sdurw_math.*;
3import static org.robwork.sdurw.sdurwConstants.*;
4import java.lang.Math;
5
6public class ExEAA {
7    public static void main(String[] args) throws Exception {
9
11        System.out.println("EAA: " + eaa);
12        System.out.println(" angle: " + eaa.angle());
13        System.out.println(" axis: " + eaa.axis());
14        Rotation3Dd rotationFromEAA = eaa.toRotation3D();
15        System.out.println("Rotation from RPY: " + rotationFromEAA);
16
17        Rotation3Dd rot = new Rotation3Dd(-1,0,0,0,0,1,0,1,0);
18        System.out.println("Rotation: " + rot);
20        System.out.println("EAA from Rotation: " + eaaFromRotation);
21        System.out.println(" angle: " + eaaFromRotation.angle());
22        System.out.println(" axis: " + eaaFromRotation.axis());
23    }
24}

API Reference:

LUA

1require("sdurw_core")
2require("sdurw")
3using("sdurw")
4require("sdurw_math")
5using("sdurw_math")
6
7eaa = EAA(math.sqrt(2)/2*Pi,math.sqrt(2)/2*Pi,0);
8print("EAA: " .. tostring(eaa))
9print(" angle: " .. eaa:angle())
10print(" axis: " .. tostring(eaa:axis()));
11rotationFromEAA = eaa:toRotation3D();
12print("Rotation from EAA: " .. tostring(rotationFromEAA));
13
14rot = Rotation3D(-1,0,0,0,0,1,0,1,0);
15print("Rotation: " .. tostring(rot));
16eaaFromRotation = EAA(rot);
17print("EAA from Rotation: " .. tostring(eaaFromRotation))
18print(" angle: " .. eaaFromRotation:angle())
19print(" axis: " .. tostring(eaaFromRotation:axis()));

Output

EAA:  EAA { 2.22144, 2.22144, 0}
angle: 3.14159
axis: Vector3D(0.707107, 0.707107, 0)
Rotation from EAA: Rotation3D(2.22045e-16, 1, 8.65956e-17, 1, 2.22045e-16, -8.65956e-17, -8.65956e-17, 8.65956e-17, -1)
Rotation: Rotation3D(-1, 0, 0, 0, 0, 1, 0, 1, 0)
EAA from Rotation:  EAA { 0, 2.22144, 2.22144}
angle: 3.14159
axis: Vector3D(0, 0.707107, 0.707107)

## Roll Pitch Yaw Angle (RPY)

Roll Pitch Yaw angles is one form of Euler angles where the rotation is defined by three consecutive rotations around the axes of a coordinate system. In RobWork, RPY is the rotation around the z, y and x axes (in that order). Notice that the rotation around the y axis is the y axis after doing the rotation around z. The rotation around the x axis is the x axis after doing the rotations around both z and y.

C++

1#include <rw/math/Constants.hpp>
2#include <rw/math/Rotation3D.hpp>
3#include <rw/math/RPY.hpp>
4
5using namespace rw::math;
6
7int main(int argc, char** argv) {
8    const RPY<> rpy = RPY<>(Pi,Pi/2,0);
9    std::cout << "RPY: " << rpy << std::endl;
10    const Rotation3D<> rotationFromRPY = rpy.toRotation3D();
11    std::cout << "Rotation from RPY: " << rotationFromRPY << std::endl;
12
13    const Rotation3D<> rot = Rotation3D<>(-1,0,0,0,0,1,0,1,0);
14    std::cout << "Rotation: " << rot << std::endl;
15    const RPY<> rpyFromRotation = RPY<>(rot);
16    std::cout << "RPY from Rotation: " << rpyFromRotation << std::endl;
17
18    return 0;
19}

API Reference: rw::math::RPY

Python

1from sdurw import *
2
3if __name__ == '__main__':
4    rpy = RPY(Pi,Pi/2,0);
5    print("RPY: " + str(rpy));
6    rotationFromRPY = rpy.toRotation3D();
7    print("Rotation from RPY: " + str(rotationFromRPY));
8
9    rot = Rotation3D(-1,0,0,0,0,1,0,1,0);
10    print("Rotation: " + str(rot));
11    rpyFromRotation = RPY(rot);
12    print("RPY from Rotation: " + str(rpyFromRotation));
13    rot = Rotation3D(1,0,0,0,1,0,0,0,1)

API Reference:

• rw.RPYd (double precision)

• rw.RPYf (float precision)

Java

2import org.robwork.sdurw.*;
3import static org.robwork.sdurw.sdurwConstants.*;
4
5public class ExRPY {
6    public static void main(String[] args) throws Exception {
8
9        RPYd rpy = new RPYd(Pi,Pi/2,0);
10        System.out.println("RPY: " + rpy);
11        Rotation3Dd rotationFromRPY = rpy.toRotation3D();
12        System.out.println("Rotation from RPY: " + rotationFromRPY);
13
14        Rotation3Dd rot = new Rotation3Dd(-1,0,0,0,0,1,0,1,0);
15        System.out.println("Rotation: " + rot);
16        RPYd rpyFromRotation = new RPYd(rot);
17        System.out.println("RPY from Rotation: " + rpyFromRotation);
18    }
19}

API Reference:

LUA

1require("sdurw_core")
2require("sdurw")
3using("sdurw")
4require("sdurw_math")
5using("sdurw_math")
6
7rpy = RPY(Pi,Pi/2,0);
8print("RPY: " .. tostring(rpy));
9rotationFromRPY = rpy:toRotation3D();
10print("Rotation from RPY: " .. tostring(rotationFromRPY));
11
12rot = Rotation3D(-1,0,0,0,0,1,0,1,0);
13print("Rotation: " .. tostring(rot));
14rpyFromRotation = RPY(rot);
15print("RPY from Rotation: " .. tostring(rpyFromRotation));

Output

RPY: RPY {3.14159, 1.5708, 0}
Rotation from RPY: Rotation3D(-6.12323e-17, -1.22465e-16, -1, 7.4988e-33, -1, 1.22465e-16, -1, 0, 6.12323e-17)
Rotation: Rotation3D(-1, 0, 0, 0, 0, 1, 0, 1, 0)
RPY from Rotation: RPY {3.14159, -0, 1.5708}

## Quaternion

Quaternions are complex numbers, storing the rotation as 4 values.

C++

1#include <rw/math/Quaternion.hpp>
2#include <rw/math/Rotation3D.hpp>
3
4using namespace rw::math;
5
6int main (int argc, char** argv)
7{
8    const Quaternion<> quat = Quaternion<> (sqrt (2) / 2, sqrt (2) / 2, 0, 0);
9    std::cout << "Quaternion: " << quat << std::endl;
10    const Rotation3D<> rotationFromQuat = quat.toRotation3D ();
11    std::cout << "Rotation from Quaternion: " << rotationFromQuat << std::endl;
12
13    const Rotation3D<> rot = Rotation3D<> (-1, 0, 0, 0, 0, 1, 0, 1, 0);
14    std::cout << "Rotation: " << rot << std::endl;
15    const Quaternion<> quatFromRotation = Quaternion<> (rot);
16    std::cout << "Quaternion from Rotation: " << quatFromRotation << std::endl;
17
18    return 0;
19}

API Reference: rw::math::Quaternion

Python

1from sdurw import *
2import math
3
4if __name__ == '__main__':
5    quat = Quaternion(math.sqrt(2)/2,math.sqrt(2)/2,0,0)
6    print("Quaternion: " + str(quat))
7    rotationFromQuat = quat.toRotation3D()
8    print("Rotation from Quaternion: " + str(rotationFromQuat));
9
10    rot = Rotation3D(-1,0,0,0,0,1,0,1,0);
11    print("Rotation: " + str(rot));
12    quatFromRotation = Quaternion(rot);
13    print("Quaternion from Rotation: " + str(quatFromRotation));

API Reference:

• rw.Quaterniond (double precision)

• rw.Quaternionf (float precision)

Java

2import org.robwork.sdurw.*;
3import java.lang.Math;
4
5public class ExQuaternion {
6    public static void main(String[] args) throws Exception {
8
9        Quaterniond quat = new Quaterniond(Math.sqrt(2)/2,Math.sqrt(2)/2,0,0);
10        System.out.println("Quaternion: " + quat);
11        Rotation3Dd rotationFromQuat = quat.toRotation3D();
12        System.out.println("Rotation from Quaternion: " + rotationFromQuat);
13
14        Rotation3Dd rot = new Rotation3Dd(-1,0,0,0,0,1,0,1,0);
15        System.out.println("Rotation: " + rot);
16        Quaterniond quatFromRotation = new Quaterniond(rot);
17        System.out.println("Quaternion from Rotation: " + quatFromRotation);
18    }
19}

API Reference:

LUA

1require("sdurw_core")
2require("sdurw")
3using("sdurw_core")
4require("sdurw_math")
5using("sdurw_math")
6
7quat = Quaternion(math.sqrt(2)/2,math.sqrt(2)/2,0,0);
8print("Quaternion: " .. tostring(quat))
9rotationFromQuat = quat:toRotation3D();
10print("Rotation from Quaternion: " .. tostring(rotationFromQuat));
11
12rot = Rotation3D(-1,0,0,0,0,1,0,1,0);
13print("Rotation: " .. tostring(rot));
14quatFromRotation = Quaternion(rot);
15print("Quaternion from Rotation: " .. tostring(quatFromRotation))

Output

Quaternion: Quaternion {0.707107, 0.707107, 0, 0}
Rotation from Quaternion: Rotation3D(-2.22045e-16, 1, 0, 1, -2.22045e-16, 0, 0, 0, -1)
Rotation: Rotation3D(-1, 0, 0, 0, 0, 1, 0, 1, 0)
Quaternion from Rotation: Quaternion {0, 0.707107, 0.707107, 0}

## Converting Rotations

To convert between EAA, RPY and Quaternions, it is in general possible to convert the types via the full Rotation3D representation. First convert to Rotation3D using the toRotation3D() function and then construct the new target type from this rotation matrix.

The RobWork Math class provides special functions for converting between EAA and Quaternion. Please see the quaternionToEAA and eaaToQuaternion functions.

API Reference:

## Transformations

The Transform3D type is a full 4x4 homogeneous transformation matrix. A transformation matrix combines a rotation and a translation. It can be constructed from a Vector3D and any of the rotation types above.

Alternatively, the Pose6D stores a pose using six values. Three values for the position and three values for the EAA orientation.

API Reference: