EVO评估数据导出在origin中绘制

一、EVO数据导出

1.1、使用EVO保存图片为pdf,保存数据为zip

bash 复制代码
evo_ape tum trajectory.txt pose.txt -p -v  --align_origin  --plot_mode=xy --save_results evo_results.zip --save_plot evo_results.pdf

evo_ape tum trajectory.txt pose.txt -p -v --align_origin --plot_mode=xy --save_results evo_results.zip --save_plot evo_results.pdf

注意此处

--save_results evo_results.zip 其中--save_results后加保存zip名称

--save_plot evo_results.pdf 其中--save_plot后加保存pdf名称

解压后发现格式都是npz的,需要转换为csv格式

  1. error_array.npz

内容:位姿误差的原始数值数组(对应你用evo_ape计算的绝对位姿误差,或evo_rpe的相对位姿误差)。

含义:存储了每一个数据点的误差值(例如evo_ape的平移误差 / 旋转误差),是后续绘制误差曲线的核心数据。

  1. timestamps.npz

内容:每个误差数据对应的时间戳数组。

含义:与error_array.npz中的误差值一一对应,记录了每个误差点对应的「轨迹时间戳」,用于绘制 "误差随时间变化" 的曲线。

  1. seconds_from_start.npz

内容:每个数据点相对于轨迹起始时刻的时间差数组(单位:秒)。

含义:是时间戳的 "相对简化版"(例如轨迹第 1 秒、第 2 秒对应的误差),部分场景下比原始时间戳更直观。

  1. stats.json

内容:误差的统计指标信息(以 JSON 格式存储)。

含义:包含误差的最大值、最小值、均值、标准差、RMSE(均方根误差)等关键统计量,是评估 SLAM 算法精度的核心定量指标。

  1. info.json

内容:EVO 评估的元信息(以 JSON 格式存储)。

含义:记录了本次评估的「配置参数」,例如:

你用的 EVO 命令(evo_ape)、评估的轨迹文件(trajectory.txt/pose.txt);

对齐方式(--align_origin)、绘图模式(--plot_mode=xy);

EVO 版本、运行时间等环境信息。

1.2将zip压缩包的内容npz格式转为csv

创建py脚本执行批量转换

python npz_to_csv.py

python 复制代码
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import numpy as np
import csv
import os
import zipfile

# ========== 适配当前目录的路径配置 ==========
npz_zip_path = "./evo_results.zip"
extract_dir = "./evo_results"

def npz_single_to_csv(npz_file_path, csv_file_path):
    """
    单个npz文件转换为csv文件的工具函数
    :param npz_file_path: 输入npz文件路径
    :param csv_file_path: 输出csv文件路径
    """
    try:
        # 1. 加载npz数据(适配旧版EVO的ndarray格式)
        npz_data = np.load(npz_file_path)
    except Exception as e:
        print("错误:加载npz文件 {} 失败,异常信息:{}".format(npz_file_path, str(e)))
        return False

    # 2. 数据格式优化(确保为一维数组,适配CSV写入)
    if npz_data.ndim > 1:
        npz_data = npz_data.flatten()
        print("提示:{} 为多维数组,已展平为一维".format(os.path.basename(npz_file_path)))

    # 3. 写入CSV文件
    try:
        with open(csv_file_path, 'w') as csv_file:
            csv_writer = csv.writer(csv_file)
            # 写入列头(根据npz文件名自动生成简易列头,适配EVO数据)
            npz_file_name = os.path.splitext(os.path.basename(npz_file_path))[0]
            csv_writer.writerow(["{}_index".format(npz_file_name), "{}_value".format(npz_file_name)])
            
            # 逐行写入数据(索引+数值,适配所有一维npz数据)
            for i, value in enumerate(npz_data):
                csv_writer.writerow([i, value])
        
        print("成功:{} 已转换为 {},数据长度:{}".format(npz_file_path, csv_file_path, len(npz_data)))
        return True
    except Exception as e:
        print("错误:写入CSV文件 {} 失败,异常信息:{}".format(csv_file_path, str(e)))
        return False

