def ape(traj_ref: PosePath3D, traj_est: PosePath3D, pose_relation: metrics.PoseRelation, align: bool = False, correct_scale: bool = False, n_to_align: int = -1, align_origin: bool = False, ref_name: str = "reference", est_name: str = "estimate") -> Result: # Align the trajectories. only_scale = correct_scale and not align if align or correct_scale: logger.debug(SEP) traj_est.align(traj_ref, correct_scale, only_scale, n=n_to_align) elif align_origin: logger.debug(SEP) traj_est.align_origin(traj_ref) # Calculate APE. logger.debug(SEP) data = (traj_ref, traj_est) ape_metric = metrics.APE(pose_relation) ape_metric.process_data(data) title = str(ape_metric) if align and not correct_scale: title += "\n(with SE(3) Umeyama alignment)" elif align and correct_scale: title += "\n(with Sim(3) Umeyama alignment)" elif only_scale: title += "\n(scale corrected)" elif align_origin: title += "\n(with origin alignment)" else: title += "\n(not aligned)" if (align or correct_scale) and n_to_align != -1: title += " (aligned poses: {})".format(n_to_align) ape_result = ape_metric.get_result(ref_name, est_name) ape_result.info["title"] = title logger.debug(SEP) logger.info(ape_result.pretty_str()) ape_result.add_trajectory(ref_name, traj_ref) ape_result.add_trajectory(est_name, traj_est) if isinstance(traj_est, PoseTrajectory3D): seconds_from_start = [ t - traj_est.timestamps[0] for t in traj_est.timestamps ] ape_result.add_np_array("seconds_from_start", seconds_from_start) ape_result.add_np_array("timestamps", traj_est.timestamps) return ape_result
def rpe(traj_ref: PosePath3D, traj_est: PosePath3D, pose_relation: metrics.PoseRelation, delta: float, delta_unit: metrics.Unit, rel_delta_tol: float = 0.1, all_pairs: bool = False, align: bool = False, correct_scale: bool = False, n_to_align: int = -1, align_origin: bool = False, ref_name: str = "reference", est_name: str = "estimate", support_loop: bool = False) -> Result: # Align the trajectories. only_scale = correct_scale and not align if align or correct_scale: logger.debug(SEP) traj_est.align(traj_ref, correct_scale, only_scale, n=n_to_align) elif align_origin: logger.debug(SEP) traj_est.align_origin(traj_ref) # Calculate RPE. logger.debug(SEP) data = (traj_ref, traj_est) rpe_metric = metrics.RPE(pose_relation, delta, delta_unit, rel_delta_tol, all_pairs) rpe_metric.process_data(data) title = str(rpe_metric) if align and not correct_scale: title += "\n(with SE(3) Umeyama alignment)" elif align and correct_scale: title += "\n(with Sim(3) Umeyama alignment)" elif only_scale: title += "\n(scale corrected)" elif align_origin: title += "\n(with origin alignment)" else: title += "\n(not aligned)" if (align or correct_scale) and n_to_align != -1: title += " (aligned poses: {})".format(n_to_align) rpe_result = rpe_metric.get_result(ref_name, est_name) rpe_result.info["title"] = title logger.debug(SEP) logger.info(rpe_result.pretty_str()) # Restrict trajectories to delta ids for further processing steps. if support_loop: # Avoid overwriting if called repeatedly e.g. in Jupyter notebook. import copy traj_ref = copy.deepcopy(traj_ref) traj_est = copy.deepcopy(traj_est) traj_ref.reduce_to_ids(rpe_metric.delta_ids) traj_est.reduce_to_ids(rpe_metric.delta_ids) rpe_result.add_trajectory(ref_name, traj_ref) rpe_result.add_trajectory(est_name, traj_est) if isinstance(traj_est, PoseTrajectory3D): seconds_from_start = [ t - traj_est.timestamps[0] for t in traj_est.timestamps ] rpe_result.add_np_array("seconds_from_start", seconds_from_start) rpe_result.add_np_array("timestamps", traj_est.timestamps) return rpe_result