예제 #1
0
def calc_euroc_seq_errors(est_traj, gt_traj):
    gt_traj_synced, est_traj_synced = sync.associate_trajectories(
        gt_traj, est_traj, max_diff=0.01)
    est_traj_aligned = trajectory.align_trajectory(est_traj_synced,
                                                   gt_traj_synced,
                                                   correct_scale=False,
                                                   correct_only_scale=False)
    pose_relation = metrics.PoseRelation.translation_part
    ape_metric = metrics.APE(pose_relation)
    ape_metric.process_data((
        gt_traj_synced,
        est_traj_aligned,
    ))
    ape_stat = ape_metric.get_statistic(metrics.StatisticsType.rmse)

    # ape_metric = metrics.RPE(pose_relation)
    # ape_metric.process_data((gt_traj_synced, est_traj_aligned,))
    # ape_stat = ape_metric.get_statistic(metrics.StatisticsType.rmse)

    # fig = plt.figure()
    # traj_by_label = {
    #     "estimate (not aligned)": est_traj,
    #     "estimate (aligned)": est_traj_aligned,
    #     "reference": gt_traj
    # }
    # plot.trajectories(fig, traj_by_label, plot.PlotMode.xyz)
    # plt.show()

    return ape_metric, ape_stat
예제 #2
0
 def test_se3_alignment(self):
     traj = helpers.fake_trajectory(1000, 1)
     traj_transformed = copy.deepcopy(traj)
     traj_transformed.transform(lie.random_se3())
     self.assertNotEqual(traj, traj_transformed)
     traj_aligned = trajectory.align_trajectory(traj_transformed, traj)
     self.assertEqual(traj_aligned, traj)
예제 #3
0
    def test_alignment_degenerate_case(self):
        length = 100
        poses = [lie.random_se3()] * length
        traj_1 = PoseTrajectory3D(poses_se3=poses,
                                  timestamps=helpers.fake_timestamps(
                                      length, 1, 0.0))
        traj_2 = copy.deepcopy(traj_1)
        traj_2.transform(lie.random_se3())
        traj_2.scale(1.234)
        self.assertNotEqual(traj_1, traj_2)

        with self.assertRaises(GeometryException):
            trajectory.align_trajectory(traj_1, traj_2)

        with self.assertRaises(GeometryException):
            trajectory.align_trajectory(traj_1, traj_2, correct_scale=True)
예제 #4
0
 def test_scale_correction(self):
     traj = helpers.fake_trajectory(1000, 1)
     traj_transformed = copy.deepcopy(traj)
     traj_transformed.scale(1.234)
     self.assertNotEqual(traj, traj_transformed)
     traj_aligned = trajectory.align_trajectory(traj_transformed, traj,
                                                correct_only_scale=True)
     self.assertEqual(traj_aligned, traj)
예제 #5
0
 def test_sim3_alignment(self):
     traj = helpers.fake_trajectory(1000, 1)
     traj_transformed = copy.deepcopy(traj)
     traj_transformed.transform(lie.random_se3())
     traj_transformed.scale(1.234)
     self.assertNotEqual(traj, traj_transformed)
     traj_aligned = trajectory.align_trajectory(traj_transformed, traj,
                                                correct_scale=True)
     self.assertEqual(traj_aligned, traj)
예제 #6
0
def rpe(traj_ref, traj_est, pose_relation, delta, delta_unit,
        rel_delta_tol=0.1, all_pairs=False, align=False, correct_scale=False,
        ref_name="reference", est_name="estimate", support_loop=False):

    from evo.core import metrics
    from evo.core import trajectory

    # Align the trajectories.
    only_scale = correct_scale and not align
    if align or correct_scale:
        logger.debug(SEP)
        traj_est = trajectory.align_trajectory(traj_est, traj_ref,
                                               correct_scale, only_scale)

    # 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)"
    else:
        title += "\n(not aligned)"

    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, trajectory.PoseTrajectory3D) and not all_pairs:
        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
예제 #7
0
def ape(traj_ref,
        traj_est,
        pose_relation,
        align=False,
        correct_scale=False,
        align_origin=False,
        ref_name="reference",
        est_name="estimate"):
    from evo.core import metrics
    from evo.core import trajectory

    # Align the trajectories.
    only_scale = correct_scale and not align
    if align or correct_scale:
        logger.debug(SEP)
        traj_est = trajectory.align_trajectory(traj_est, traj_ref,
                                               correct_scale, only_scale)
    elif align_origin:
        logger.debug(SEP)
        traj_est = trajectory.align_trajectory_origin(traj_est, 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)"

    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, trajectory.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
