Rotation of 3D Points

The main goal of this exercise is to learn how to rotate 3d (laser scan) points. We have got 3 files in ply format containing laser scan points. This data be used to check the implementation in our exercise. This page is available for practice as an interactive jupyter notebook.

Load the data

Polygon File Format (PLY) is designed to store 3D data. The data can be stored in a readable ascii format or the more efficient binary format. In the next cell we take a look at one of our ply files.

! head -n 30 schneiderberg3.ply
ply
format ascii 1.0
comment VCGLIB generated
element vertex 10699
property float x
property float y
property float z
property uchar red
property uchar green
property uchar blue
property uchar alpha
element face 0
property list uchar int vertex_indices
end_header
10.019 2.656 0.885 35 37 20 255 
7.559 4.033 0.896 30 29 26 255 
8.175 4.201 0.911 22 23 20 255 
6.058 6 0.993 26 19 20 255 
10.923 3.782 1.042 25 28 17 255 
7.566 4.038 1.098 29 27 28 255 
7.682 4.158 1.177 22 22 24 255 
9.963 4.176 1.098 26 21 19 255 
10.119 4.157 1.094 27 19 17 255 
--More--(0%)

As you can see in output of the cell above the file has a header. The end of the header is indicated by end_header. The header describes the structure of the data part. Per line we have the coordinates x y z followed by the captured color of the point stored in red green blue format and the alpha value.

Implement loader

In the following step we implement the loader.

import numpy as np

def load_ply(filename):
    with open(filename) as ply_file: 
        for line in ply_file:  # scip header
            # Here we could interpret the header information.
            # In our case we will hardcode this method to our existing data.
            if line.strip() == 'end_header':
                break
        
        # Now you need to iterate through the data block of the file line by line.
        # Split the lines by the separator ' ' (space) and parse string representation of the number in
        # in suitable format like for example float.
        # Compose alls the points to single matrix. As output is expected a matrix with dimension (787639, 6).
        # 787639 points in the test file Schneiderberg3.ply and 7 because of three coordinates x y z and three rgb 
        # values and the alpha value.
        
        # YOUR CODE HERE
        raise NotImplementedError()
        
        
       
loaded_file = load_ply('schneiderberg3.ply')
print("Shape of the loaded matrix: {}".format(loaded_file.shape))
assert loaded_file.shape == (10699, 7)


Rotate

Lets implement a function to rotate 3D points.

omega: rotation angle about x axis

phi: rotation angle about y axis

kappa: rotation angle about z axis

from math import cos, sin, pi
def rotation(omega, phi, kappa):
    # This method should return numpy matrix which rotate a 3d point by given angles.
    # YOUR CODE HERE
    raise NotImplementedError()
assert np.array_equal(rotation(np.radians(-90),0,0).astype(int),
                      np.array([[ 1,  0,  0],
                                [ 0,  0,  1],
                                [ 0, -1,  0]]))
assert np.array_equal(rotation(0, np.radians(90),0).astype(int),
                      np.array([[ 0,  0,  1],
                                [ 0,  1,  0],
                                [ -1,  0, 0]]))
assert np.array_equal(rotation(0, 0, np.radians(90)).astype(int),
                      np.array([[ 0,  -1,  0],
                                [ 1,  0,  0],
                                [ 0, 0, 1]]))
# Example rotation
points = load_ply('schneiderberg3.ply')[:,0:3]
rot_mat = rotation(0, 0, np.radians(90))
#points_rot = np.dot(rot_mat, points.transpose()).transpose()
#print(points_rot)
#print(points_rot.shape)

# Visualization example
import ipyvolume as ipv
ipv.quickscatter(points[:,0], points[:,1], points[:,2], size=1, marker="sphere")

Rotate the point cloud

Please rotate the point cloud and visualize it. Rotate the point cloud by kapa= 90 deg, omega= 180 deg and phi= 180 deg!

# YOUR CODE HERE
raise NotImplementedError()

Quaternions

The main idea is that we can use them to define a rotation along an axis r by an angle alpha.

def rot_quat(alpha, r):
    # Please create a quternion from the rotations axis r and angle alpha. Expected output is a array R^4.
    
    # YOUR CODE HERE
    raise NotImplementedError()
    
    return q
   

assert np.array_equal(rot_quat(np.radians(0), np.array((1,0,0))),
                      np.array([ 1.,  0.,  0.,  0.]))
assert np.array_equal(rot_quat(np.radians(180), np.array((1,1,1))).astype(int),
                      np.array([  0,   1,   1,   1,]))

assert np.array_equal(rot_quat(np.radians(180), np.array((1,0,1))).astype(int),
                      np.array([  0,   1,   0,   1,]))
assert np.array_equal(rot_quat(np.radians(180), np.array((1,0,1))).astype(int),
                      np.array([  0,   1,   0,   1,]))