def batch_convert_npz_to_csv():
    """
    批量转换压缩包中所有npz文件为csv文件的主函数
    """
    # 步骤1:解压压缩包(若未解压)
    if os.path.exists(npz_zip_path) and npz_zip_path.endswith(".zip"):
        # 检查是否已解压(判断提取目录是否存在,且包含npz文件)
        npz_files_exist = False
        if os.path.exists(extract_dir):
            for file in os.listdir(extract_dir):
                if file.endswith(".npz"):
                    npz_files_exist = True
                    break
        
        if not npz_files_exist:
            # 不存在有效npz文件,重新解压
            with zipfile.ZipFile(npz_zip_path, 'r') as zip_ref:
                zip_ref.extractall(extract_dir)
            print("已解压 {} 到:{}".format(npz_zip_path, extract_dir))
        else:
            print("压缩包已解压且包含npz文件,跳过解压步骤")
    else:
        print("错误:未找到压缩包文件 {},请检查路径".format(npz_zip_path))
        return

    # 步骤2:遍历提取目录,收集所有npz文件
    npz_file_list = []
    for root, dirs, files in os.walk(extract_dir):
        for file in files:
            if file.endswith(".npz"):
                npz_file_path = os.path.join(root, file)
                npz_file_list.append(npz_file_path)
    
    if not npz_file_list:
        print("错误:在 {} 目录下未找到任何npz文件".format(extract_dir))
        return
    print("\n共找到 {} 个npz文件,开始批量转换...\n".format(len(npz_file_list)))

    # 步骤3:批量转换每个npz文件为csv文件
    success_count = 0
    for npz_file_path in npz_file_list:
        # 构造csv文件路径(与npz文件同名,后缀改为.csv)
        csv_file_path = os.path.splitext(npz_file_path)[0] + ".csv"
        # 调用单个转换函数
        if npz_single_to_csv(npz_file_path, csv_file_path):
            success_count += 1

    # 步骤4:输出批量转换总结
    print("\n批量转换完成!共处理 {} 个npz文件,成功转换 {} 个,失败 {} 个".format(len(npz_file_list), success_count, len(npz_file_list)-success_count))
    print("所有CSV文件已保存至 {} 目录下(与对应npz文件同名)".format(extract_dir))

if __name__ == '__main__':
    batch_convert_npz_to_csv()

得到转换后文件

二、创建虚拟环境使用EVO导出csv格式(放弃,ubuntu18.04未成功,依赖要改的太多)

2.1安装虚拟环境管理工具 virtualenv

bash 复制代码
# 1. 若系统无 pip3,先安装 python3-pip(Ubuntu 18.04 自带 Python 3.6,不影响 ROS)
sudo apt update && sudo apt install -y python3-pip

# 2. 用 pip3 安装 virtualenv(全局安装,仅用于创建虚拟环境,无版本冲突风险)
sudo pip3 install virtualenv

# 3. 验证安装成功
virtualenv --version

2.2创建干净的 Python 3.8 虚拟环境

bash 复制代码
# 1. 创建虚拟环境存放目录(若已存在,跳过此步)
mkdir -p ~/python_envs
cd ~/python_envs

# 2. 验证 Python 3.8 路径正确性(确保输出 /usr/bin/python3.8)
which python3.8

# 3. 创建 Python 3.8 虚拟环境,命名为 `evo_highver`(清晰标识高版本 EVO)
virtualenv -p /usr/bin/python3.8 evo_highver

2.3激活虚拟环境

bash 复制代码
# 激活虚拟环境(终端前缀会出现 (evo_highver) 标识,代表进入隔离环境)
source ~/python_envs/evo_highver/bin/activate

