diff --git a/eval_pose.py b/eval_pose.py
new file mode 100644
index 0000000000000000000000000000000000000000..467a4d07ccc72670c11eb20f733d6c847810142b
--- /dev/null
+++ b/eval_pose.py
@@ -0,0 +1,308 @@
+import data
+import numpy as np
+import math
+from scipy import spatial
+from scipy.linalg import logm
+from numpy import linalg as LA
+import open3d as o3d
+import argparse
+import os
+import sys
+
+
+def read_diameter(object_name):
+    filename = f'Generated_Worlds_/Generated/{class_name}/diameter.txt'
+    with open(filename) as f:
+        diameter_in_cm = float(f.readline())
+    return diameter_in_cm * 0.01
+
+
+def transform_pts_Rt(pts, R, t):
+    """Applies a rigid transformation to 3D points.
+  :param pts: nx3 ndarray with 3D points.
+  :param R: 3x3 ndarray with a rotation matrix.
+  :param t: 3x1 ndarray with a translation vector.
+  :return: nx3 ndarray with transformed 3D points.
+  """
+    assert (pts.shape[1] == 3)
+    pts_t = R.dot(pts.T) + t.reshape((3, 1))
+    return pts_t.T
+
+
+def project_pts(pts, K, R, t):
+    """Projects 3D points.
+  :param pts: nx3 ndarray with the 3D points.
+  :param K: 3x3 ndarray with an intrinsic camera matrix.
+  :param R: 3x3 ndarray with a rotation matrix.
+  :param t: 3x1 ndarray with a translation vector.
+  :return: nx2 ndarray with 2D image coordinates of the projections.
+  """
+    assert (pts.shape[1] == 3)
+    P = K.dot(np.hstack((R, t)))
+    pts_h = np.hstack((pts, np.ones((pts.shape[0], 1))))
+    pts_im = P.dot(pts_h.T)
+    pts_im /= pts_im[2, :]
+    return pts_im[:2, :].T
+
+
+def add(R_est, t_est, R_gt, t_gt, pts):
+    """Average Distance of Model Points for objects with no indistinguishable
+  views - by Hinterstoisser et al. (ACCV'12).
+  :param R_est: 3x3 ndarray with the estimated rotation matrix.
+  :param t_est: 3x1 ndarray with the estimated translation vector.
+  :param R_gt: 3x3 ndarray with the ground-truth rotation matrix.
+  :param t_gt: 3x1 ndarray with the ground-truth translation vector.
+  :param pts: nx3 ndarray with 3D model points.
+  :return: The calculated error.
+  """
+    pts_est = transform_pts_Rt(pts, R_est, t_est)
+    pts_gt = transform_pts_Rt(pts, R_gt, t_gt)
+    e = np.linalg.norm(pts_est - pts_gt, axis=1).mean()
+    return e
+
+
+def adi(R_est, t_est, R_gt, t_gt, pts):
+    """Average Distance of Model Points for objects with indistinguishable views
+  - by Hinterstoisser et al. (ACCV'12).
+  :param R_est: 3x3 ndarray with the estimated rotation matrix.
+  :param t_est: 3x1 ndarray with the estimated translation vector.
+  :param R_gt: 3x3 ndarray with the ground-truth rotation matrix.
+  :param t_gt: 3x1 ndarray with the ground-truth translation vector.
+  :param pts: nx3 ndarray with 3D model points.
+  :return: The calculated error.
+  """
+    pts_est = transform_pts_Rt(pts, R_est, t_est)
+    pts_gt = transform_pts_Rt(pts, R_gt, t_gt)
+
+    # Calculate distances to the nearest neighbors from vertices in the
+    # ground-truth pose to vertices in the estimated pose.
+    nn_index = spatial.cKDTree(pts_est)
+    nn_dists, _ = nn_index.query(pts_gt, k=1)
+
+    e = nn_dists.mean()
+    return e
+
+
+def re(R_est, R_gt):
+    """Rotational Error.
+  :param R_est: 3x3 ndarray with the estimated rotation matrix.
+  :param R_gt: 3x3 ndarray with the ground-truth rotation matrix.
+  :return: The calculated error.
+  """
+    error_cos = float(0.5 * (np.trace(R_est.dot(np.linalg.inv(R_gt))) - 1.0))
+
+    # Avoid invalid values due to numerical errors.
+    error_cos = min(1.0, max(-1.0, error_cos))
+
+    error = math.acos(error_cos)
+    error = 180.0 * error / np.pi  # Convert [rad] to [deg].
+    return error
+
+
+def te(t_est, t_gt):
+    """Translational Error.
+  :param t_est: 3x1 ndarray with the estimated translation vector.
+  :param t_gt: 3x1 ndarray with the ground-truth translation vector.
+  :return: The calculated error.
+  """
+    assert (t_est.size == t_gt.size == 3)
+    error = np.linalg.norm(t_gt - t_est)
+    return error
+
+
+def proj(R_est, t_est, R_gt, t_gt, K, pts):
+    """Average distance of projections of object model vertices [px]
+  - by Brachmann et al. (CVPR'16).
+  :param R_est: 3x3 ndarray with the estimated rotation matrix.
+  :param t_est: 3x1 ndarray with the estimated translation vector.
+  :param R_gt: 3x3 ndarray with the ground-truth rotation matrix.
+  :param t_gt: 3x1 ndarray with the ground-truth translation vector.
+  :param K: 3x3 ndarray with an intrinsic camera matrix.
+  :param pts: nx3 ndarray with 3D model points.
+  :return: The calculated error.
+  """
+    proj_est = project_pts(pts, K, R_est, t_est)
+    proj_gt = project_pts(pts, K, R_gt, t_gt)
+    e = np.linalg.norm(proj_est - proj_gt, axis=1).mean()
+    return e
+
+
+def compute_add_score(pts3d, diameter, R_pred, t_pred, R_gt, t_gt, percentage=0.1):
+    # R_gt, t_gt = pose_gt
+    # R_pred, t_pred = pose_pred
+    count = R_gt.shape[0]
+    mean_distances = np.zeros((count,), dtype=np.float32)
+    for i in range(count):
+        pts_xformed_gt = R_gt[i] * pts3d.transpose() + t_gt[i]
+        pts_xformed_pred = R_pred[i] * pts3d.transpose() + t_pred[i]
+        distance = np.linalg.norm(pts_xformed_gt - pts_xformed_pred, axis=0)
+        mean_distances[i] = np.mean(distance)
+
+    threshold = diameter * percentage
+    score = (mean_distances < threshold).sum() / count
+    return score
+
+
+def compute_adds_score(pts3d, diameter, pose_gt, pose_pred, percentage=0.1):
+    R_gt, t_gt = pose_gt
+    R_pred, t_pred = pose_pred
+
+    count = R_gt.shape[0]
+    mean_distances = np.zeros((count,), dtype=np.float32)
+    for i in range(count):
+        if np.isnan(np.sum(t_pred[i])):
+            mean_distances[i] = np.inf
+            continue
+        pts_xformed_gt = R_gt[i] * pts3d.transpose() + t_gt[i]
+        pts_xformed_pred = R_pred[i] * pts3d.transpose() + t_pred[i]
+        kdt = spatial.KDTree(pts_xformed_gt.transpose(), metric='euclidean')
+        distance, _ = kdt.query(pts_xformed_pred.transpose(), k=1)
+        mean_distances[i] = np.mean(distance)
+    threshold = diameter * percentage
+    score = (mean_distances < threshold).sum() / count
+    return score
+
+
+def compute_pose_error(diameter, pose_gt, pose_pred):
+    R_gt, t_gt = pose_gt
+    R_pred, t_pred = pose_pred
+
+    count = R_gt.shape[0]
+    R_err = np.zeros(count)
+    t_err = np.zeros(count)
+    for i in range(count):
+        if np.isnan(np.sum(t_pred[i])):
+            continue
+        r_err = logm(np.dot(R_pred[i].transpose(), R_gt[i])) / 2
+        R_err[i] = LA.norm(r_err, 'fro')
+        t_err[i] = LA.norm(t_pred[i] - t_gt[i])
+    return np.median(R_err) * 180 / np.pi, np.median(t_err) / diameter
+
+
+def cou_mask(mask_est, mask_gt):
+    """Complement over Union of 2D binary masks.
+  :param mask_est: hxw ndarray with the estimated mask.
+  :param mask_gt: hxw ndarray with the ground-truth mask.
+  :return: The calculated error.
+  """
+    mask_est_bool = mask_est.astype(bool)
+    mask_gt_bool = mask_gt.astype(bool)
+
+    inter = np.logical_and(mask_gt_bool, mask_est_bool)
+    union = np.logical_or(mask_gt_bool, mask_est_bool)
+
+    union_count = float(union.sum())
+    if union_count > 0:
+        e = 1.0 - inter.sum() / union_count
+    else:
+        e = 1.0
+    return e
+
+
+def find_nn_idx(pc_src, pc_target):
+    """
+        pc_src: (N1, 3) array
+        pc_target: (N2, 3) array
+    """
+    dist_sq = -np.dot(pc_src, pc_target.T) * 2 + \
+            np.square(np.linalg.norm(pc_src, axis=-1, keepdims=True)) + \
+            np.square(np.linalg.norm(pc_target.T, axis=0, keepdims=True))
+    idx_min = np.argmin(dist_sq, axis=0)
+    return idx_min
+
+
+def add_metric(pose_pred, pose_targets, obj_points, diameter, symm=False, percentage=0.1, gpu=False):
+
+    diam = diameter * percentage
+    model_pred = np.dot(obj_points, pose_pred[:, :3].T) + pose_pred[:, 3]
+    model_targets = np.dot(obj_points, pose_targets[:, :3].T) + pose_targets[:, 3]
+
+    if symm:
+        # if gpu:
+        #     idxs = nn_utils.find_nearest_point_idx(model_pred, model_targets)
+        # else:
+        idxs = find_nn_idx(model_pred, model_targets)
+        mean_dist = np.mean(np.linalg.norm(model_pred[idxs] - model_targets, 2, 1))
+    else:
+        mean_dist = np.mean(np.linalg.norm(model_pred - model_targets, axis=-1))
+
+    return mean_dist < diam, (mean_dist, diam)
+
+
+def eval_pose(r_est, t_est, r_gt, t_gt, pc, k, diameter, sym=False):
+    add_res = add(r_est, t_est, r_gt, t_gt, pc)
+    is_add = add(r_est, t_est, r_gt, t_gt, pc) < diameter * 0.1
+    proj_res = proj(r_est, t_est, r_gt, t_gt, k, pc)
+    is_proj = proj(r_est, t_est, r_gt, t_gt, k, pc) < 5
+    adi_res = 0
+    is_adi = False
+    if sym:
+        add_res = adi(r_est, t_est, r_gt, t_gt, pc)
+        is_add = adi(r_est, t_est, r_gt, t_gt, pc) < diameter * 0.1
+
+    return add_res, is_add, proj_res, is_proj, adi_res, is_adi
+
+
+if __name__ == '__main__':
+    ap = argparse.ArgumentParser()
+    ap.add_argument("-cls_name", "--class_name", type=str,
+                    default='kiwi1',
+                    help="[apple2, apricot, banana1, kiwi1, lemon2, orange2, peach1, pear2]")
+    ap.add_argument("-sym", "--symmetry", type=bool,
+                    default=False)
+
+    args = vars(ap.parse_args())
+
+    class_name = args["class_name"]
+    symmetry = args["symmetry"]
+
+    basePath = os.path.dirname(
+        os.path.realpath(__file__)) + '/Generated_Worlds_/Generated_Worlds_Evaluating/' + class_name
+
+    images_ls, labels_ls, mask_ls, choice_ls = data.getAllValData(class_name)
+    print(len(images_ls))
+
+    pc_path = f'/{basePath}/Models/{class_name}.ply'
+    pcd = o3d.io.read_point_cloud(pc_path)
+    pc = np.asarray(pcd.points)
+
+    add_res_ls = []
+    proj_res_ls = []
+    count_add = 0
+    count_iadd = 0
+    count_proj = 0
+
+
+
+    for idx in range(len(images_ls)):
+        #  ============== Loading Pose ===============
+        pose_est = np.load(f'{basePath}/Pose_prediction/{idx}.npy')
+        r_est = pose_est[:3, :3]
+        t_est = pose_est[:3, 3]
+
+        pose_gt = np.load(f'{basePath}/Pose_transformed/{idx}.npy')
+        r_gt = np.array(pose_gt[0:3, 0:3], dtype='float64')
+        t_gt = np.array(pose_gt[0:3, 3], dtype='float64').reshape(3, 1)
+
+        #  ============== Evaluation ===============
+        k = np.array([[543.25272224, 0., 320.25],
+                      [0., 724.33696299, 240.33333333],
+                      [0., 0., 1.]])
+        diameter = read_diameter(class_name)
+
+        add_res, is_add, proj_res, is_proj, adi_res, is_adi = eval_pose(r_est, t_est, r_gt, t_gt, pc, k, diameter, symmetry)
+
+        if is_add:
+            count_add += 1
+
+        if is_proj:
+            count_proj += 1
+        if is_adi:
+            count_iadd += 1
+
+    print(f"ADD_Res: {count_add / len(images_ls)}")
+    print(f"ADI_Res: {count_iadd / len(images_ls)}")
+    print(f"Proj_Res: {count_proj / len(images_ls)}")
+    print(f"======================")
+
+    print("Done")