Skip to content

Commit 137b660

Browse files
committed
[Feat] provide the evaluation method for NTU-VIRAL.
1 parent 998eada commit 137b660

23 files changed

+87870
-1
lines changed

.gitignore

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +0,0 @@
1-
Log/*

Log/result/.gitkeep

Whitespace-only changes.

Log/result/ntu_viral/README.md

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
## Usage Instructions
2+
The files in this folder follow the naming convention: `xxx_xx_*`
3+
4+
- `xxx`: Scene name (e.g., eee, nya, sbs).
5+
- `xx`: Sequence number (e.g., 01, 02, 03) for the same scene.
6+
- `xxx_xx_prism.txt`: Estimated poses from FAST-LIVO2 converted to the PRISM coordinate system.
7+
- `xxx_xx_gt.txt`: Ground truth trajectories converted to the TUM format.
8+
9+
To compute RMSE between ground truth and estimated trajectories, run:
10+
```bash
11+
evo_ape tum eee_01_gt.txt eee_01_prism.txt -a --plot --plot_mode xyz
12+
```
13+
Results below:
14+
| Scene | Sequence | RMSE (cm) |
15+
|--------|----------|-----------|
16+
| eee | 01 | 2.71 |
17+
| eee | 02 | 2.11 |
18+
| eee | 03 | 2.61 |
19+
| nya | 01 | 3.56 |
20+
| nya | 02 | 3.39 |
21+
| nya | 03 | 3.52 |
22+
| sbs | 01 | 2.34 |
23+
| sbs | 02 | 2.83 |
24+
| sbs | 03 | 3.11 |
25+
26+
**Note:** The provided files are results (*_prism.txt, *_gt.txt) from my runs. To compare your own FAST-LIVO2 pose outputs with ground truth, you must first run `evaluate_viral.py` to:
27+
- Convert the official [leica_pose.csv](https://github.com/ntu-aris/viral_eval) file to TUM format.
28+
- Transform SLAM trajectories from the **IMU frame** to the **PRISM coordinate system**.

Log/result/ntu_viral/eee_01_gt.txt

Lines changed: 6616 additions & 0 deletions
Large diffs are not rendered by default.

Log/result/ntu_viral/eee_01_prism.txt

Lines changed: 3982 additions & 0 deletions
Large diffs are not rendered by default.

Log/result/ntu_viral/eee_02_gt.txt

Lines changed: 5512 additions & 0 deletions
Large diffs are not rendered by default.

Log/result/ntu_viral/eee_02_prism.txt

Lines changed: 3203 additions & 0 deletions
Large diffs are not rendered by default.

Log/result/ntu_viral/eee_03_gt.txt

Lines changed: 2990 additions & 0 deletions
Large diffs are not rendered by default.

Log/result/ntu_viral/eee_03_prism.txt

Lines changed: 1805 additions & 0 deletions
Large diffs are not rendered by default.
Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
import os
2+
import numpy as np
3+
import pandas as pd
4+
from scipy.spatial.transform import Rotation
5+
6+
def convert_slam_to_prism(slam_tum_file, output_file):
7+
"""
8+
Convert SLAM trajectory in TUM format to prism coordinate system
9+
:param slam_tum_file: SLAM estimated trajectory file (TUM format, quaternion order x y z w)
10+
:param output_file: Output file path
11+
"""
12+
try:
13+
# Check file existence
14+
if not os.path.exists(slam_tum_file):
15+
raise FileNotFoundError(f"SLAM file not found: {slam_tum_file}")
16+
17+
# Read SLAM trajectory data
18+
slam_data = pd.read_csv(slam_tum_file, sep=' ', header=None)
19+
timestamps = slam_data.iloc[:, 0].values
20+
positions = slam_data.iloc[:, 1:4].values
21+
quaternions = slam_data.iloc[:, 4:8].values # Quaternion order: x y z w
22+
23+
# Static transformation vector from body to prism coordinates
24+
trans_B2prism = np.array([-0.293656, -0.012288, -0.273095])
25+
26+
# Convert positions to prism coordinate system
27+
positions_prism = positions + quat_rotate_vector(quaternions, trans_B2prism)
28+
29+
# Save in TUM format
30+
output_data = np.column_stack((timestamps, positions_prism, quaternions))
31+
np.savetxt(output_file, output_data, fmt='%.6f', delimiter=' ')
32+
print(f"Successfully processed SLAM data: {output_file}")
33+
34+
except Exception as e:
35+
print(f"Error processing SLAM data: {str(e)}")
36+
raise
37+
38+
def convert_leica_to_tum(leica_file, output_file):
39+
"""
40+
Convert leica_pose.csv to TUM format
41+
:param leica_file: leica_pose.csv file path
42+
:param output_file: Output file path
43+
"""
44+
try:
45+
# Check file existence
46+
if not os.path.exists(leica_file):
47+
raise FileNotFoundError(f"Leica file not found: {leica_file}")
48+
49+
# Read Leica data
50+
leica_data = pd.read_csv(leica_file, skiprows=1, header=None).values
51+
timestamps = leica_data[:, 0] / 1e9 # Convert nanoseconds to seconds
52+
positions = leica_data[:, 3:6]
53+
quaternions = np.zeros((len(positions), 4)) # Assume identity rotation
54+
quaternions[:, 3] = 1 # w-component of quaternion
55+
56+
# Save in TUM format
57+
output_data = np.column_stack((timestamps, positions, quaternions))
58+
np.savetxt(output_file, output_data, fmt='%.6f', delimiter=' ')
59+
print(f"Successfully processed Leica data: {output_file}")
60+
61+
except Exception as e:
62+
print(f"Error processing Leica data: {str(e)}")
63+
raise
64+
65+
def quat_rotate_vector(quat, vec):
66+
"""
67+
Rotate vector using quaternion(s) (quaternion order: x y z w)
68+
:param quat: Quaternion array (N x 4, order [x, y, z, w])
69+
:param vec: 3D vector to rotate
70+
:return: Rotated vectors (N x 3)
71+
"""
72+
# Create rotation object using x y z w order
73+
rot = Rotation.from_quat(quat[:, :4])
74+
return rot.apply(vec)
75+
76+
if __name__ == '__main__':
77+
# File paths
78+
input_files = {
79+
'slam': 'eee_01.txt',
80+
'leica': 'leica_pose.csv'
81+
}
82+
83+
output_files = {
84+
'slam': 'eee_01_prism.txt',
85+
'leica': 'eee_01_gt.txt'
86+
}
87+
88+
# Process SLAM data
89+
try:
90+
convert_slam_to_prism(input_files['slam'], output_files['slam'])
91+
except:
92+
print("Skipping SLAM processing")
93+
94+
# Process Leica data
95+
try:
96+
convert_leica_to_tum(input_files['leica'], output_files['leica'])
97+
except:
98+
print("Skipping Leica processing")

0 commit comments

Comments
 (0)