Usage#

This section will guide you through the basic usage of the py3dframe package.

Construct a rigth-handed frame#

First to create a frame, you can give the origin and the axes of the frame as follows:

import numpy as np
from py3dframe import Frame

origin = np.array([1, 2, 3])
x_axis = np.array([1, 0, 0])
y_axis = np.array([0, 1, 0])
z_axis = np.array([0, 0, 1])

frame = Frame(origin=origin, x_axis=x_axis, y_axis=y_axis, z_axis=z_axis)

You can also construct a frame from a rotation and a translation using one the 8 possible conventions:

Index

Formula

0

\(\mathbf{X}_E = \mathbf{R} \mathbf{X}_F + \mathbf{T}\)

1

\(\mathbf{X}_E = \mathbf{R} \mathbf{X}_F - \mathbf{T}\)

2

\(\mathbf{X}_E = \mathbf{R} (\mathbf{X}_F + \mathbf{T})\)

3

\(\mathbf{X}_E = \mathbf{R} (\mathbf{X}_F - \mathbf{T})\)

4

\(\mathbf{X}_F = \mathbf{R} \mathbf{X}_E + \mathbf{T}\)

5

\(\mathbf{X}_F = \mathbf{R} \mathbf{X}_E - \mathbf{T}\)

6

\(\mathbf{X}_F = \mathbf{R} (\mathbf{X}_E + \mathbf{T})\)

7

\(\mathbf{X}_F = \mathbf{R} (\mathbf{X}_E - \mathbf{T})\)

Where \(\mathbf{X}_E\) is the point expressed in the parent (or global) frame \(E\), \(\mathbf{X}_F\) is the point expressed in the child (or local) frame \(F\), \(\mathbf{R}\) is the rotation matrix and \(\mathbf{T}\) is the translation vector.

from py3dframe import Frame, Rotation

rotation = Rotation.from_euler('xyz', [0, 0, 0], degrees=True)
translation = np.array([1, 2, 3]).reshape(3, 1)

frame = Frame(rotation=rotation, translation=translation, convention=0)

You can check the coordinates of the frame by plotting it into a 3D plot:

import matplotlib.pyplot as plt

fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')

frame.plot(ax)
ax.set_xlabel('X')
ax.set_ylabel('Y')
ax.set_zlabel('Z')

plt.show()

Construct a system of frames#

Lets consider a person walking in a train. The person is represented by a frame \(F\) and the train is represented by a frame \(E\). It is possible to represent the position of the person in the train by defining the frame \(F\) in the frame \(E\) coordinates.

from py3dframe import Frame, Transform

rotation = Rotation.from_euler('xyz', [0, 0, 0], degrees=True)
translation = np.array([1, 2, 3]).reshape(3, 1)

frame_E = Frame(rotation=rotation, translation=translation, convention=0)

rotation = Rotation.from_euler('xyz', [0, 0, 0], degrees=True)
translation = np.array([0, 0, 0]).reshape(3, 1)

frame_F = Frame(rotation=rotation, translation=translation, convention=0, parent=frame_E)

In this case, when the frame \(E\) moves, the frame \(F\) moves with it.

Transformation between frames#

The transformation between two frames can be computed using the Transform class:

from py3dframe import Frame, Transform

rotation = Rotation.from_euler('xyz', [0, 0, 0], degrees=True)
translation = np.array([1, 2, 3]).reshape(3, 1)

frame_E = Frame(rotation=rotation, translation=translation, convention=0)

rotation = Rotation.from_euler('xyz', [0, 0, 0], degrees=True)
translation = np.array([0, 0, 0]).reshape(3, 1)

frame_F = Frame(rotation=rotation, translation=translation, convention=0, parent=frame_E)

transform = Transform(input_frame=frame_E, output_frame=frame_F)

print(transform.translation)
print(transform.rotation.as_euler('xyz', degrees=True))

This object can be used to transform points or vector from one frame to another:

point_E = np.array([1, 2, 3]).reshape(3, 1)
point_F = transform.transform(point=point_E) # In convention 0 : pE = R * pF + T
point_E = transform.inverse_transform(point=point_F)

vector_E = np.array([1, 2, 3]).reshape(3, 1)
vector_F = transform.transform(vector=vector_E) # In convention 0 : vE = R * vF
vector_E = transform.inverse_transform(vector=vector_F)

When the frame \(E\) moves, the transform object will automatically update the transformation between the two frames.