#!/usr/bin/env python

# Copyright (c) 2016 Satya Mallick <spmallick@learnopencv.com>
# All rights reserved. No warranty, explicit or implicit, provided.

import cv2
import numpy as np
import math
import random

R = np.matrix([[0.6927,-0.7146,0.0978],[0.7165,0.6973,0.0198],[-0.0824,0.0564,0.995]])
# Checks if a matrix is a valid rotation matrix.
def isRotationMatrix(R) :
    Rt = np.transpose(R)
    shouldBeIdentity = np.dot(Rt, R)
    I = np.identity(3, dtype = R.dtype)
    n = np.linalg.norm(I - shouldBeIdentity)
    return n < 1e-6


# Calculates rotation matrix to euler angles
# The result is the same as MATLAB except the order
# of the euler angles ( x and z are swapped ).
def rotationMatrixToEulerAngles(R) :

   # assert(isRotationMatrix(R))
    
    sy = math.sqrt(R[0,0] * R[0,0] +  R[1,0] * R[1,0])
    
    singular = sy < 1e-6

    if  not singular :
        x = math.atan2(R[2,1] , R[2,2])
        y = math.atan2(-R[2,0], sy)
        z = math.atan2(R[1,0], R[0,0])
    else :
        x = math.atan2(-R[1,2], R[1,1])
        y = math.atan2(-R[2,0], sy)
        z = 0

    return np.array([x, y, z])

# Calculates Rotation Matrix given euler angles.
def eulerAnglesToRotationMatrix(theta) :
    
    R_x = np.array([[1,         0,                  0                   ],
                    [0,         math.cos(theta[0]), -math.sin(theta[0]) ],
                    [0,         math.sin(theta[0]), math.cos(theta[0])  ]
                    ])
        
        
                    
    R_y = np.array([[math.cos(theta[1]),    0,      math.sin(theta[1])  ],
                    [0,                     1,      0                   ],
                    [-math.sin(theta[1]),   0,      math.cos(theta[1])  ]
                    ])
                
    R_z = np.array([[math.cos(theta[2]),    -math.sin(theta[2]),    0],
                    [math.sin(theta[2]),    math.cos(theta[2]),     0],
                    [0,                     0,                      1]
                    ])
                    
                    
    RR = np.dot(R_z, np.dot( R_y, R_x ))

    return RR


if __name__ == '__main__' :

    # Randomly generate Euler angles
 #   e = np.random.rand(3) * math.pi * 2 - math.pi
    
    # Calculate rotation matrix
 #   RR = eulerAnglesToRotationMatrix(e)
    
    # Calculate Euler angles from rotation matrix
    e1 = rotationMatrixToEulerAngles(R)

    # Calculate rotation matrix
    R1 = eulerAnglesToRotationMatrix(e1)

    # Note e and e1 will be the same a lot of times
    # but not always. R and R1 should be the same always.

 #   print "\nInput Euler angles :\n{0}".format(e)
    print "\nR :\n{0}".format(R)
    print "\nOutput Euler angles :\n{0}".format(e1)
 #   print "\nR1 :\n{0}".format(R1)

