2023-09-05 15:54:19 +03:00
|
|
|
|
from pathlib import Path
|
|
|
|
|
|
|
|
|
|
|
|
import numpy
|
|
|
|
|
|
from matplotlib import pyplot
|
2023-09-14 17:41:53 +03:00
|
|
|
|
from matplotlib.figure import figaspect, SubplotParams
|
|
|
|
|
|
from mpl_toolkits.mplot3d import Axes3D
|
2023-09-05 15:54:19 +03:00
|
|
|
|
|
2023-09-11 16:26:22 +03:00
|
|
|
|
from transformations import calculate_rotation_matrix, centroid, convert_rotation_matrix_to_angles
|
2023-09-05 15:54:19 +03:00
|
|
|
|
|
|
|
|
|
|
expected_points_file_path = Path('expected_points.txt')
|
|
|
|
|
|
actual_points_file_path = Path('actual_points.txt')
|
|
|
|
|
|
|
2023-09-14 17:41:53 +03:00
|
|
|
|
plot_3d: Axes3D = pyplot.figure(subplotpars=SubplotParams(0, 0, 1, 1, 0, 0),
|
|
|
|
|
|
figsize=(10, 8)).add_subplot(projection='3d')
|
2023-09-05 15:54:19 +03:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def read_points_from_file(points_file_path: Path) -> numpy.ndarray:
|
2023-09-14 17:41:53 +03:00
|
|
|
|
"""
|
|
|
|
|
|
Чтение пути из файла
|
|
|
|
|
|
|
|
|
|
|
|
:param points_file_path: путь к файлу
|
|
|
|
|
|
:return: Путь, вычитанный из файла
|
|
|
|
|
|
|
|
|
|
|
|
"""
|
2023-09-05 15:54:19 +03:00
|
|
|
|
with points_file_path.open('r') as points_file:
|
|
|
|
|
|
return numpy.array([[float(coordinate) for coordinate in point_line.strip().split(' ')]
|
|
|
|
|
|
for point_line in points_file])
|
|
|
|
|
|
|
|
|
|
|
|
|
2023-09-14 17:41:53 +03:00
|
|
|
|
def rsmd(first_path: numpy.ndarray, second_path: numpy.ndarray) -> float:
|
|
|
|
|
|
"""
|
|
|
|
|
|
Расчёт среднеквадратичное отклонение между путями
|
|
|
|
|
|
|
|
|
|
|
|
:param first_path: первый путь
|
|
|
|
|
|
:param second_path: второй путь
|
|
|
|
|
|
:return: СКО
|
|
|
|
|
|
|
|
|
|
|
|
"""
|
|
|
|
|
|
diff = first_path - second_path
|
|
|
|
|
|
return numpy.sqrt((diff * diff).sum() / first_path.shape[0])
|
|
|
|
|
|
|
|
|
|
|
|
|
2023-09-05 15:54:19 +03:00
|
|
|
|
if __name__ == '__main__':
|
|
|
|
|
|
expected_points = read_points_from_file(expected_points_file_path)
|
|
|
|
|
|
actual_points = read_points_from_file(actual_points_file_path)
|
|
|
|
|
|
|
2023-09-11 16:26:22 +03:00
|
|
|
|
plot_3d.plot(expected_points[:, 0], expected_points[:, 1], expected_points[:, 2],
|
2023-09-14 17:41:53 +03:00
|
|
|
|
's-k', markersize=12, linewidth=3,
|
|
|
|
|
|
label='Expected Points')
|
2023-09-11 16:26:22 +03:00
|
|
|
|
plot_3d.plot(actual_points[:, 0], actual_points[:, 1], actual_points[:, 2],
|
2023-09-14 17:41:53 +03:00
|
|
|
|
's-g', markersize=12, linewidth=3,
|
|
|
|
|
|
label='Actual Points')
|
|
|
|
|
|
|
|
|
|
|
|
for calculation_points_number in range(len(actual_points), 1, -1):
|
|
|
|
|
|
print(f"{15 * '='} Calc on {calculation_points_number:2} points {15 * '='}")
|
|
|
|
|
|
rotation_matrix = calculate_rotation_matrix(actual_points,
|
|
|
|
|
|
expected_points,
|
|
|
|
|
|
calculation_points_number=calculation_points_number)
|
|
|
|
|
|
angles = convert_rotation_matrix_to_angles(rotation_matrix)
|
2023-09-11 16:26:22 +03:00
|
|
|
|
|
2023-09-14 17:41:53 +03:00
|
|
|
|
actual_points_rotated = numpy.dot(actual_points, rotation_matrix)
|
2023-09-05 15:54:19 +03:00
|
|
|
|
|
2023-09-14 17:41:53 +03:00
|
|
|
|
actual_points_for_offset = actual_points_rotated[:calculation_points_number]
|
|
|
|
|
|
expected_points_for_offset = expected_points[:calculation_points_number]
|
2023-09-05 15:54:19 +03:00
|
|
|
|
|
2023-09-14 17:41:53 +03:00
|
|
|
|
offset = centroid(actual_points_for_offset) - centroid(expected_points_for_offset)
|
|
|
|
|
|
actual_points_converted = actual_points_rotated - offset
|
2023-09-07 14:19:18 +03:00
|
|
|
|
|
2023-09-14 17:41:53 +03:00
|
|
|
|
print(f" {angles = }")
|
|
|
|
|
|
print(f" offset = {tuple(offset)}")
|
|
|
|
|
|
print(f" error = {rsmd(expected_points, actual_points_converted)}")
|
2023-09-11 16:26:22 +03:00
|
|
|
|
|
2023-09-14 17:41:53 +03:00
|
|
|
|
plot_3d.plot(actual_points_converted[:, 0], actual_points_converted[:, 1], actual_points_converted[:, 2],
|
|
|
|
|
|
'o-', markersize=9, linewidth=3,
|
|
|
|
|
|
label=f'Transformed actual points (on {calculation_points_number} points)')
|
2023-09-11 16:26:22 +03:00
|
|
|
|
|
2023-09-05 15:54:19 +03:00
|
|
|
|
plot_3d.grid(True)
|
|
|
|
|
|
plot_3d.tick_params(labelsize=15)
|
|
|
|
|
|
|
2023-09-11 16:26:22 +03:00
|
|
|
|
pyplot.legend()
|
2023-09-05 15:54:19 +03:00
|
|
|
|
pyplot.show()
|