Search code examples
pythonrotationpoint-clouds

Rotating Point Cloud Data in Bird's-Eye-View Using Rotation Matrix


I am trying to rotate 3d point cloud data to theta degree using rotation matrix. The shape of point cloud data that is indicated as 'xyz' in code is (64,2048,3), so there are 131,072 points including x,y,z. I have tried with 2d rotation matrix (since I want to rotate in bird's eye view).

The 2d rotation matrix that I used is: 2d rotation matrix

And this is my code for the rotation:

def rotation (xyz):
            original_x = []
            original_y = []
            for i in range(64):
                for j in range(2048): 
                    original_x.append(xyz[i][j][0])
                    original_y.append(xyz[i][j][1])
                    
            original = np.matrix.transpose(np.array([original_x,original_y]))
            rotation_2d = [[np.cos(theta), -np.sin(theta)],[np.sin(theta),np.cos(theta)]]
            rotated_points = np.matmul(original,rotation_2d)

            return rotated_points

The result looks successful from bird's eye view, but not successful from the front view, as it is very messy so it is not possible to understand the data.

I have also tried with 3d rotation matrix with [x,y,z] that is : 3d rotation matrix

However, the result was exactly the same when 2d rotation matrix was used.

What could be the possible reason? Is there any mistake in the rotation method?


Solution

  • Here's a function that applies the rotation you're after and a demonstration of this code.

    Note that the rotation is applied clockwise. For a counterclockwise rotation, use the transpose of the rotation matrix.

    import numpy as np
    import matplotlib.pyplot as plt
    from scipy.linalg import block_diag
    
    def rotation(xyz):
        before = xyz.reshape((-1,3))
        rot_3d = block_diag([[np.cos(theta), -np.sin(theta)],[np.sin(theta),np.cos(theta)]],1)
        after = before @ rot_3d
        return after
    
    theta = 3*np.pi/2
    xyz_test = np.random.rand(8,16)
    xyz_test = np.stack([xyz_test]*3,axis = -1)
    xyz_test += np.random.randn(8,16,3)*.1
    original = xyz_test.reshape([8*16,3])
    rotated = rotation(xyz_test)
    
    # plt.plot(1,2,3,projection = '3d')
    
    fig,ax = plt.subplots(figsize = (10,10), subplot_kw = {"projection":"3d"})
    ax.plot3D(*original.T, 'x', ms = 20)
    ax.plot3D(*rotated.T, 'x', ms = 20)
    

    Sample resulting plot (of cloud and rotated cloud):

    enter image description here