2.4在虚拟环境中安装高版本 EVO(支持 --save_as_csv

bash 复制代码
# 1. 升级虚拟环境内的 pip 和 setuptools(避免依赖解析错误)
pip install --upgrade pip setuptools==65.5.0

# 2. 安装 EVO 核心依赖(预编译包,快速无报错,适配 Python 3.8)
pip install numpy==1.24.4 matplotlib==3.6.0 scipy==1.10.1 pandas==2.0.3 seaborn==0.12.2 natsort==8.4.0 pyyaml==6.0.1

# 3. 安装 EVO 1.16.0(核心步骤,支持 --save_as_csv)
pip install evo==1.16.0

# 4. 验证 EVO 安装成功,且支持目标参数
echo "===== 验证 EVO 版本 ====="
evo pkg --version

echo -e "\n===== 验证 --save_as_csv 参数 ====="
evo export --help | grep "save_as_csv"

2.5在虚拟环境中执行轨迹导出(核心需求落地,避免 ROS 干扰)

bash 复制代码
# 1. 切换到轨迹文件所在目录(替换为你的实际路径,确保 trajectory.txt 和 pose.txt 存在)
cd ~/map-bag-date/bag/da_lun_wen/liwo_mapping/01/pose_half

# 2. 执行完整的轨迹导出命令(原点对齐 + 导出 CSV 到当前目录,无需可视化可去掉 -p)
evo traj tum trajectory.txt pose.txt -p -v --align_origin --ref trajectory.txt | evo export --save_as_csv --output_dir ./

2.6出虚拟环境,恢复 ROS 环境(零残留,无干扰)

bash 复制代码
# 退出虚拟环境(终端前缀 (evo_highver) 消失,恢复原状)
deactivate

2.7后续复用高版本 EVO(无需重复安装,高效便捷)

bash 复制代码
# 1. 激活虚拟环境
source ~/python_envs/evo_highver/bin/activate

# 2. 切换到轨迹目录,执行导出命令(直接复用,无需修改)
cd ~/map-bag-date/bag/da_lun_wen/liwo_mapping/01/pose_half
evo traj tum trajectory.txt pose.txt -v --align_origin --ref trajectory.txt | evo export --save_as_csv --output_dir ./

# 3. 退出虚拟环境
deactivate

三、ubuntu18.04+py2.7环境下安装EVO

3.1、参考链接

https://blog.csdn.net/weixin_68647501/article/details/128858007?fromshare=blogdetail&sharetype=blogdetail&sharerId=128858007&sharerefer=PC&sharesource=2201_76065173&sharefrom=from_link

bash 复制代码
git clone https://github.com/MichaelGrupp/evo.git
#下载git包
cd evo
git checkout v1.12.0
#检查
sudo pip install  -i https://pypi.tuna.tsinghua.edu.cn/simple --editable . --upgrade --no-binary evo 
#解决下载慢的问题(镜像)(我这里找不到命令,所以前面加了sudo)

evo pkg --version查看安装版本

四、导出变换后的轨迹

4.1、使用--save_as_tum导出变换后的数据,注意不能加输出名称,默认输出当前位置同名

evo_traj tum pose.txt --ref trajectory.txt -as -p --save_as_tum

变化前目录内容

使用evo_traj tum pose.txt --ref trajectory.txt -as -p --save_as_tum图

轨迹保存路径

4.2变化前后pose轨迹对比

4.3变化前后地面真值(因为以它为参考,故而无变化)

五、导出数据整理

5.1导出ape数据--------ao对齐原点

evo_ape tum trajectory.txt pose.txt -v --align_origin --plot_mode=xy -p -r trans_part --save_plot ao.pdf --save_results ao.zip

5.2导出ape数据-----as全局对齐

evo_ape tum trajectory.txt pose.txt -v -as --plot_mode=xy -p -r trans_part --save_plot as.pdf --save_results as.zip

5.3导出traj数据------ao对齐

evo_traj tum pose.txt --ref trajectory.txt -v --save_table ao_traj.csv --align_origin --plot_mode=xy -p --save_plot ao_traj.pdf --save_as_tum

5.4导出traj数据------as对齐

evo_traj tum pose.txt --ref trajectory.txt -v --save_table as_traj.csv -as --plot_mode=xy -p --save_plot as_traj.pdf --save_as_tum

5.5修改压缩包内容格式npz_to_csv.py

四、数据导入origin

4.1关联origin与matlab

使用origin的控制台连接matlab:必须是同一台计算机运行origin与matlab;必须先打开origin

在matlab控制台输入matlab命令,输入desktop打开matlab的工作区

在打开的matlab中编写一个.m文件用于读取csv文件格式到工作区

Matlab 复制代码
% MATLAB 文件读取工具 - 小白友好版
clear; clc; % 清空工作区和命令窗口,保持干净

% !!!你只需要修改这里!!!指定你的文件路径和名称
% filename = 'E:\00我的纵向\05大论文\02试验数据\00建图仿真\01LIWO一圈第一次数据\complete_line\ao_tf\ao_ape\error_array.csv'; % 例如 'C:/Data/my_data.csv'
filename = 'E:\00我的纵向\05大论文\02试验数据\00建图仿真\01LIWO一圈第一次数据\complete_line\ao_tf\ao_traj_trajectory.csv';


try % 尝试读取文件
    fprintf('正在尝试读取文件: %s\n', filename);
    
    % 方法1: 优先使用 readtable,适用于大多数带行列结构的CSV/TXT
    data = readtable(filename);
    fprintf('✓ 使用 readtable 读取成功!数据是一个 %dx%d 的表格。\n', size(data,1), size(data,2));
    
    % 显示前几行预览
    disp('数据预览:');
    head(data);
    
    % 方法2: 如果readtable失败,尝试更通用的importdata
    % 这个函数会把数据放到一个结构体里,有时更能容错
    % data_struct = importdata(filename);
    % fprintf('✓ 使用 importdata 读取成功!\n');
    % disp('导入的数据结构如下:');
    % disp(data_struct);
    
catch ME % 如果读取失败,会在这里给出错误提示
    fprintf('读取文件时出错:%s\n', ME.message);
    fprintf('请检查:\n');
    fprintf('  1. 文件路径和名称是否正确。\n');
    fprintf('  2. 文件是否被其他程序打开。\n');
    fprintf('  3. 文件格式是否完整。\n');
    
    % 建议使用图形化界面导入
    fprintf('\n建议尝试使用图形化导入界面(uiimport)...\n');
    uiimport(filename);
end

点击导入,选中需要的工作区数据

发现此处matlab解析成table无法以工作表导入,故而先直接手动复制,或则txt导入origin

4.2、导入数据绘图

导入多个txt或则csv格式文件并绘图

与ape绘图一致

五、ATE与APE

SLAM中的位姿与轨迹评价指标:APE、RPE、ATE、RTE

APE绝对位姿误差(Absolute Pose Error,APE);同一时刻下计算,EVO可选平移\旋转\以及都考虑

ATE绝对轨迹误差(Absolute Trajectory Error, ATE);需要先轨迹对齐

APE是ATE的基础,位姿是轨迹的基础。绝对轨迹误差(ATE):将对齐后的轨迹直接与真值比较,求取每个状态的RMSE作为整段轨迹总误差。其计算步骤主要包含两个:(1)轨迹对齐 (2)在对齐轨迹与真值之间计算RMSE。

六、建图精度评估

https://visionary.blog.csdn.net/article/details/115054278?fromshare=blogdetail&sharetype=blogdetail&sharerId=115054278&sharerefer=PC&sharesource=2201_76065173&sharefrom=from_link

相关推荐
Clarence Liu2 小时前
机器学习(5) 梯度下降
人工智能·机器学习
kisshuan123962 小时前
电信杆塔类型识别与分类_fovea_r101_fpn_4xb4-2x_coco模型详解_模型训练与验证_通俗易懂!入门必看系列!
人工智能·目标跟踪·分类
子午2 小时前
【2026原创】动物识别系统~Python+深度学习+人工智能+模型训练+图像识别
人工智能·python·深度学习
o_insist2 小时前
LangChain1.0 实现 PDF 文档向量检索全流程
人工智能·python·langchain
OpenMiniServer2 小时前
AI + GitLab + VSCode:下一代开发工作流的革命性集成
人工智能·vscode·gitlab
脑洞AI食验员2 小时前
智能体来了:用异常与文件处理守住代码底线
人工智能·python
摘星观月2 小时前
【三维重建2】TCPFormer以及NeRF相关SOTA方法
人工智能·深度学习
shangjian0072 小时前
AI大模型-机器学习-分类
人工智能·机器学习·分类
Tiny_React2 小时前
使用 Claude Code Skills 模拟的视频生成流程
人工智能·音视频开发·vibecoding