|
| 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