예제 #8
0
def original_ape(traj_ref,
                 traj_est,
                 pose_relation,
                 align=False,
                 correct_scale=False,
                 align_origin=False,
                 ref_name="reference",
                 est_name="estimate"):
    ''' Copied from main_ape.py
    '''
    traj_ref, traj_est = sync.associate_trajectories(traj_ref, traj_est)
    # Align the trajectories.
    only_scale = correct_scale and not align
    if align or correct_scale:
        traj_est = trajectory.align_trajectory(traj_est, traj_ref,
                                               correct_scale, only_scale)
    elif align_origin:
        traj_est = trajectory.align_trajectory_origin(traj_est, traj_ref)

    # Calculate APE.
    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)"

    ape_result = ape_metric.get_result(ref_name, est_name)
    ape_result.info["title"] = title

    ape_result.add_trajectory(ref_name, traj_ref)
    ape_result.add_trajectory(est_name, traj_est)
    if isinstance(traj_est, trajectory.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
예제 #9
0
def three_plots(ref, est, table, name):
    """Generates plots and statistics table into Report

    :ref: PoseTrajectory3D object that is used as reference
    :est: PoseTrajectory3D object that is plotted against reference
    :table: Tabular object that is generated by Tabular('c c')
    :name: String that is used as name for file and table entry
    :returns: translation of reference against estimation

    """
    ref, est = sync.associate_trajectories(ref, est)
    est, rot, tra, s = trajectory.align_trajectory(est,
                                                   ref,
                                                   correct_scale=False,
                                                   return_parameters=True)

    data = (ref, est)
    ape_metric = metrics.APE(metrics.PoseRelation.translation_part)
    ape_metric.process_data(data)
    ape_statistics = ape_metric.get_all_statistics()

    # [ Localization ]
    fig, axarr = plt.subplots(3)  #sharex=True)
    fig.suptitle('Localization', fontsize=30)
    fig.tight_layout()
    plot.traj_xyyaw(axarr, est, '-', 'red', 'estimation', 1, ref.timestamps[0])
    plot.traj_xyyaw(axarr, ref, '-', 'gray', 'original')
    fig.subplots_adjust(hspace=0.2)
    plt.waitforbuttonpress(0)
    plt.savefig("/home/kostas/results/latest/" + name + ".png",
                format='png',
                bbox_inches='tight')
    plt.close(fig)

    table.add_row((
        name,
        round(ape_statistics["rmse"], 3),
        round(ape_statistics["mean"], 3),
        round(ape_statistics["median"], 3),
        round(ape_statistics["std"], 3),
        round(ape_statistics["min"], 3),
        round(ape_statistics["max"], 3),
        round(ape_statistics["sse"], 3),
    ))
    table.add_hline
예제 #10
0
파일: main_ape.py 프로젝트: danpeng2/evo
def ape(traj_ref, traj_est, pose_relation, align=False,
        correct_scale=False, ref_name="reference", est_name="estimate"):
    from evo.core import metrics
    from evo.core import trajectory

    # Align the trajectories.
    only_scale = correct_scale and not align
    if align or correct_scale:
        logger.debug(SEP)
        traj_est = trajectory.align_trajectory(
            traj_est, traj_ref, correct_scale, only_scale)

    # 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)"
    else:
        title += "\n(not aligned)"

    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, trajectory.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
예제 #11
0
def compare_using_APE(ref_file, est_file, use_aligned_trajectories=False):
    """
    Compare two files using EVO API. Using the APE metric.
    :param ref_file:
    :param est_file:
    :param use_aligned_trajectories: True to align before comparing. False to leave original data as it is.
    :return:
    """
    # Load trajectories
    traj_ref = file_interface.read_tum_trajectory_file(ref_file)
    traj_est = file_interface.read_tum_trajectory_file(est_file)

    # Sinchronize trajectories by timestamps
    max_diff = 0.01
    traj_ref, traj_est = sync.associate_trajectories(traj_ref, traj_est, max_diff)

    # -------------EVO_APE-------------
    # Settings
    pose_relation = metrics.PoseRelation.translation_part
    use_aligned_trajectories = False  # OPTION -va on the scripts. Is related to Uleyamas alignment

    # The aligned trajectories can be used if we want it to
    if use_aligned_trajectories:
        # Align trajectories with Uleyamas algorithm
        try:
            traj_est_aligned = trajectory.align_trajectory(traj_est, traj_ref, correct_scale=False,
                                                           correct_only_scale=False)
            data = (traj_ref, traj_est_aligned)
        except GeometryException:
            print("Couldnt align with Uleyamas algorithm...")
            data = (traj_ref, traj_est)
    else:
        data = (traj_ref, traj_est)

    ape_metric = metrics.APE(pose_relation) # APE with only pose is in reality ATE (Absolute trajectory error) instead of APE (abs. pose error)
    ape_metric.process_data(data)

    # Get all stadistics in a dict
    ape_stats = ape_metric.get_all_statistics()
    return ape_stats
예제 #12
0
def ape(traj_ref,
        traj_est,
        pose_relation,
        align=False,
        correct_scale=False,
        align_origin=False,
        ref_name="reference",
        est_name="estimate"):
    ''' Based on main_ape.py
    '''
    traj_ref, traj_est = sync.associate_trajectories(traj_ref, traj_est)
    # Align the trajectories.
    only_scale = correct_scale and not align
    if align or correct_scale:
        traj_est = trajectory.align_trajectory(traj_est, traj_ref,
                                               correct_scale, only_scale)
    elif align_origin:
        traj_est = trajectory.align_trajectory_origin(traj_est, traj_ref)

    # Calculate APE.
    data = (traj_ref, traj_est)
    ape_metric = APE(pose_relation)
    ape_metric.process_data(data)

    ape_result = ape_metric.get_result(ref_name, est_name)

    ape_result.add_trajectory(ref_name, traj_ref)
    ape_result.add_trajectory(est_name, traj_est)
    if isinstance(traj_est, trajectory.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
예제 #13
0
파일: custom_app.py 프로젝트: danpeng2/evo
#!/usr/bin/env python

from __future__ import print_function

print("loading required evo modules")
from evo.core import trajectory, sync, metrics
from evo.tools import file_interface

print("loading trajectories")
traj_ref = file_interface.read_tum_trajectory_file("../../test/data/fr2_desk_groundtruth.txt")
traj_est = file_interface.read_tum_trajectory_file("../../test/data/fr2_desk_ORB.txt")

print("registering and aligning trajectories")
traj_ref, traj_est = sync.associate_trajectories(traj_ref, traj_est)
traj_est = trajectory.align_trajectory(traj_est, traj_ref, correct_scale=False)

print("calculating APE")
data = (traj_ref, traj_est)
ape_metric = metrics.APE(metrics.PoseRelation.translation_part)
ape_metric.process_data(data)
ape_statistics = ape_metric.get_all_statistics()
print("mean:", ape_statistics["mean"])

print("loading plot modules")
from evo.tools import plot
import matplotlib.pyplot as plt

print("plotting")
plot_collection = plot.PlotCollection("Example")
# metric values
fig_1 = plt.figure(figsize=(8, 8))
예제 #14
0
import numpy as np
import matplotlib.pyplot as plt

logger = logging.getLogger("evo")
log.configure_logging(verbose=True)


traj_ref = file_interface.read_kitti_poses_file("../test/data/KITTI_00_gt.txt")
traj_est = file_interface.read_kitti_poses_file("../test/data/KITTI_00_ORB.txt")

# add artificial Sim(3) transformation
traj_est.transform(lie.se3(np.eye(3), [0, 0, 0]))
traj_est.scale(0.5)

logger.info("\nUmeyama alignment without scaling")
traj_est_aligned = trajectory.align_trajectory(traj_est, traj_ref)

logger.info("\nUmeyama alignment with scaling")
traj_est_aligned_scaled = trajectory.align_trajectory(
    traj_est, traj_ref, correct_scale=True)

logger.info("\nUmeyama alignment with scaling only")
traj_est_aligned_only_scaled = trajectory.align_trajectory(
    traj_est, traj_ref, correct_only_scale=True)

fig = plt.figure(figsize=(8, 8))
plot_mode = plot.PlotMode.xz

ax = plot.prepare_axis(fig, plot_mode, subplot_arg='221')
plot.traj(ax, plot_mode, traj_ref, '--', 'gray')
plot.traj(ax, plot_mode, traj_est, '-', 'blue')
예제 #15
0
def run_analysis(traj_ref_path,
                 traj_est_path,
                 segments,
                 save_results,
                 display_plot,
                 save_plots,
                 save_folder,
                 confirm_overwrite=False,
                 dataset_name="",
                 discard_n_start_poses=0,
                 discard_n_end_poses=0):
    """ Run analysis on given trajectories, saves plots on given path:
    :param traj_ref_path: path to the reference (ground truth) trajectory.
    :param traj_est_path: path to the estimated trajectory.
    :param save_results: saves APE, and RPE per segment results.
    :param save_plots: whether to save the plots.
    :param save_folder: where to save the plots.
    :param confirm_overwrite: whether to confirm overwriting plots or not.
    :param dataset_name: optional param, to allow setting the same scale on different plots.
    """
    # Load trajectories.
    from evo.tools import file_interface
    traj_ref = None
    try:
        traj_ref = file_interface.read_euroc_csv_trajectory(
            traj_ref_path)  # TODO make it non-euroc specific.
    except file_interface.FileInterfaceException as e:
        raise Exception(
            "\033[91mMissing ground truth csv! \033[93m {}.".format(e))

    traj_est = None
    try:
        traj_est = file_interface.read_swe_csv_trajectory(traj_est_path)
    except file_interface.FileInterfaceException as e:
        log.info(e)
        raise Exception("\033[91mMissing vio output csv.\033[99m")

    evt.print_purple("Registering trajectories")
    traj_ref, traj_est = sync.associate_trajectories(traj_ref, traj_est)

    evt.print_purple("Aligning trajectories")
    traj_est = trajectory.align_trajectory(
        traj_est,
        traj_ref,
        correct_scale=False,
        discard_n_start_poses=int(discard_n_start_poses),
        discard_n_end_poses=int(discard_n_end_poses))

    num_of_poses = traj_est.num_poses
    traj_est.reduce_to_ids(
        range(int(discard_n_start_poses),
              int(num_of_poses - discard_n_end_poses), 1))
    traj_ref.reduce_to_ids(
        range(int(discard_n_start_poses),
              int(num_of_poses - discard_n_end_poses), 1))

    results = dict()

    evt.print_purple("Calculating APE translation part")
    data = (traj_ref, traj_est)
    ape_metric = metrics.APE(metrics.PoseRelation.translation_part)
    ape_metric.process_data(data)
    ape_result = ape_metric.get_result()
    results["absolute_errors"] = ape_result

    log.info(ape_result.pretty_str(info=True))

    # TODO(Toni): Save RPE computation results rather than the statistics
    # you can compute statistics later...
    evt.print_purple("Calculating RPE translation part for plotting")
    rpe_metric_trans = metrics.RPE(metrics.PoseRelation.translation_part, 1.0,
                                   metrics.Unit.frames, 0.0, False)
    rpe_metric_trans.process_data(data)
    rpe_stats_trans = rpe_metric_trans.get_all_statistics()
    log.info("mean: %f" % rpe_stats_trans["mean"])

    evt.print_purple("Calculating RPE rotation angle for plotting")
    rpe_metric_rot = metrics.RPE(metrics.PoseRelation.rotation_angle_deg, 1.0,
                                 metrics.Unit.frames, 1.0, False)
    rpe_metric_rot.process_data(data)
    rpe_stats_rot = rpe_metric_rot.get_all_statistics()
    log.info("mean: %f" % rpe_stats_rot["mean"])

    results["relative_errors"] = dict()
    # Read segments file
    for segment in segments:
        results["relative_errors"][segment] = dict()
        evt.print_purple("RPE analysis of segment: %d" % segment)
        evt.print_lightpurple("Calculating RPE segment translation part")
        rpe_segment_metric_trans = metrics.RPE(
            metrics.PoseRelation.translation_part, float(segment),
            metrics.Unit.meters, 0.01, True)
        rpe_segment_metric_trans.process_data(data)
        rpe_segment_stats_trans = rpe_segment_metric_trans.get_all_statistics()
        results["relative_errors"][segment][
            "rpe_trans"] = rpe_segment_stats_trans
        # print(rpe_segment_stats_trans)
        # print("mean:", rpe_segment_stats_trans["mean"])

        evt.print_lightpurple("Calculating RPE segment rotation angle")
        rpe_segment_metric_rot = metrics.RPE(
            metrics.PoseRelation.rotation_angle_deg, float(segment),
            metrics.Unit.meters, 0.01, True)
        rpe_segment_metric_rot.process_data(data)
        rpe_segment_stats_rot = rpe_segment_metric_rot.get_all_statistics()
        results["relative_errors"][segment]["rpe_rot"] = rpe_segment_stats_rot
        # print(rpe_segment_stats_rot)
        # print("mean:", rpe_segment_stats_rot["mean"])

    if save_results:
        # Save results file
        results_file = os.path.join(save_folder, 'results.yaml')
        evt.print_green("Saving analysis results to: %s" % results_file)
        with open(results_file, 'w') as outfile:
            if confirm_overwrite:
                if evt.user.check_and_confirm_overwrite(results_file):
                    outfile.write(yaml.dump(results, default_flow_style=False))
                else:
                    log.info("Not overwritting results.")
            else:
                outfile.write(yaml.dump(results, default_flow_style=False))

    # For each segment in segments file
    # Calculate rpe with delta = segment in meters with all-pairs set to True
    # Calculate max, min, rmse, mean, median etc

    # Plot boxplot, or those cumulative figures you see in evo (like demographic plots)
    if display_plot or save_plots:
        evt.print_green("Plotting:")
        log.info(dataset_name)
        plot_collection = plot.PlotCollection("Example")
        # metric values
        fig_1 = plt.figure(figsize=(8, 8))
        ymax = -1
        if dataset_name is not "" and FIX_MAX_Y:
            ymax = Y_MAX_APE_TRANS[dataset_name]

        ape_statistics = ape_metric.get_all_statistics()
        plot.error_array(
            fig_1,
            ape_metric.error,
            statistics=ape_statistics,
            name="APE translation",
            title=""  #str(ape_metric)
            ,
            xlabel="Keyframe index [-]",
            ylabel="APE translation [m]",
            y_min=0.0,
            y_max=ymax)
        plot_collection.add_figure("APE_translation", fig_1)

        # trajectory colormapped with error
        fig_2 = plt.figure(figsize=(8, 8))
        plot_mode = plot.PlotMode.xy
        ax = plot.prepare_axis(fig_2, plot_mode)
        plot.traj(ax, plot_mode, traj_ref, '--', 'gray', 'reference')
        plot.traj_colormap(ax,
                           traj_est,
                           ape_metric.error,
                           plot_mode,
                           min_map=0.0,
                           max_map=math.ceil(ape_statistics['max'] * 10) / 10,
                           title="ATE mapped onto trajectory [m]")
        plot_collection.add_figure("APE_translation_trajectory_error", fig_2)

        # RPE
        ## Trans
        ### metric values
        fig_3 = plt.figure(figsize=(8, 8))
        if dataset_name is not "" and FIX_MAX_Y:
            ymax = Y_MAX_RPE_TRANS[dataset_name]
        plot.error_array(
            fig_3,
            rpe_metric_trans.error,
            statistics=rpe_stats_trans,
            name="RPE translation",
            title=""  #str(rpe_metric_trans)
            ,
            xlabel="Keyframe index [-]",
            ylabel="RPE translation [m]",
            y_max=ymax)
        plot_collection.add_figure("RPE_translation", fig_3)

        ### trajectory colormapped with error
        fig_4 = plt.figure(figsize=(8, 8))
        plot_mode = plot.PlotMode.xy
        ax = plot.prepare_axis(fig_4, plot_mode)
        traj_ref_trans = copy.deepcopy(traj_ref)
        traj_ref_trans.reduce_to_ids(rpe_metric_trans.delta_ids)
        traj_est_trans = copy.deepcopy(traj_est)
        traj_est_trans.reduce_to_ids(rpe_metric_trans.delta_ids)
        plot.traj(ax, plot_mode, traj_ref_trans, '--', 'gray', 'Reference')
        plot.traj_colormap(
            ax,
            traj_est_trans,
            rpe_metric_trans.error,
            plot_mode,
            min_map=0.0,
            max_map=math.ceil(rpe_stats_trans['max'] * 10) / 10,
            title="RPE translation error mapped onto trajectory [m]")
        plot_collection.add_figure("RPE_translation_trajectory_error", fig_4)

        ## Rot
        ### metric values
        fig_5 = plt.figure(figsize=(8, 8))
        if dataset_name is not "" and FIX_MAX_Y:
            ymax = Y_MAX_RPE_ROT[dataset_name]
        plot.error_array(
            fig_5,
            rpe_metric_rot.error,
            statistics=rpe_stats_rot,
            name="RPE rotation error",
            title=""  #str(rpe_metric_rot)
            ,
            xlabel="Keyframe index [-]",
            ylabel="RPE rotation [deg]",
            y_max=ymax)
        plot_collection.add_figure("RPE_rotation", fig_5)

        ### trajectory colormapped with error
        fig_6 = plt.figure(figsize=(8, 8))
        plot_mode = plot.PlotMode.xy
        ax = plot.prepare_axis(fig_6, plot_mode)
        traj_ref_rot = copy.deepcopy(traj_ref)
        traj_ref_rot.reduce_to_ids(rpe_metric_rot.delta_ids)
        traj_est_rot = copy.deepcopy(traj_est)
        traj_est_rot.reduce_to_ids(rpe_metric_rot.delta_ids)
        plot.traj(ax, plot_mode, traj_ref_rot, '--', 'gray', 'Reference')
        plot.traj_colormap(
            ax,
            traj_est_rot,
            rpe_metric_rot.error,
            plot_mode,
            min_map=0.0,
            max_map=math.ceil(rpe_stats_rot['max'] * 10) / 10,
            title="RPE rotation error mapped onto trajectory [deg]")
        plot_collection.add_figure("RPE_rotation_trajectory_error", fig_6)

        if display_plot:
            evt.print_green("Displaying plots.")
            plot_collection.show()

        if save_plots:
            evt.print_green("Saving plots to: ")
            log.info(save_folder)
            # Config output format (pdf, eps, ...) using evo_config...
            plot_collection.export(os.path.join(save_folder, "plots.eps"),
                                   False)
            plot_collection.export(os.path.join(save_folder, "plots.pdf"),
                                   False)
예제 #16
0
# load trajectories (examples from TUM benchmark)
ref_file = "data/freiburg1_xyz-groundtruth.txt"
est_file = "data/freiburg1_xyz-rgbdslam_drift.txt"
max_diff = 0.01
offset = 0.0
start = time.clock()
traj_ref, traj_est = file_interface.load_assoc_tum_trajectories(
    est_file,
    ref_file,
    max_diff,
    offset,
)
# align trajectories
print("\naligning trajectories...")
traj_est = trajectory.align_trajectory(traj_est, traj_ref)

stop = time.clock()
load_time = stop - start
print("elapsed time for trajectory loading (seconds): \t", "{0:.6f}".format(load_time))

"""
test absolute pose error algorithms
for different types of pose relations
"""
for pose_relation in metrics.PoseRelation:
    print("\n------------------------------------------------------------------\n")
    data = (traj_ref, traj_est)
    start = time.clock()

    ape_metric = metrics.APE(pose_relation)
예제 #17
0
def ape(traj_ref_list,
        traj_est_list,
        pose_relation,
        align=False,
        correct_scale=False,
        align_origin=False,
        ref_name=["reference"],
        est_name=["estimate"]):
    from evo.core import metrics
    from evo.core import trajectory

    # Align the trajectories.
    only_scale = correct_scale and not align
    if align or correct_scale:
        logger.debug(SEP)
        for i in range(len(traj_ref_list)):
            print(traj_est_list[i], traj_ref_list[i])
            traj_est_list[i] = trajectory.align_trajectory(
                traj_est_list[i], traj_ref_list[i], correct_scale, only_scale)
    elif align_origin:
        logger.debug(SEP)
        for i in range(len(traj_ref_list)):
            traj_est_list[i] = trajectory.align_trajectory_origin(
                traj_est_list[i], traj_ref_list[i])

    # Calculate APE.
    logger.debug(SEP)
    data = [(traj_ref_list[i], traj_est_list[i])
            for i in range(len(traj_ref_list))]
    ape_metric = [
        metrics.APE(pose_relation) for i in range(len(traj_ref_list))
    ]
    for i in range(len(traj_ref_list)):
        ape_metric[i].process_data(data[i])

    ape_result = [
        ape_metric[i].get_result(ref_name[i], est_name[i])
        for i in range(len(traj_ref_list))
    ]
    for i in range(len(traj_ref_list)):
        title = str(ape_metric[i])
        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)"
        ape_result[i].info["title"] = title

        logger.debug(SEP)
        logger.info(ape_result[i].pretty_str())

        ape_result[i].add_trajectory(ref_name[i], traj_ref_list[i])
        ape_result[i].add_trajectory(est_name[i], traj_est_list[i])
        if isinstance(traj_est_list[i], trajectory.PoseTrajectory3D):
            seconds_from_start = [
                t - traj_est_list[i].timestamps[0]
                for t in traj_est_list[i].timestamps
            ]
            ape_result[i].add_np_array("seconds_from_start",
                                       seconds_from_start)
            ape_result[i].add_np_array("timestamps",
                                       traj_est_list[i].timestamps)

    return ape_result
예제 #18
0
def get_and_save_results_from_folder(folder_with_predicted_poses,category):
    
    global args
    global kitti_eval_tool
    global folder_with_gt_poses
    global output_folder
    global t
    global results
    
    values_for_excel = []
    columns_for_excel = []
    type_of_statistics = 'mean'
    for filename in sorted(os.listdir(folder_with_predicted_poses)):
        if not(os.path.exists(os.path.join(folder_with_gt_poses, filename))):
            print("file with gt poses doesn't exist for "+filename)
            continue
        if filename.find('.txt') == -1:
            continue
        seq_results = {}
        seq_results['name_seq'] = filename[:filename.rfind('.')]
        seq_results['category'] = category
        folder_name = seq_results['category']
        seq_results['metrics'] = {}
        seq_results['lost'] = False
        
        os.makedirs(os.path.join(output_folder, folder_name), exist_ok=True)
        output_folder_seq = os.path.join(output_folder, folder_name, filename[:filename.rfind('.')])
        os.makedirs(output_folder_seq, exist_ok=True)
        if os.path.isfile(os.path.join(output_folder, folder_name,"results.txt")):
            file_results_txt = open(os.path.join(output_folder, folder_name,"results.txt"), "a")
        else:
            file_results_txt = open(os.path.join(output_folder, folder_name,"results.txt"), "w")
            file_results_txt.write("translation_error(%) rotation_error(deg/m) ATE(m) APE_translation_error_median(m) APE_rotation_error_median(deg) dst_to_trgt\n")
        
        # -------------------------------------Getting results---------------------------------------------------
        if args.gt_format == 'kitti':        
            traj_ref = file_interface.read_kitti_poses_file(os.path.join(folder_with_gt_poses, filename))
        if args.gt_format == 'tum':        
            traj_ref = file_interface.read_tum_trajectory_file(os.path.join(folder_with_gt_poses, filename))
            seq_results["length_of_ref_traj"] = traj_ref.path_length
            end_time_gt = traj_ref.get_infos()["t_end (s)"]
        if args.gt_format == 'euroc':        
            traj_ref = file_interface.read_euroc_csv_trajectory(os.path.join(folder_with_gt_poses, filename))
        if args.result_format == 'kitti':
            traj_est = file_interface.read_kitti_poses_file(os.path.join(folder_with_predicted_poses, filename))
        if args.result_format == 'tum':
            traj_est = file_interface.read_tum_trajectory_file(os.path.join(folder_with_predicted_poses, filename))
            seq_results["length_of_estimated_traj"] = traj_est.path_length
        if args.result_format == 'euroc':
            traj_est = file_interface.read_euroc_csv_trajectory(os.path.join(folder_with_predicted_poses, filename))
        if args.result_format == 'tum' and args.gt_format == 'tum':
            seq_results["num_gt_poses"] = traj_ref.num_poses
            seq_results["num_predicted_poses"] = traj_est.num_poses
            traj_ref, traj_est = sync.associate_trajectories(traj_ref, traj_est, args.max_diff)
            end_time_est = traj_est.get_infos()["t_end (s)"]
            if (abs(end_time_est - end_time_gt) > 0.2) or (traj_est.get_infos()["t_start (s)"] > 0.2):
                print('LOST in track '+filename[:filename.rfind('.')])
                seq_results['lost'] = True
                results.append(seq_results)
                t.update(1)
                continue
        if args.alignment != None:
            traj_est = trajectory.align_trajectory(traj_est, traj_ref, correct_scale=args.alignment.find("scale") != -1, correct_only_scale=args.alignment=="scale")
        trajectory.align_trajectory_origin(traj_est, traj_ref)
        data = (traj_ref, traj_est)
        
        ape_metric_translation = metrics.APE(metrics.PoseRelation.translation_part)
        ape_metric_rotation = metrics.APE(metrics.PoseRelation.rotation_angle_deg)
        ape_metric_translation.process_data(data)
        ape_metric_rotation.process_data(data)
        ape_translation_statistics = ape_metric_translation.get_all_statistics()
        ape_rotation_statistics = ape_metric_rotation.get_all_statistics()
        
        ape_translation_statistics_plot = copy.deepcopy(ape_translation_statistics)
        ape_rotation_statistics_plot = copy.deepcopy(ape_rotation_statistics)
        ape_translation_statistics_plot.pop('sse')
        ape_translation_statistics_plot.pop('std')
        ape_translation_statistics_plot.pop('min')
        ape_translation_statistics_plot.pop('max')
        ape_rotation_statistics_plot.pop('sse')
        ape_rotation_statistics_plot.pop('std')
        ape_rotation_statistics_plot.pop('min')
        ape_rotation_statistics_plot.pop('max')
        
        kitti_trans_err, kitti_rot_err, ate = kitti_eval_tool.eval(traj_ref.poses_se3, 
                                                               traj_est.poses_se3, 
                                                               alignment=None)
    
        #---------------------------------adding results to variable seq_results for excel -----------------------------
        seq_results['metrics']['dist_to_trgt'] = traj_est.get_infos()['pos_end (m)'] - traj_ref.get_infos()['pos_end (m)']
        seq_results['metrics']['dist_to_trgt'] = np.sum(np.array(seq_results['metrics']['dist_to_trgt'])**2)**0.5
        seq_results['metrics']["Kitti trans err (%)"] = kitti_trans_err
        seq_results['metrics']["Kitti rot err (deg/m)"] = kitti_rot_err
        seq_results['metrics']["ATE (m)"] = ate
        seq_results['metrics']["APE(trans err) median (m)"] = ape_translation_statistics["median"]
        seq_results['metrics']["APE(rot err) median (deg)"] = ape_rotation_statistics["median"]
        #--------------------------------------------------------------------------------------------------------
        
        
        #-------------------------------------------------------------------------------------------------------    
    
        # --------------------------------printing results into console----------------------------------------------
        print('Results for "'+filename+'":')
        print('Kitti average translational error (%): {:.7f}'.format(kitti_trans_err))
        print('Kitti average rotational error (deg/m): {:.7f}'.format(kitti_rot_err))
        print('ATE (m): {:.7f}'.format(ate))
        print('APE(translation error) median (m): {:.7f}'.format(ape_translation_statistics["median"]))
        print('APE(rotation error) median (deg): {:.7f}'.format(ape_rotation_statistics["median"]))
        print('distance to target on the last frame: {:.7f}'.format(seq_results['metrics']['dist_to_trgt']))
        #------------------------------------------------------------------------------------------------------------
        
        #---------------------------------Saving results into overall results text file------------------------------
        file_results_txt.write('{:<24} '.format(filename[:filename.rfind('.')]))
        file_results_txt.write('{:>7.4f} '.format(kitti_trans_err))
        file_results_txt.write('{:>7.4f} '.format(kitti_rot_err))
        file_results_txt.write('{:>7.4f} '.format(ate))
        file_results_txt.write('{:>7.4f} '.format(ape_translation_statistics["median"]))
        file_results_txt.write('{:>7.4f} '.format(ape_rotation_statistics["median"]))
        file_results_txt.write('{:>7.4f}\n'.format(seq_results['metrics']['dist_to_trgt']))
        #------------------------------------------------------------------------------------------------------------
    
        # --------------------------------Saving metrics to text file for one track----------------------------------
        txt_filename = filename[:filename.rfind('.')]+"_metrics.txt"
        with open(os.path.join(output_folder_seq, txt_filename), "w") as txt_file:
            txt_file.write('Kitti average translational error (%): {:.7f}\n'.format(kitti_trans_err))
            txt_file.write('Kitti average rotational error (deg/m): {:.7f}\n'.format(kitti_rot_err))
            txt_file.write('ATE (m): {:.7f}\n'.format(ate))
            txt_file.write('APE(translation error) median (m): {:.7f}\n'.format(ape_translation_statistics["median"]))
            txt_file.write('APE(rotation error) median (deg): {:.7f}\n'.format(ape_rotation_statistics["median"]))
            txt_file.write('Distance to target on the last frame: {:.7f}\n'.format(seq_results['metrics']['dist_to_trgt']))
        #---------------------------------------------------------------------------------------------------------
    
        # ---------------------------------Saving values of errors for each frame to text file------------------------
        # ------------------------------------------for translation errors----------------------------------------
        txt_filename = filename[:filename.rfind('.')]+"_APE(translation)_errors.txt"
        output_folder_seq_translation = os.path.join(output_folder_seq,"translation")
        output_folder_seq_rotation = os.path.join(output_folder_seq,"rotation")
        os.makedirs(output_folder_seq_translation, exist_ok=True)
        os.makedirs(output_folder_seq_rotation, exist_ok=True)
        with open(os.path.join(output_folder_seq_translation, txt_filename), "w") as txt_file:
            for error in ape_metric_translation.error:
                txt_file.write('{:.10f}\n'.format(error))
        # -----------------------------------------for rotation degree errors--------------------------------------
        txt_filename = filename[:filename.rfind('.')]+"_APE(rotation_deg)_errors.txt"
        with open(os.path.join(output_folder_seq_rotation, txt_filename), "w") as txt_file:
            for error in ape_metric_rotation.error:
                txt_file.write('{:.10f}\n'.format(error))
        #----------------------------------------------------------------------------------------------------------
            
        # ---------------------------------------Saving plot of errors of each frame------------------------------
        # ------------------------------------------for translation errors----------------------------------------
        plot_collection = plot.PlotCollection("Example")
        fig_1 = plt.figure(figsize=(8, 8))
        plot.error_array(fig_1, ape_metric_translation.error, 
                         name="APE", title=str(ape_metric_translation), xlabel="Index of frame", ylabel='Error')
        plot_collection.add_figure("raw", fig_1)
        plot_filename = filename[:filename.rfind('.')]+"_APE(translation)_errors.png"
        plt.savefig(os.path.join(output_folder_seq_translation, plot_filename))
        plt.close(fig_1)
        # -----------------------------------------for rotation degree errors--------------------------------------
        plot_collection = plot.PlotCollection("Example")
        fig_1 = plt.figure(figsize=(8, 8))
        plot.error_array(fig_1, ape_metric_rotation.error, 
                         name="APE", title=str(ape_metric_rotation), xlabel="Index of frame", ylabel='Error')
        plot_collection.add_figure("raw", fig_1)
        plot_filename = filename[:filename.rfind('.')]+"_APE(rotation)_errors.png"
        plt.savefig(os.path.join(output_folder_seq_rotation,plot_filename))
        plt.close(fig_1)
        #-----------------------------------------------------------------------------------------------------------
    
        # -----------------------------------------Saving trajectory plot------------------------------------------- 
        # ------------------------------------------for translation errors----------------------------------------
        fig_2 = plt.figure(figsize=(8, 8))
        ax = plot.prepare_axis(fig_2, plot_mode)
        plot.traj(ax, plot_mode, traj_ref, '--', 'gray', 'reference')
        plot.traj_colormap( ax, traj_est, ape_metric_translation.error, plot_mode, 
                           min_map=ape_translation_statistics["min"],
                           max_map=ape_translation_statistics["max"], title="APE translation mapped onto trajectory")
        plot_collection.add_figure("traj (error)", fig_2)
        plot_filename = filename[:filename.rfind('.')]+"_APE(translation)_map.png"
        plt.savefig(os.path.join(output_folder_seq_translation,plot_filename))
        plt.close(fig_2)
        # -----------------------------------------for rotation degree errors--------------------------------------
        fig_2 = plt.figure(figsize=(8, 8))
        ax = plot.prepare_axis(fig_2, plot_mode)
        plot.traj(ax, plot_mode, traj_ref, '--', 'gray', 'reference')
        plot.traj_colormap( ax, traj_est, ape_metric_rotation.error, plot_mode, 
                           min_map=ape_rotation_statistics["min"],
                           max_map=ape_rotation_statistics["max"], title="APE rotation mapped onto trajectory")
        plot_collection.add_figure("traj (error)", fig_2)
        plot_filename = filename[:filename.rfind('.')]+"_APE(rotation)_map.png"
        plt.savefig(os.path.join(output_folder_seq_rotation,plot_filename))
        plt.close(fig_2)
        #-----------------------------------------------------------------------------------------------------------
        print()
        
        active_worksheet = wb['sheet1']
        thin = Side(border_style="thin", color="000000")
        thick = Side(border_style="thick", color="000000")
        medium = Side(border_style="medium", color="000000")
        font_header = Font(name='Arial',
                       size=10,
                       bold=True,
                       italic=False,
                       vertAlign=None,
                       underline='none',
                       strike=False,
                       color='FF000000')
        font_values = Font(name='Arial',
                       size=10,
                       bold=False,
                       italic=False,
                       vertAlign=None,
                               underline='none',
                       strike=False,
                       color='FF000000')

        active_worksheet.row_dimensions[2].height = 35
        
        file_results_txt.close()
        results.append(seq_results)
        t.update(1)
예제 #19
0
def main_ape(traj_ref,
             traj_est,
             pose_relation,
             align=True,
             correct_scale=False,
             ref_name="",
             est_name="",
             show_plot=False,
             save_plot=None,
             plot_mode=None,
             save_results=None,
             no_warnings=False,
             serialize_plot=None,
             plot_colormap_max=None,
             plot_colormap_min=None,
             plot_colormap_max_percentile=None):

    from evo.core import metrics, result
    from evo.core import trajectory
    from evo.tools import file_interface
    from evo.tools.settings import SETTINGS

    import numpy as np

    only_scale = correct_scale and not align
    if align or correct_scale:
        logger.debug(SEP)
        if only_scale:
            logger.debug("correcting scale...")
        else:
            logger.debug("aligning using Umeyama's method..." +
                         (" (with scale correction)" if correct_scale else ""))
        traj_est = trajectory.align_trajectory(traj_est, traj_ref,
                                               correct_scale, only_scale)
    logger.debug(SEP)

    # calculate APE
    data = (traj_ref, traj_est)
    ape_metric = metrics.APE(pose_relation)
    ape_metric.process_data(data)
    ape_statistics = ape_metric.get_all_statistics()

    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)"
    else:
        title += "\n(not aligned)"

    ape_result = ape_metric.get_result(ref_name, est_name)
    logger.debug(SEP)
    logger.info(ape_result.pretty_str())

    if isinstance(traj_est, trajectory.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)
    else:
        seconds_from_start = None

    if show_plot or save_plot or save_results or serialize_plot:
        if show_plot or save_plot or serialize_plot:
            from evo.tools import plot
            import matplotlib.pyplot as plt
            logger.debug(SEP)
            logger.debug("plotting results... ")
            fig1 = plt.figure(figsize=(SETTINGS.plot_figsize[0],
                                       SETTINGS.plot_figsize[1]))
            # metric values
            plot.error_array(
                fig1,
                ape_metric.error,
                x_array=seconds_from_start,
                statistics=ape_statistics,
                name="APE" + (" (" + ape_metric.unit.value + ")")
                if ape_metric.unit else "",
                title=title,
                xlabel="$t$ (s)" if seconds_from_start else "index")
            # info text
            if SETTINGS.plot_info_text and est_name and ref_name:
                ax = fig1.gca()
                ax.text(0,
                        -0.12,
                        "estimate:  " + est_name + "\nreference: " + ref_name,
                        transform=ax.transAxes,
                        fontsize=8,
                        color="gray")

            # trajectory colormapped
            fig2 = plt.figure(figsize=(SETTINGS.plot_figsize[0],
                                       SETTINGS.plot_figsize[1]))
            plot_mode = plot_mode if plot_mode is not None else plot.PlotMode.xyz
            ax = plot.prepare_axis(fig2, plot_mode)
            plot.traj(ax,
                      plot_mode,
                      traj_ref,
                      '--',
                      'gray',
                      'reference',
                      alpha=0.0 if SETTINGS.plot_hideref else 1.0)

            min_map = ape_statistics[
                "min"] if plot_colormap_min is None else plot_colormap_min
            if plot_colormap_max_percentile is not None:
                max_map = np.percentile(ape_result.np_arrays["error_array"],
                                        plot_colormap_max_percentile)
            else:
                max_map = ape_statistics[
                    "max"] if plot_colormap_max is None else plot_colormap_max

            plot.traj_colormap(ax,
                               traj_est,
                               ape_metric.error,
                               plot_mode,
                               min_map=min_map,
                               max_map=max_map,
                               title="APE mapped onto trajectory")
            fig2.axes.append(ax)

            plot_collection = plot.PlotCollection(title)
            plot_collection.add_figure("raw", fig1)
            plot_collection.add_figure("map", fig2)
            if show_plot:
                plot_collection.show()
            if save_plot:
                plot_collection.export(save_plot,
                                       confirm_overwrite=not no_warnings)
            if serialize_plot:
                logger.debug(SEP)
                plot_collection.serialize(serialize_plot,
                                          confirm_overwrite=not no_warnings)

    if save_results:
        logger.debug(SEP)
        if SETTINGS.save_traj_in_zip:
            ape_result.add_trajectory("traj_ref", traj_ref)
            ape_result.add_trajectory("traj_est", traj_est)
        file_interface.save_res_file(save_results,
                                     ape_result,
                                     confirm_overwrite=not no_warnings)

    return ape_result
    def run_analysis(self,
                     traj_ref_path,
                     traj_vio_path,
                     traj_pgo_path,
                     segments,
                     dataset_name="",
                     discard_n_start_poses=0,
                     discard_n_end_poses=0):
        """ Analyze data from a set of trajectory csv files.

            Args:
                traj_ref_path: string representing filepath of the reference (ground-truth) trajectory.
                traj_vio_path: string representing filepath of the vio estimated trajectory.
                traj_pgo_path: string representing filepath of the pgo estimated trajectory.
                segments: list of segments for RPE calculation, defined in the experiments yaml file.
                dataset_name: string representing the dataset's name
                discard_n_start_poses: int representing number of poses to discard from start of analysis.
                discard_n_end_poses: int representing the number of poses to discard from end of analysis.
        """
        import copy

        # Mind that traj_est_pgo might be None
        traj_ref, traj_est_vio, traj_est_pgo = self.read_traj_files(
            traj_ref_path, traj_vio_path, traj_pgo_path)

        # We copy to distinguish from the pgo version that may be created
        traj_ref_vio = copy.deepcopy(traj_ref)

        # Register and align trajectories:
        evt.print_purple("Registering and aligning trajectories")
        traj_ref_vio, traj_est_vio = sync.associate_trajectories(
            traj_ref_vio, traj_est_vio)
        traj_est_vio = trajectory.align_trajectory(
            traj_est_vio,
            traj_ref_vio,
            correct_scale=False,
            discard_n_start_poses=int(discard_n_start_poses),
            discard_n_end_poses=int(discard_n_end_poses))

        # We do the same for the PGO trajectory if needed:
        traj_ref_pgo = None
        if traj_est_pgo is not None:
            traj_ref_pgo = copy.deepcopy(traj_ref)
            traj_ref_pgo, traj_est_pgo = sync.associate_trajectories(
                traj_ref_pgo, traj_est_pgo)
            traj_est_pgo = trajectory.align_trajectory(
                traj_est_pgo,
                traj_ref_pgo,
                correct_scale=False,
                discard_n_start_poses=int(discard_n_start_poses),
                discard_n_end_poses=int(discard_n_end_poses))

        # We need to pick the lowest num_poses before doing any computation:
        num_of_poses = traj_est_vio.num_poses
        if traj_est_pgo is not None:
            num_of_poses = min(num_of_poses, traj_est_pgo.num_poses)
            traj_est_pgo.reduce_to_ids(
                range(int(discard_n_start_poses),
                      int(num_of_poses - discard_n_end_poses), 1))
            traj_ref_pgo.reduce_to_ids(
                range(int(discard_n_start_poses),
                      int(num_of_poses - discard_n_end_poses), 1))

        traj_est_vio.reduce_to_ids(
            range(int(discard_n_start_poses),
                  int(num_of_poses - discard_n_end_poses), 1))
        traj_ref_vio.reduce_to_ids(
            range(int(discard_n_start_poses),
                  int(num_of_poses - discard_n_end_poses), 1))

        # Calculate all metrics:
        (ape_metric_vio, rpe_metric_trans_vio, rpe_metric_rot_vio,
         results_vio) = self.process_trajectory_data(traj_ref_vio,
                                                     traj_est_vio, segments,
                                                     True)

        # We do the same for the pgo trajectory if needed:
        ape_metric_pgo = None
        rpe_metric_trans_pgo = None
        rpe_metric_rot_pgo = None
        results_pgo = None
        if traj_est_pgo is not None:
            (ape_metric_pgo, rpe_metric_trans_pgo, rpe_metric_rot_pgo,
             results_pgo) = self.process_trajectory_data(
                 traj_ref_pgo, traj_est_pgo, segments, False)

        # Generate plots for return:
        plot_collection = None
        if self.display_plots or self.save_plots:
            evt.print_green("Plotting:")
            log.info(dataset_name)
            plot_collection = plot.PlotCollection("Example")

            if traj_est_pgo is not None:
                # APE Metric Plot:
                plot_collection.add_figure(
                    "PGO_APE_translation",
                    plot_metric(ape_metric_pgo, "PGO + VIO APE Translation"))

                # Trajectory Colormapped with ATE Plot:
                plot_collection.add_figure(
                    "PGO_APE_translation_trajectory_error",
                    plot_traj_colormap_ape(
                        ape_metric_pgo, traj_ref_pgo, traj_est_vio,
                        traj_est_pgo, "PGO + VIO ATE Mapped Onto Trajectory"))

                # RPE Translation Metric Plot:
                plot_collection.add_figure(
                    "PGO_RPE_translation",
                    plot_metric(rpe_metric_trans_pgo,
                                "PGO + VIO RPE Translation"))

                # Trajectory Colormapped with RTE Plot:
                plot_collection.add_figure(
                    "PGO_RPE_translation_trajectory_error",
                    plot_traj_colormap_rpe(
                        rpe_metric_trans_pgo, traj_ref_pgo, traj_est_vio,
                        traj_est_pgo,
                        "PGO + VIO RPE Translation Error Mapped Onto Trajectory"
                    ))

                # RPE Rotation Metric Plot:
                plot_collection.add_figure(
                    "PGO_RPE_Rotation",
                    plot_metric(rpe_metric_rot_pgo, "PGO + VIO RPE Rotation"))

                # Trajectory Colormapped with RTE Plot:
                plot_collection.add_figure(
                    "PGO_RPE_rotation_trajectory_error",
                    plot_traj_colormap_rpe(
                        rpe_metric_rot_pgo, traj_ref_pgo, traj_est_vio,
                        traj_est_pgo,
                        "PGO + VIO RPE Rotation Error Mapped Onto Trajectory"))

            # Plot VIO results
            plot_collection.add_figure(
                "VIO_APE_translation",
                plot_metric(ape_metric_vio, "VIO APE Translation"))

            plot_collection.add_figure(
                "VIO_APE_translation_trajectory_error",
                plot_traj_colormap_ape(ape_metric_vio, traj_ref_vio,
                                       traj_est_vio, None,
                                       "VIO ATE Mapped Onto Trajectory"))

            plot_collection.add_figure(
                "VIO_RPE_translation",
                plot_metric(rpe_metric_trans_vio, "VIO RPE Translation"))

            plot_collection.add_figure(
                "VIO_RPE_translation_trajectory_error",
                plot_traj_colormap_rpe(
                    rpe_metric_trans_vio, traj_ref_vio, traj_est_vio, None,
                    "VIO RPE Translation Error Mapped Onto Trajectory"))

            plot_collection.add_figure(
                "VIO_RPE_Rotation",
                plot_metric(rpe_metric_rot_vio, "VIO RPE Rotation"))

            plot_collection.add_figure(
                "VIO_RPE_rotation_trajectory_error",
                plot_traj_colormap_rpe(
                    rpe_metric_rot_vio, traj_ref_vio, traj_est_vio, None,
                    "VIO RPE Rotation Error Mapped Onto Trajectory"))

        return [plot_collection, results_vio, results_pgo]
