import numpy as np class PoseUtil: ROTATION = 1 TRANSLATION = 2 SCALE = 3 @staticmethod def get_uniform_translation(trans_m_min, trans_m_max, trans_unit, debug=False): if isinstance(trans_m_min, list): x_min, y_min, z_min = trans_m_min x_max, y_max, z_max = trans_m_max else: x_min, y_min, z_min = trans_m_min, trans_m_min, trans_m_min x_max, y_max, z_max = trans_m_max, trans_m_max, trans_m_max x = np.random.uniform(x_min, x_max) y = np.random.uniform(y_min, y_max) z = np.random.uniform(z_min, z_max) translation = np.array([x, y, z]) if trans_unit == "cm": translation = translation / 100 if debug: print("uniform translation:", translation) return translation @staticmethod def get_uniform_rotation(rot_degree_min=0, rot_degree_max=180, debug=False): axis = np.random.randn(3) axis /= np.linalg.norm(axis) theta = np.random.uniform( rot_degree_min / 180 * np.pi, rot_degree_max / 180 * np.pi ) K = np.array( [[0, -axis[2], axis[1]], [axis[2], 0, -axis[0]], [-axis[1], axis[0], 0]] ) R = np.eye(3) + np.sin(theta) * K + (1 - np.cos(theta)) * (K @ K) if debug: print("uniform rotation:", theta * 180 / np.pi) return R @staticmethod def get_uniform_pose( trans_min, trans_max, rot_min=0, rot_max=180, trans_unit="cm", debug=False ): translation = PoseUtil.get_uniform_translation( trans_min, trans_max, trans_unit, debug ) rotation = PoseUtil.get_uniform_rotation(rot_min, rot_max, debug) pose = np.eye(4) pose[:3, :3] = rotation pose[:3, 3] = translation return pose @staticmethod def get_n_uniform_pose( trans_min, trans_max, rot_min=0, rot_max=180, n=1, trans_unit="cm", fix=None, contain_canonical=True, debug=False, ): if fix == PoseUtil.ROTATION: translations = np.zeros((n, 3)) for i in range(n): translations[i] = PoseUtil.get_uniform_translation( trans_min, trans_max, trans_unit, debug ) if contain_canonical: translations[0] = np.zeros(3) rotations = PoseUtil.get_uniform_rotation(rot_min, rot_max, debug) elif fix == PoseUtil.TRANSLATION: rotations = np.zeros((n, 3, 3)) for i in range(n): rotations[i] = PoseUtil.get_uniform_rotation(rot_min, rot_max, debug) if contain_canonical: rotations[0] = np.eye(3) translations = PoseUtil.get_uniform_translation( trans_min, trans_max, trans_unit, debug ) else: translations = np.zeros((n, 3)) rotations = np.zeros((n, 3, 3)) for i in range(n): translations[i] = PoseUtil.get_uniform_translation( trans_min, trans_max, trans_unit, debug ) for i in range(n): rotations[i] = PoseUtil.get_uniform_rotation(rot_min, rot_max, debug) if contain_canonical: translations[0] = np.zeros(3) rotations[0] = np.eye(3) pose = np.eye(4, 4, k=0)[np.newaxis, :].repeat(n, axis=0) pose[:, :3, :3] = rotations pose[:, :3, 3] = translations return pose @staticmethod def get_n_uniform_pose_batch( trans_min, trans_max, rot_min=0, rot_max=180, n=1, batch_size=1, trans_unit="cm", fix=None, contain_canonical=False, debug=False, ): batch_poses = [] for i in range(batch_size): pose = PoseUtil.get_n_uniform_pose( trans_min, trans_max, rot_min, rot_max, n, trans_unit, fix, contain_canonical, debug, ) batch_poses.append(pose) pose_batch = np.stack(batch_poses, axis=0) return pose_batch @staticmethod def get_uniform_scale(scale_min, scale_max, debug=False): if isinstance(scale_min, list): x_min, y_min, z_min = scale_min x_max, y_max, z_max = scale_max else: x_min, y_min, z_min = scale_min, scale_min, scale_min x_max, y_max, z_max = scale_max, scale_max, scale_max x = np.random.uniform(x_min, x_max) y = np.random.uniform(y_min, y_max) z = np.random.uniform(z_min, z_max) scale = np.array([x, y, z]) if debug: print("uniform scale:", scale) return scale