예제 #21
0
# res_final = []
for seq in seqs:
    traj_files = glob.glob(str(data_path / f'{seq}/*.txt'))
    # print(data_path / f'{seq}')
    gt_file = f'{gt_path}/{seq}.csv'

    failure_count = 0
    if not len(traj_files) == 0:
        mean, rmse = [], []
        for traj_file in traj_files:
            traj_gt = file_interface.read_euroc_csv_trajectory(gt_file)
            traj_est = file_interface.read_tum_trajectory_file(traj_file)
            kf_traj_est = file_interface.read_tum_trajectory_file(traj_file)

            traj_gt, traj_est = sync.associate_trajectories(traj_gt, traj_est)
            traj_est_aligned, rot, trans, scale = trajectory.align_trajectory(
                traj_est, traj_gt, correct_scale=True, return_parameters=True)

            data = (traj_gt, traj_est_aligned)
            ape_metric = metrics.APE(pose_relation=pose_relation)

            ape_metric.process_data(data)
            ape_stat = ape_metric.get_all_statistics()
            mean_curr = ape_stat['mean']
            rmse_curr = ape_stat['rmse']
            if mean_curr > 1.0 or rmse_curr > 1.0:
                failure_count += 1
                continue
            mean.append(mean_curr)
            rmse.append(rmse_curr)

        print(
예제 #22
0
def run(args):
    import os
    import sys

    import numpy as np

    import evo.core.lie_algebra as lie
    from evo.core import trajectory
    from evo.core.trajectory import PoseTrajectory3D
    from evo.tools import file_interface, log
    from evo.tools.settings import SETTINGS

    log.configure_logging(verbose=args.verbose,
                          silent=args.silent,
                          debug=args.debug)
    if args.debug:
        import pprint
        logger.debug(
            "main_parser config:\n" +
            pprint.pformat({arg: getattr(args, arg)
                            for arg in vars(args)}) + "\n")
    logger.debug(SEP)

    trajectories, ref_traj = load_trajectories(args)

    if args.merge:
        if args.subcommand == "kitti":
            die("Can't merge KITTI files.")
        if len(trajectories) == 0:
            die("No trajectories to merge (excluding --ref).")
        trajectories = {
            "merged_trajectory": trajectory.merge(trajectories.values())
        }

    if args.transform_left or args.transform_right:
        tf_type = "left" if args.transform_left else "right"
        tf_path = args.transform_left \
                if args.transform_left else args.transform_right
        transform = file_interface.load_transform_json(tf_path)
        logger.debug(SEP)
        if not lie.is_se3(transform):
            logger.warning("Not a valid SE(3) transformation!")
        if args.invert_transform:
            transform = lie.se3_inverse(transform)
        logger.debug("Applying a {}-multiplicative transformation:\n{}".format(
            tf_type, transform))
        for traj in trajectories.values():
            traj.transform(transform, right_mul=args.transform_right)

    if args.t_offset:
        logger.debug(SEP)
        for name, traj in trajectories.items():
            if type(traj) is trajectory.PosePath3D:
                die("{} doesn't have timestamps - can't add time offset.".
                    format(name))
            logger.info("Adding time offset to {}: {} (s)".format(
                name, args.t_offset))
            traj.timestamps += args.t_offset

    if args.sync or args.align or args.correct_scale:
        from evo.core import sync
        if not args.ref:
            logger.debug(SEP)
            die("Can't align or sync without a reference! (--ref)  *grunt*")
        for name, traj in trajectories.items():
            if args.subcommand == "kitti":
                ref_traj_tmp = ref_traj
            else:
                logger.debug(SEP)
                ref_traj_tmp, trajectories[name] = sync.associate_trajectories(
                    ref_traj,
                    traj,
                    max_diff=args.t_max_diff,
                    first_name="reference",
                    snd_name=name)
            if args.align or args.correct_scale:
                logger.debug(SEP)
                logger.debug("Aligning {} to reference.".format(name))
                trajectories[name] = trajectory.align_trajectory(
                    trajectories[name],
                    ref_traj_tmp,
                    correct_scale=args.correct_scale,
                    correct_only_scale=args.correct_scale and not args.align,
                    n=args.n_to_align)

    for name, traj in trajectories.items():
        print_traj_info(name, traj, args.verbose, args.full_check)
    if args.ref:
        print_traj_info(args.ref, ref_traj, args.verbose, args.full_check)

    if args.plot or args.save_plot or args.serialize_plot:
        from evo.tools.plot import PlotMode
        plot_mode = PlotMode.xyz if not args.plot_mode else PlotMode[
            args.plot_mode]
        import numpy as np
        from evo.tools import plot
        import matplotlib.pyplot as plt
        import matplotlib.cm as cm

        plot_collection = plot.PlotCollection("evo_traj - trajectory plot")
        fig_xyz, axarr_xyz = plt.subplots(3,
                                          sharex="col",
                                          figsize=tuple(SETTINGS.plot_figsize))
        fig_rpy, axarr_rpy = plt.subplots(3,
                                          sharex="col",
                                          figsize=tuple(SETTINGS.plot_figsize))
        fig_traj = plt.figure(figsize=tuple(SETTINGS.plot_figsize))
        ax_traj = plot.prepare_axis(fig_traj, plot_mode)
        pltstart = 0
        pltend = traj.num_poses
        if args.plotstart:
            pltstart = args.plotstart
        if args.plotend != -1:
            pltend = args.plotend

        if args.ref:
            short_traj_name = os.path.splitext(os.path.basename(args.ref))[0]
            if SETTINGS.plot_usetex:
                short_traj_name = short_traj_name.replace("_", "\\_")
            plot.traj(ax_traj,
                      plot_mode,
                      ref_traj,
                      style=SETTINGS.plot_reference_linestyle,
                      color=SETTINGS.plot_reference_color,
                      label=short_traj_name,
                      alpha=SETTINGS.plot_reference_alpha,
                      start=pltstart,
                      end=pltend)
            plot.traj_xyz(axarr_xyz,
                          ref_traj,
                          style=SETTINGS.plot_reference_linestyle,
                          color=SETTINGS.plot_reference_color,
                          label=short_traj_name,
                          alpha=SETTINGS.plot_reference_alpha,
                          start=pltstart,
                          end=pltend)
            plot.traj_rpy(axarr_rpy,
                          ref_traj,
                          style=SETTINGS.plot_reference_linestyle,
                          color=SETTINGS.plot_reference_color,
                          label=short_traj_name,
                          alpha=SETTINGS.plot_reference_alpha,
                          start=pltstart,
                          end=pltend)

        cmap_colors = None
        if SETTINGS.plot_multi_cmap.lower() != "none":
            cmap = getattr(cm, SETTINGS.plot_multi_cmap)
            cmap_colors = iter(cmap(np.linspace(0, 1, len(trajectories))))

        fig_3 = plt.figure(figsize=tuple(SETTINGS.plot_figsize))
        #plot_mode = plot.PlotMode.xz
        ax = plot.prepare_axis(fig_3, plot_mode)
        fig_3.axes.append(ax)
        for name, traj in trajectories.items():
            num = traj.positions_xyz.shape[0]
            if pltstart >= num:
                print(name, "plotstart > len!", num)
                pltstart = 0
            if pltend != -1 and (pltend > num or pltend < pltstart):
                print(name, "plotend > len!", num)
                pltend = traj.num_poses

            pltstart = int(pltstart)
            pltend = int(pltend)
            if cmap_colors is None:
                color = next(ax_traj._get_lines.prop_cycler)['color']
            else:
                color = next(cmap_colors)
            short_traj_name = os.path.splitext(os.path.basename(name))[0]
            if SETTINGS.plot_usetex:
                short_traj_name = short_traj_name.replace("_", "\\_")
            plot.traj(ax_traj,
                      plot_mode,
                      traj,
                      '-',
                      color,
                      short_traj_name,
                      start=pltstart,
                      end=pltend)
            if args.ref and isinstance(ref_traj, trajectory.PoseTrajectory3D):
                start_time = ref_traj.timestamps[0]
            else:
                start_time = None
            plot.traj_xyz(axarr_xyz,
                          traj,
                          '-',
                          color,
                          short_traj_name,
                          start_timestamp=start_time,
                          start=pltstart,
                          end=pltend)
            plot.traj_rpy(axarr_rpy,
                          traj,
                          '-',
                          color,
                          short_traj_name,
                          start_timestamp=start_time,
                          start=pltstart,
                          end=pltend)

            speeds = [
                trajectory.calc_speed(traj.positions_xyz[i],
                                      traj.positions_xyz[i + 1],
                                      traj.timestamps[i],
                                      traj.timestamps[i + 1])
                for i in range(pltstart, pltend - 1)
            ]
            speeds.append(0)
            #plot.traj(ax, plot_mode, traj, '--', 'gray', 'reference')
            plot.traj_colormap(ax,
                               traj,
                               speeds,
                               plot_mode,
                               min_map=min(speeds),
                               max_map=max(max(speeds), 10),
                               title="speed mapped onto trajectory",
                               start=pltstart,
                               end=pltend)

        plot_collection.add_figure("trajectories", fig_traj)
        plot_collection.add_figure("xyz_view", fig_xyz)
        plot_collection.add_figure("rpy_view", fig_rpy)
        plot_collection.add_figure("traj (speed)", fig_3)
        if args.plot:
            plot_collection.show()
        if args.save_plot:
            logger.info(SEP)
            plot_collection.export(args.save_plot,
                                   confirm_overwrite=not args.no_warnings)
        if args.serialize_plot:
            logger.info(SEP)
            plot_collection.serialize(args.serialize_plot,
                                      confirm_overwrite=not args.no_warnings)

    if args.save_as_tum:
        logger.info(SEP)
        for name, traj in trajectories.items():
            dest = os.path.splitext(os.path.basename(name))[0] + ".tum"
            file_interface.write_tum_trajectory_file(
                dest, traj, confirm_overwrite=not args.no_warnings)
        if args.ref:
            dest = os.path.splitext(os.path.basename(args.ref))[0] + ".tum"
            file_interface.write_tum_trajectory_file(
                dest, ref_traj, confirm_overwrite=not args.no_warnings)
    if args.save_as_kitti:
        logger.info(SEP)
        for name, traj in trajectories.items():
            dest = os.path.splitext(os.path.basename(name))[0] + ".kitti"
            file_interface.write_kitti_poses_file(
                dest, traj, confirm_overwrite=not args.no_warnings)
        if args.ref:
            dest = os.path.splitext(os.path.basename(args.ref))[0] + ".kitti"
            file_interface.write_kitti_poses_file(
                dest, ref_traj, confirm_overwrite=not args.no_warnings)
    if args.save_as_bag:
        import datetime
        import rosbag
        dest_bag_path = str(
            datetime.datetime.now().strftime("%Y-%m-%d-%H-%M-%S")) + ".bag"
        logger.info(SEP)
        logger.info("Saving trajectories to " + dest_bag_path + "...")
        bag = rosbag.Bag(dest_bag_path, 'w')
        try:
            for name, traj in trajectories.items():
                dest_topic = os.path.splitext(os.path.basename(name))[0]
                frame_id = traj.meta[
                    "frame_id"] if "frame_id" in traj.meta else ""
                file_interface.write_bag_trajectory(bag, traj, dest_topic,
                                                    frame_id)
            if args.ref:
                dest_topic = os.path.splitext(os.path.basename(args.ref))[0]
                frame_id = ref_traj.meta[
                    "frame_id"] if "frame_id" in ref_traj.meta else ""
                file_interface.write_bag_trajectory(bag, ref_traj, dest_topic,
                                                    frame_id)
        finally:
            bag.close()
import numpy as np
import matplotlib.pyplot as plt

logging.basicConfig(format="%(message)s",
                    stream=sys.stdout,
                    level=logging.DEBUG)

traj_ref = file_interface.read_kitti_poses_file("../data/KITTI_00_gt.txt")
traj_est = file_interface.read_kitti_poses_file("../data/KITTI_00_ORB.txt")

# add artificial Sim(3) transformation
traj_est.transform(lie.se3(np.eye(3), [0, 0, 0]))
traj_est.scale(0.5)

logging.info("\nUmeyama alignment without scaling")
traj_est_aligned = trajectory.align_trajectory(traj_est, traj_ref)
logging.info("\nUmeyama alignment with scaling")
traj_est_aligned_scaled = trajectory.align_trajectory(traj_est,
                                                      traj_ref,
                                                      correct_scale=True)
logging.info("\nUmeyama alignment with scaling only")
traj_est_aligned_only_scaled = trajectory.align_trajectory(
    traj_est, traj_ref, correct_only_scale=True)

fig = plt.figure(figsize=(8, 8))
# fig.suptitle("Umeyama $\mathrm{Sim}(3)$ alignment")
plot_mode = plot.PlotMode.xz
ax = plot.prepare_axis(fig, plot_mode,
                       subplot_arg='221')  # 122 = 1*2 grid, second
plot.traj(ax, plot_mode, traj_ref, '--', 'gray')  #, 'reference')
plot.traj(ax, plot_mode, traj_est, '-', 'blue')  #, 'not aligned')
def main_rpe_for_each(traj_ref, traj_est, pose_relation, mode, bins, rel_tols,
                      align=False, correct_scale=False, ref_name="", est_name="",
                      show_plot=False, save_plot=None, save_results=None, no_warnings=False,
                      serialize_plot=None):

    from evo.core import metrics, result
    from evo.core import filters
    from evo.core import trajectory
    from evo.tools import file_interface
    from evo.tools.settings import SETTINGS

    if not bins or not rel_tols:
        raise RuntimeError("bins and tolerances must have more than one element")
    if len(bins) != len(rel_tols):
        raise RuntimeError("bins and tolerances must have the same number of elements")
    if mode in {"speed", "angular_speed"} and traj_est is trajectory.PosePath3D:
        raise RuntimeError("timestamps are required for mode: " + mode)

    bin_unit = None
    if mode == "speed":
        bin_unit = metrics.VelUnit.meters_per_sec
    elif mode == "path":
        bin_unit = metrics.Unit.meters
    elif mode == "angle":
        bin_unit = metrics.Unit.degrees
    elif mode == "angular_speed":
        bin_unit = metrics.VelUnit.degrees_per_sec

    rpe_unit = None
    if pose_relation is metrics.PoseRelation.translation_part:
        rpe_unit = metrics.Unit.meters
    elif pose_relation is metrics.PoseRelation.rotation_angle_deg:
        rpe_unit = metrics.Unit.degrees
    elif pose_relation is metrics.PoseRelation.rotation_angle_rad:
        rpe_unit = metrics.Unit.radians

    correct_only_scale = correct_scale and not align
    if align or correct_scale:
        logger.debug(SEP)
        if correct_only_scale:
            logger.debug("Correcting scale...")
        else:
            logger.debug("Aligning using Umeyama's method..."
                         + (" (with scale correction)" if correct_scale else ""))
        traj_est = trajectory.align_trajectory(traj_est, traj_ref, correct_scale,
                                               correct_only_scale)

    results = []
    for bin, rel_tol, in zip(bins, rel_tols):
        logger.debug(SEP)
        logger.info(
            "Calculating RPE for each sub-sequence of " + str(bin) + " (" + bin_unit.value + ")")

        tol = bin * rel_tol
        id_pairs = []
        if mode == "path":
            id_pairs = filters.filter_pairs_by_path(traj_ref.poses_se3, bin, tol, all_pairs=True)
        elif mode == "angle":
            id_pairs = filters.filter_pairs_by_angle(traj_ref.poses_se3, bin, tol, degrees=True)
        elif mode == "speed":
            id_pairs = filters.filter_pairs_by_speed(traj_ref.poses_se3, traj_ref.timestamps,
                                                     bin, tol)
        elif mode == "angular_speed":
            id_pairs = filters.filter_pairs_by_angular_speed(traj_ref.poses_se3,
                                                             traj_ref.timestamps, bin, tol, True)

        if len(id_pairs) == 0:
            raise RuntimeError("bin " + str(bin) + " (" + str(bin_unit.value) + ") "
                               + "produced empty index list - try other values")

        # calculate RPE with all IDs (delta 1 frames)
        data = (traj_ref, traj_est)
        # the delta here has nothing to do with the bin - 1f delta just to use all poses of the bin
        rpe_metric = metrics.RPE(pose_relation, delta=1, delta_unit=metrics.Unit.frames,
                                 all_pairs=True)
        rpe_metric.process_data(data, id_pairs)
        mean = rpe_metric.get_statistic(metrics.StatisticsType.mean)
        results.append(mean)

    if SETTINGS.plot_usetex:
        mode.replace("_", "\_")
    title = "mean RPE w.r.t. " + pose_relation.value + "\nfor different " + mode + " sub-sequences"
    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 correct_only_scale:
        title += "\n(scale corrected)"
    else:
        title += "\n(not aligned)"

    rpe_for_each_result = result.Result()
    rpe_for_each_result.add_info({
        "label": "RPE ({})".format(rpe_unit.value),
        "est_name": est_name,
        "ref_name": ref_name,
        "title": title,
        "xlabel": "{} sub-sequences ({})".format(mode, bin_unit.value)
    })
    rpe_for_each_result.add_stats({bin: result for bin, result in zip(bins, results)})
    # TODO use a more suitable name than seconds
    rpe_for_each_result.add_np_array("seconds_from_start", bins)
    rpe_for_each_result.add_np_array("error_array", results)

    logger.debug(SEP)
    logger.info(rpe_for_each_result.pretty_str())

    if show_plot or save_plot or serialize_plot:
        from evo.tools import plot
        import matplotlib.pyplot as plt
        plot_collection = plot.PlotCollection(title)
        fig = plt.figure(figsize=(SETTINGS.plot_figsize[0], SETTINGS.plot_figsize[1]))
        plot.error_array(fig, results, x_array=bins,
                         name="mean RPE" + (" (" + rpe_unit.value + ")") if rpe_unit else "",
                         marker="o", title=title,
                         xlabel=mode + " sub-sequences " + " (" + bin_unit.value + ")")
        # info text
        if SETTINGS.plot_info_text and est_name and ref_name:
            ax = fig.gca()
            ax.text(0, -0.12, "estimate:  " + est_name + "\nreference: " + ref_name,
                    transform=ax.transAxes, fontsize=8, color="gray")
        plt.title(title)
        plot_collection.add_figure("raw", fig)
        if show_plot:
            plot_collection.show()
        if save_plot:
            plot_collection.export(save_plot, confirm_overwrite=not no_warnings)
        if serialize_plot:
            logger.debug(SEP)
            plot_collection.serialize(serialize_plot, confirm_overwrite=not no_warnings)

    if save_results:
        logger.debug(SEP)
        if SETTINGS.save_traj_in_zip:
            rpe_for_each_result.add_trajectory("traj_ref", traj_ref)
            rpe_for_each_result.add_trajectory("traj_est", traj_est)
        file_interface.save_res_file(save_results, rpe_for_each_result,
                                     confirm_overwrite=not no_warnings)

    return rpe_for_each_result
예제 #25
0
def main_rpe(traj_ref,
             traj_est,
             pose_relation,
             delta,
             delta_unit,
             rel_delta_tol=0.1,
             all_pairs=False,
             align=False,
             correct_scale=False,
             ref_name="",
             est_name="",
             show_plot=False,
             save_plot=None,
             plot_mode=None,
             save_results=None,
             no_warnings=False,
             support_loop=False,
             serialize_plot=None):

    from evo.core import metrics, result
    from evo.core import trajectory
    from evo.tools import file_interface
    from evo.tools.settings import SETTINGS

    if (show_plot or save_plot or serialize_plot) and all_pairs:
        raise metrics.MetricsException(
            "all_pairs mode cannot be used with plotting functions")

    only_scale = correct_scale and not align
    if align or correct_scale:
        logging.debug(SEP)
        if only_scale:
            logging.debug("correcting scale...")
        else:
            logging.debug("aligning using Umeyama's method..." + (
                " (with scale correction)" if correct_scale else ""))
        traj_est = trajectory.align_trajectory(traj_est, traj_ref,
                                               correct_scale, only_scale)
    logging.debug(SEP)

    # calculate RPE
    data = (traj_ref, traj_est)
    rpe_metric = metrics.RPE(pose_relation, delta, delta_unit, rel_delta_tol,
                             all_pairs)
    rpe_metric.process_data(data)
    rpe_statistics = rpe_metric.get_all_statistics()

    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)"
    else:
        title += "\n(not aligned)"

    rpe_result = result.from_metric(rpe_metric, title, ref_name, est_name)
    logging.debug(SEP)
    logging.info(rpe_result.pretty_str())

    # restrict trajectories to delta ids
    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)
    if isinstance(traj_est, trajectory.PoseTrajectory3D) and not all_pairs:
        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)
    else:
        seconds_from_start = None

    if show_plot or save_plot or serialize_plot and not all_pairs:
        from evo.tools import plot
        import matplotlib.pyplot as plt
        logging.debug(SEP)
        logging.debug("plotting results... ")
        fig1 = plt.figure(figsize=(SETTINGS.plot_figsize[0],
                                   SETTINGS.plot_figsize[1]))
        # metric values
        plot.error_array(
            fig1,
            rpe_metric.error,
            x_array=seconds_from_start,
            statistics=rpe_statistics,
            name="RPE" +
            (" (" + rpe_metric.unit.value + ")") if rpe_metric.unit else "",
            title=title,
            xlabel="$t$ (s)" if seconds_from_start else "index")
        # info text
        if SETTINGS.plot_info_text and est_name and ref_name:
            ax = fig1.gca()
            ax.text(0,
                    -0.12,
                    "estimate:  " + est_name + "\nreference: " + ref_name,
                    transform=ax.transAxes,
                    fontsize=8,
                    color="gray")
        # trajectory colormapped
        fig2 = plt.figure(figsize=(SETTINGS.plot_figsize[0],
                                   SETTINGS.plot_figsize[1]))
        plot_mode = plot_mode if plot_mode is not None else plot.PlotMode.xyz
        ax = plot.prepare_axis(fig2, plot_mode)
        plot.traj(ax,
                  plot_mode,
                  traj_ref,
                  '--',
                  'gray',
                  'reference',
                  alpha=0 if SETTINGS.plot_hideref else 1)
        plot.traj_colormap(ax,
                           traj_est,
                           rpe_metric.error,
                           plot_mode,
                           min_map=rpe_statistics["min"],
                           max_map=rpe_statistics["max"],
                           title="RPE mapped onto trajectory")
        fig2.axes.append(ax)
        plot_collection = plot.PlotCollection(title)
        plot_collection.add_figure("raw", fig1)
        plot_collection.add_figure("map", fig2)
        if show_plot:
            plot_collection.show()
        if save_plot:
            plot_collection.export(save_plot,
                                   confirm_overwrite=not no_warnings)
        if serialize_plot:
            logging.debug(SEP)
            plot_collection.serialize(serialize_plot,
                                      confirm_overwrite=not no_warnings)

    if save_results:
        logging.debug(SEP)
        if SETTINGS.save_traj_in_zip:
            rpe_result.add_trajectory("traj_ref", traj_ref)
            rpe_result.add_trajectory("traj_est", traj_est)
        file_interface.save_res_file(save_results,
                                     rpe_result,
                                     confirm_overwrite=not no_warnings)

    return rpe_result
예제 #26
0
def run(args):
    import os
    import sys

    import numpy as np

    import evo.core.lie_algebra as lie
    from evo.core import trajectory
    from evo.core.trajectory import PoseTrajectory3D
    from evo.tools import file_interface, log
    from evo.tools.settings import SETTINGS

    log.configure_logging(verbose=args.verbose,
                          silent=args.silent,
                          debug=args.debug)
    if args.debug:
        import pprint
        logger.debug(
            "main_parser config:\n" +
            pprint.pformat({arg: getattr(args, arg)
                            for arg in vars(args)}) + "\n")
    logger.debug(SEP)

    trajectories = []
    ref_traj = None
    if args.subcommand == "tum":
        for traj_file in args.traj_files:
            if traj_file != args.ref:
                trajectories.append(
                    (traj_file,
                     file_interface.read_tum_trajectory_file(traj_file)))
        if args.ref:
            ref_traj = file_interface.read_tum_trajectory_file(args.ref)
    elif args.subcommand == "kitti":
        for pose_file in args.pose_files:
            if pose_file != args.ref:
                trajectories.append(
                    (pose_file,
                     file_interface.read_kitti_poses_file(pose_file)))
        if args.ref:
            ref_traj = file_interface.read_kitti_poses_file(args.ref)
    elif args.subcommand == "euroc":
        for csv_file in args.state_gt_csv:
            if csv_file != args.ref:
                trajectories.append(
                    (csv_file,
                     file_interface.read_euroc_csv_trajectory(csv_file)))
        if args.ref:
            ref_traj = file_interface.read_euroc_csv_trajectory(args.ref)
    elif args.subcommand == "bag":
        import rosbag
        bag = rosbag.Bag(args.bag)
        try:
            if args.all_topics:
                topic_info = bag.get_type_and_topic_info()
                topics = sorted([
                    t for t in topic_info[1].keys()
                    if topic_info[1][t][0] == "geometry_msgs/PoseStamped"
                    and t != args.ref
                ])
                if len(topics) == 0:
                    logger.error("No geometry_msgs/PoseStamped topics found!")
                    sys.exit(1)
            else:
                topics = args.topics
                if not topics:
                    logger.warning(
                        "No topics used - specify topics or set --all_topics.")
                    sys.exit(1)
            for topic in topics:
                trajectories.append(
                    (topic, file_interface.read_bag_trajectory(bag, topic)))
            if args.ref:
                ref_traj = file_interface.read_bag_trajectory(bag, args.ref)
        finally:
            bag.close()
    else:
        raise RuntimeError("unsupported subcommand: " + args.subcommand)

    if args.merge:
        if args.subcommand == "kitti":
            raise TypeError(
                "can't merge KITTI files - but you can append them with 'cat'")
        if len(trajectories) == 0:
            raise RuntimeError("no trajectories to merge (excluding --ref)")
        merged_stamps = trajectories[0][1].timestamps
        merged_xyz = trajectories[0][1].positions_xyz
        merged_quat = trajectories[0][1].orientations_quat_wxyz
        for _, traj in trajectories[1:]:
            merged_stamps = np.concatenate((merged_stamps, traj.timestamps))
            merged_xyz = np.concatenate((merged_xyz, traj.positions_xyz))
            merged_quat = np.concatenate(
                (merged_quat, traj.orientations_quat_wxyz))
        order = merged_stamps.argsort()
        merged_stamps = merged_stamps[order]
        merged_xyz = merged_xyz[order]
        merged_quat = merged_quat[order]
        trajectories = [("merged_trajectory",
                         PoseTrajectory3D(merged_xyz, merged_quat,
                                          merged_stamps))]

    if args.transform_left or args.transform_right:
        tf_type = "left" if args.transform_left else "right"
        tf_path = args.transform_left if args.transform_left else args.transform_right
        t, xyz, quat = file_interface.load_transform_json(tf_path)
        logger.debug(SEP)
        if not lie.is_se3(t):
            logger.warning("Not a valid SE(3) transformation!")
        if args.invert_transform:
            t = lie.se3_inverse(t)
        logger.debug("Applying a {}-multiplicative transformation:\n{}".format(
            tf_type, t))
        for name, traj in trajectories:
            traj.transform(t, right_mul=args.transform_right)

    if args.t_offset:
        logger.debug(SEP)
        for name, traj in trajectories:
            if type(traj) is trajectory.PosePath3D:
                logger.warning(
                    "{} doesn't have timestamps - can't add time offset.".
                    format(name))
            else:
                logger.info("Adding time offset to {}: {} (s)".format(
                    name, args.t_offset))
                traj.timestamps += args.t_offset

    if args.align or args.correct_scale:
        if not args.ref:
            logger.debug(SEP)
            logger.warning("Can't align without a reference! (--ref)  *grunt*")
        else:
            if args.subcommand == "kitti":
                traj_tmp, ref_traj_tmp = trajectories, [
                    ref_traj for n, t in trajectories
                ]
            else:
                traj_tmp, ref_traj_tmp = [], []
                from evo.core import sync
                for name, traj in trajectories:
                    logger.debug(SEP)
                    ref_assoc, traj_assoc = sync.associate_trajectories(
                        ref_traj,
                        traj,
                        max_diff=args.t_max_diff,
                        first_name="ref",
                        snd_name=name)
                    ref_traj_tmp.append(ref_assoc)
                    traj_tmp.append((name, traj_assoc))
                    trajectories = traj_tmp
            correct_only_scale = args.correct_scale and not args.align
            trajectories_new = []
            for nt, ref_assoc in zip(trajectories, ref_traj_tmp):
                logger.debug(SEP)
                logger.debug("Aligning " + nt[0] + " to " + args.ref + "...")
                trajectories_new.append(
                    (nt[0],
                     trajectory.align_trajectory(nt[1], ref_assoc,
                                                 args.correct_scale,
                                                 correct_only_scale,
                                                 args.n_to_align)))
            trajectories = trajectories_new

    for name, traj in trajectories:
        print_traj_info(name, traj, args.verbose, args.full_check)
    if args.ref:
        print_traj_info(args.ref, ref_traj, args.verbose, args.full_check)

    if args.plot or args.save_plot or args.serialize_plot:
        from evo.tools.plot import PlotMode
        plot_mode = PlotMode.xyz if not args.plot_mode else PlotMode[
            args.plot_mode]
        import numpy as np
        from evo.tools import plot
        import matplotlib.pyplot as plt
        import matplotlib.cm as cm
        plot_collection = plot.PlotCollection("evo_traj - trajectory plot")
        fig_xyz, axarr_xyz = plt.subplots(3,
                                          sharex="col",
                                          figsize=tuple(SETTINGS.plot_figsize))
        fig_rpy, axarr_rpy = plt.subplots(3,
                                          sharex="col",
                                          figsize=tuple(SETTINGS.plot_figsize))
        fig_traj = plt.figure(figsize=tuple(SETTINGS.plot_figsize))
        if (args.align or args.correct_scale) and not args.ref:
            plt.xkcd(scale=2, randomness=4)
            fig_traj.suptitle("what if --ref?")
            fig_xyz.suptitle("what if --ref?")
        ax_traj = plot.prepare_axis(fig_traj, plot_mode)
        if args.ref:
            short_traj_name = os.path.splitext(os.path.basename(args.ref))[0]
            if SETTINGS.plot_usetex:
                short_traj_name = short_traj_name.replace("_", "\\_")
            plot.traj(ax_traj,
                      plot_mode,
                      ref_traj,
                      '--',
                      'grey',
                      short_traj_name,
                      alpha=0 if SETTINGS.plot_hideref else 1)
            plot.traj_xyz(axarr_xyz,
                          ref_traj,
                          '--',
                          'grey',
                          short_traj_name,
                          alpha=0 if SETTINGS.plot_hideref else 1)
            plot.traj_rpy(axarr_rpy,
                          ref_traj,
                          '--',
                          'grey',
                          short_traj_name,
                          alpha=0 if SETTINGS.plot_hideref else 1)
        cmap_colors = None
        if SETTINGS.plot_multi_cmap.lower() != "none":
            cmap = getattr(cm, SETTINGS.plot_multi_cmap)
            cmap_colors = iter(cmap(np.linspace(0, 1, len(trajectories))))
        for name, traj in trajectories:
            if cmap_colors is None:
                color = next(ax_traj._get_lines.prop_cycler)['color']
            else:
                color = next(cmap_colors)
            short_traj_name = os.path.splitext(os.path.basename(name))[0]
            if SETTINGS.plot_usetex:
                short_traj_name = short_traj_name.replace("_", "\\_")
            plot.traj(ax_traj, plot_mode, traj, '-', color, short_traj_name)
            if args.ref and isinstance(ref_traj, trajectory.PoseTrajectory3D):
                start_time = ref_traj.timestamps[0]
            else:
                start_time = None
            plot.traj_xyz(axarr_xyz,
                          traj,
                          '-',
                          color,
                          short_traj_name,
                          start_timestamp=start_time)
            plot.traj_rpy(axarr_rpy,
                          traj,
                          '-',
                          color,
                          short_traj_name,
                          start_timestamp=start_time)
        plt.tight_layout()
        plot_collection.add_figure("trajectories", fig_traj)
        plot_collection.add_figure("xyz_view", fig_xyz)
        plot_collection.add_figure("rpy_view", fig_rpy)
        if args.plot:
            plot_collection.show()
        if args.save_plot:
            logger.info(SEP)
            plot_collection.export(args.save_plot,
                                   confirm_overwrite=not args.no_warnings)
        if args.serialize_plot:
            logger.info(SEP)
            plot_collection.serialize(args.serialize_plot,
                                      confirm_overwrite=not args.no_warnings)

    if args.save_as_tum:
        logger.info(SEP)
        for name, traj in trajectories:
            dest = os.path.splitext(os.path.basename(name))[0] + ".tum"
            file_interface.write_tum_trajectory_file(
                dest, traj, confirm_overwrite=not args.no_warnings)
        if args.ref:
            dest = os.path.splitext(os.path.basename(args.ref))[0] + ".tum"
            file_interface.write_tum_trajectory_file(
                dest, ref_traj, confirm_overwrite=not args.no_warnings)
    if args.save_as_kitti:
        logger.info(SEP)
        for name, traj in trajectories:
            dest = os.path.splitext(os.path.basename(name))[0] + ".kitti"
            file_interface.write_kitti_poses_file(
                dest, traj, confirm_overwrite=not args.no_warnings)
        if args.ref:
            dest = os.path.splitext(os.path.basename(args.ref))[0] + ".kitti"
            file_interface.write_kitti_poses_file(
                dest, ref_traj, confirm_overwrite=not args.no_warnings)
    if args.save_as_bag:
        logger.info(SEP)
        import datetime
        import rosbag
        dest_bag_path = str(
            datetime.datetime.now().strftime('%Y-%m-%d_%H:%M:%S.%f')) + ".bag"
        logger.info("Saving trajectories to " + dest_bag_path + "...")
        bag = rosbag.Bag(dest_bag_path, 'w')
        try:
            for name, traj in trajectories:
                dest_topic = os.path.splitext(os.path.basename(name))[0]
                frame_id = traj.meta[
                    "frame_id"] if "frame_id" in traj.meta else ""
                file_interface.write_bag_trajectory(bag, traj, dest_topic,
                                                    frame_id)
            if args.ref:
                dest_topic = os.path.splitext(os.path.basename(args.ref))[0]
                frame_id = ref_traj.meta[
                    "frame_id"] if "frame_id" in ref_traj.meta else ""
                file_interface.write_bag_trajectory(bag, ref_traj, dest_topic,
                                                    frame_id)
        finally:
            bag.close()
예제 #27
0
# %%
# Convert the gt relative-pose DataFrame to a trajectory object.
traj_ref_complete = pandas_bridge.df_to_trajectory(gt_df)

# Use the backend poses as trajectory.
traj_est_unaligned = pandas_bridge.df_to_trajectory(output_poses_df)
discard_n_start_poses = 0
discard_n_end_poses = 0

# Associate the data.
traj_est = copy.deepcopy(traj_est_unaligned)
traj_ref, traj_est = sync.associate_trajectories(traj_ref_complete, traj_est)
traj_est = trajectory.align_trajectory(
    traj_est,
    traj_ref,
    correct_scale=False,
    discard_n_start_poses=int(discard_n_start_poses),
    discard_n_end_poses=int(discard_n_end_poses),
)

print("traj_ref: ", traj_ref)
print("traj_est: ", traj_est)

# %%
# plot ground truth trajectory with pose
plot_mode = plot.PlotMode.xy
fig = plt.figure()
ax = plot.prepare_axis(fig, plot_mode)
draw_coordinate_axes(ax,
                     traj_ref_complete,
                     marker_scale=2,
예제 #28
0
vanilla_traj = trajectory.PoseTrajectory3D(poses_se3=vanilla_poses,
                                           timestamps=timestamps)
vision_only_traj = trajectory.PoseTrajectory3D(poses_se3=vision_only_poses,
                                               timestamps=timestamps)

vins_mono_traj = read_tum(vins_mono_poses)

gt_traj_synced_vanilla, vanilla_traj_synced = sync.associate_trajectories(
    gt_traj, vanilla_traj, max_diff=0.01)
gt_traj_synced_vision_only, vision_only_traj_synced = sync.associate_trajectories(
    gt_traj, vision_only_traj, max_diff=0.01)
gt_traj_synced_vins_mono, vins_mono_traj_synced = sync.associate_trajectories(
    gt_traj, vins_mono_traj, max_diff=0.01)

vanilla_traj_aligned = trajectory.align_trajectory(vanilla_traj_synced,
                                                   gt_traj_synced_vanilla,
                                                   correct_scale=False,
                                                   correct_only_scale=False)
vision_only_traj_aligned = trajectory.align_trajectory(
    vision_only_traj_synced,
    gt_traj_synced_vision_only,
    correct_scale=False,
    correct_only_scale=False)
vins_mono_traj_aligned = trajectory.align_trajectory(vins_mono_traj_synced,
                                                     gt_traj_synced_vins_mono,
                                                     correct_scale=False,
                                                     correct_only_scale=False)

plotter = Plotter(os.path.join(base_dir, "KITTI_figures"))


def plot_callback(fig, ax):
예제 #29
0
from __future__ import print_function

print("loading required evo modules")
from evo.core import trajectory, sync, metrics
from evo.tools import file_interface

print("loading trajectories")
traj_ref = file_interface.read_tum_trajectory_file(
    "../../test/data/fr2_desk_groundtruth.txt")
traj_est = file_interface.read_tum_trajectory_file(
    "../../test/data/fr2_desk_ORB.txt")

print("registering and aligning trajectories")
traj_ref, traj_est = sync.associate_trajectories(traj_ref, traj_est)
traj_est = trajectory.align_trajectory(traj_est, traj_ref, correct_scale=False)

print("calculating APE")
data = (traj_ref, traj_est)
ape_metric = metrics.APE(metrics.PoseRelation.translation_part)
ape_metric.process_data(data)
ape_statistics = ape_metric.get_all_statistics()
print("mean:", ape_statistics["mean"])

print("loading plot modules")
from evo.tools import plot
import matplotlib.pyplot as plt

print("plotting")
plot_collection = plot.PlotCollection("Example")
# metric values
예제 #30
0
파일: main_traj.py 프로젝트: mgladkova/evo
def run(args):
    import os
    import sys

    import numpy as np

    import evo.core.lie_algebra as lie
    from evo.core import trajectory
    from evo.core.trajectory import PoseTrajectory3D
    from evo.tools import file_interface, log
    from evo.tools.settings import SETTINGS

    log.configure_logging(verbose=args.verbose,
                          silent=args.silent,
                          debug=args.debug,
                          local_logfile=args.logfile)
    if args.debug:
        import pprint
        logger.debug(
            "main_parser config:\n" +
            pprint.pformat({arg: getattr(args, arg)
                            for arg in vars(args)}) + "\n")
    logger.debug(SEP)

    trajectories, ref_traj = load_trajectories(args)

    if args.merge:
        if args.subcommand == "kitti":
            die("Can't merge KITTI files.")
        if len(trajectories) == 0:
            die("No trajectories to merge (excluding --ref).")
        trajectories = {
            "merged_trajectory": trajectory.merge(trajectories.values())
        }

    if args.transform_left or args.transform_right:
        tf_type = "left" if args.transform_left else "right"
        tf_path = args.transform_left \
                if args.transform_left else args.transform_right
        transform = file_interface.load_transform_json(tf_path)
        logger.debug(SEP)
        if not lie.is_se3(transform):
            logger.warning("Not a valid SE(3) transformation!")
        if args.invert_transform:
            transform = lie.se3_inverse(transform)
        logger.debug("Applying a {}-multiplicative transformation:\n{}".format(
            tf_type, transform))
        for traj in trajectories.values():
            traj.transform(transform,
                           right_mul=args.transform_right,
                           propagate=args.propagate_transform)

    if args.t_offset:
        logger.debug(SEP)
        for name, traj in trajectories.items():
            if type(traj) is trajectory.PosePath3D:
                die("{} doesn't have timestamps - can't add time offset.".
                    format(name))
            logger.info("Adding time offset to {}: {} (s)".format(
                name, args.t_offset))
            traj.timestamps += args.t_offset

    if args.n_to_align != -1 and not (args.align or args.correct_scale):
        die("--n_to_align is useless without --align or/and --correct_scale")

    if args.sync or args.align or args.correct_scale or args.align_origin:
        from evo.core import sync
        if not args.ref:
            logger.debug(SEP)
            die("Can't align or sync without a reference! (--ref)  *grunt*")
        for name, traj in trajectories.items():
            if args.subcommand == "kitti":
                ref_traj_tmp = ref_traj
            else:
                logger.debug(SEP)
                ref_traj_tmp, trajectories[name] = sync.associate_trajectories(
                    ref_traj,
                    traj,
                    max_diff=args.t_max_diff,
                    first_name="reference",
                    snd_name=name)
            if args.align or args.correct_scale:
                logger.debug(SEP)
                logger.debug("Aligning {} to reference.".format(name))
                trajectories[name] = trajectory.align_trajectory(
                    trajectories[name],
                    ref_traj_tmp,
                    correct_scale=args.correct_scale,
                    correct_only_scale=args.correct_scale and not args.align,
                    n=args.n_to_align)
            if args.align_origin:
                logger.debug(SEP)
                logger.debug("Aligning {}'s origin to reference.".format(name))
                trajectories[name] = trajectory.align_trajectory_origin(
                    trajectories[name], ref_traj_tmp)

    print_compact_name = not args.subcommand == "bag"
    for name, traj in trajectories.items():
        print_traj_info(name, traj, args.verbose, args.full_check,
                        print_compact_name)
    if args.ref:
        print_traj_info(args.ref, ref_traj, args.verbose, args.full_check,
                        print_compact_name)

    if args.plot or args.save_plot or args.serialize_plot:
        import numpy as np
        from evo.tools import plot
        import matplotlib.pyplot as plt
        import matplotlib.cm as cm

        plot_collection = plot.PlotCollection("evo_traj - trajectory plot")
        fig_xyz, axarr_xyz = plt.subplots(3,
                                          sharex="col",
                                          figsize=tuple(SETTINGS.plot_figsize))
        fig_rpy, axarr_rpy = plt.subplots(3,
                                          sharex="col",
                                          figsize=tuple(SETTINGS.plot_figsize))
        fig_traj = plt.figure(figsize=tuple(SETTINGS.plot_figsize))

        plot_mode = plot.PlotMode[args.plot_mode]
        ax_traj = plot.prepare_axis(fig_traj, plot_mode)

        if args.ref:
            short_traj_name = os.path.splitext(os.path.basename(args.ref))[0]
            if SETTINGS.plot_usetex:
                short_traj_name = short_traj_name.replace("_", "\\_")
            plot.traj(ax_traj,
                      plot_mode,
                      ref_traj,
                      style=SETTINGS.plot_reference_linestyle,
                      color=SETTINGS.plot_reference_color,
                      label=short_traj_name,
                      alpha=SETTINGS.plot_reference_alpha)
            plot.draw_coordinate_axes(ax_traj, ref_traj, plot_mode,
                                      SETTINGS.plot_axis_marker_scale)
            plot.traj_xyz(axarr_xyz,
                          ref_traj,
                          style=SETTINGS.plot_reference_linestyle,
                          color=SETTINGS.plot_reference_color,
                          label=short_traj_name,
                          alpha=SETTINGS.plot_reference_alpha)
            plot.traj_rpy(axarr_rpy,
                          ref_traj,
                          style=SETTINGS.plot_reference_linestyle,
                          color=SETTINGS.plot_reference_color,
                          label=short_traj_name,
                          alpha=SETTINGS.plot_reference_alpha)

        if args.ros_map_yaml:
            plot.ros_map(ax_traj, args.ros_map_yaml, plot_mode)

        cmap_colors = None
        if SETTINGS.plot_multi_cmap.lower() != "none":
            cmap = getattr(cm, SETTINGS.plot_multi_cmap)
            cmap_colors = iter(cmap(np.linspace(0, 1, len(trajectories))))

        for name, traj in trajectories.items():
            if cmap_colors is None:
                color = next(ax_traj._get_lines.prop_cycler)['color']
            else:
                color = next(cmap_colors)
            if print_compact_name:
                short_traj_name = os.path.splitext(os.path.basename(name))[0]
            else:
                short_traj_name = name
            if SETTINGS.plot_usetex:
                short_traj_name = short_traj_name.replace("_", "\\_")
            plot.traj(ax_traj,
                      plot_mode,
                      traj,
                      SETTINGS.plot_trajectory_linestyle,
                      color,
                      short_traj_name,
                      alpha=SETTINGS.plot_trajectory_alpha)
            plot.draw_coordinate_axes(ax_traj, traj, plot_mode,
                                      SETTINGS.plot_axis_marker_scale)
            if args.ref and isinstance(ref_traj, trajectory.PoseTrajectory3D):
                start_time = ref_traj.timestamps[0]
            else:
                start_time = None
            plot.traj_xyz(axarr_xyz,
                          traj,
                          SETTINGS.plot_trajectory_linestyle,
                          color,
                          short_traj_name,
                          alpha=SETTINGS.plot_trajectory_alpha,
                          start_timestamp=start_time)
            plot.traj_rpy(axarr_rpy,
                          traj,
                          SETTINGS.plot_trajectory_linestyle,
                          color,
                          short_traj_name,
                          alpha=SETTINGS.plot_trajectory_alpha,
                          start_timestamp=start_time)
            if not SETTINGS.plot_usetex:
                fig_rpy.text(0.,
                             0.005,
                             "euler_angle_sequence: {}".format(
                                 SETTINGS.euler_angle_sequence),
                             fontsize=6)

        plot_collection.add_figure("trajectories", fig_traj)
        plot_collection.add_figure("xyz_view", fig_xyz)
        plot_collection.add_figure("rpy_view", fig_rpy)
        if args.plot:
            plot_collection.show()
        if args.save_plot:
            logger.info(SEP)
            plot_collection.export(args.save_plot,
                                   confirm_overwrite=not args.no_warnings)
        if args.serialize_plot:
            logger.info(SEP)
            plot_collection.serialize(args.serialize_plot,
                                      confirm_overwrite=not args.no_warnings)

    if args.save_as_tum:
        logger.info(SEP)
        for name, traj in trajectories.items():
            dest = os.path.splitext(os.path.basename(name))[0] + ".tum"
            file_interface.write_tum_trajectory_file(
                dest, traj, confirm_overwrite=not args.no_warnings)
        if args.ref:
            dest = os.path.splitext(os.path.basename(args.ref))[0] + ".tum"
            file_interface.write_tum_trajectory_file(
                dest, ref_traj, confirm_overwrite=not args.no_warnings)
    if args.save_as_kitti:
        logger.info(SEP)
        for name, traj in trajectories.items():
            dest = os.path.splitext(os.path.basename(name))[0] + ".kitti"
            file_interface.write_kitti_poses_file(
                dest, traj, confirm_overwrite=not args.no_warnings)
        if args.ref:
            dest = os.path.splitext(os.path.basename(args.ref))[0] + ".kitti"
            file_interface.write_kitti_poses_file(
                dest, ref_traj, confirm_overwrite=not args.no_warnings)
    if args.save_as_bag:
        import datetime
        import rosbag
        dest_bag_path = str(
            datetime.datetime.now().strftime("%Y-%m-%d-%H-%M-%S")) + ".bag"
        logger.info(SEP)
        logger.info("Saving trajectories to " + dest_bag_path + "...")
        bag = rosbag.Bag(dest_bag_path, 'w')
        try:
            for name, traj in trajectories.items():
                dest_topic = os.path.splitext(os.path.basename(name))[0]
                frame_id = traj.meta[
                    "frame_id"] if "frame_id" in traj.meta else ""
                file_interface.write_bag_trajectory(bag, traj, dest_topic,
                                                    frame_id)
            if args.ref:
                dest_topic = os.path.splitext(os.path.basename(args.ref))[0]
                frame_id = ref_traj.meta[
                    "frame_id"] if "frame_id" in ref_traj.meta else ""
                file_interface.write_bag_trajectory(bag, ref_traj, dest_topic,
                                                    frame_id)
        finally:
            bag.close()
예제 #31
0
def associate_segments(traj, tracks):
    """Associate segments of an object trajectory as given by a DATMO system
    with the object's reference trajectory

    :traj: Reference trajectory
    :tracks: All the tracks that got produced by the DATMO system
    :localization: The trajectory of the self-localization
    :returns: segments: The tracks that match to the reference trajectory
    :returns: traj_ref: The part of the reference trajectory that matches with
    tracks

    """
    matches = []
    for tr in tracks:  # Find the best matching tracks to the object trajectory

        traj_ref, traj_est = sync.associate_trajectories(traj,
                                                         tr,
                                                         max_diff=0.01)
        traj_est, rot, tra, _ = trajectory.align_trajectory(
            traj_est, traj_ref, correct_scale=False, return_parameters=True)

        # print("calculating APE for track of length", len(tr.timestamps))
        data = (traj_ref, traj_est)
        ape_metric = metrics.APE(metrics.PoseRelation.translation_part)
        ape_metric.process_data(data)
        ape_statistics = ape_metric.get_all_statistics()

        tra_dif = (tra - loc_tra)
        # print(tra)
        abs_tra_dif = abs((tra - loc_tra)[0]) + abs((tra - loc_tra)[1])
        translation = abs(tra[0]) + abs(tra[1])
        rot_dif = (rot - loc_rot)
        abs_rot_dif = 0
        for i in range(0, len(rot_dif)):            abs_rot_dif += abs(rot_dif[i][0])+ abs(rot_dif[i][1]) +\
abs(rot_dif[i][2])
        # print(abs_tra_dif,abs_rot_dif)
        mismatch = abs_tra_dif + abs_rot_dif
        tuple = [traj_est, mismatch, traj_est.get_infos()['t_start (s)']]
        matches.append(tuple)

    matches.sort(key=lambda x: x[2])

    segments = []  #The parts of the trajectory are added to this list
    for m in matches:
        # print(m[1])
        if m[1] < 0.1:  # if the mismatch is smaller than 1
            # print(m[0].get_statistics()['v_avg (m/s)'])
            segments.append(m[0])
            # print(m[0].get_infos()['t_start (s)'],m[0].get_infos()["path length (m)"])
            # print(m[0].get_statistics()['v_avg (m/s)'])
    if len(segments) == 0:
        print("No matching segments")

    whole = trajectory.merge(segments)

    traj_ref, traj_est = sync.associate_trajectories(traj,
                                                     whole,
                                                     max_diff=0.01)
    traj_est, rot, tra, _ = trajectory.align_trajectory(traj_est,
                                                        traj_ref,
                                                        correct_scale=False,
                                                        return_parameters=True)
    # print(traj_est.get_infos())

    return segments, traj_ref, translation