/
klischa
/
AstraScanner2
Обзор
Документация
Войти
/
klischa
/
AstraScanner2
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
CI/CD
Аналитика
Безопасность
master
tests/test_neural_tracker.cpp
305 строк
10 KB
k k
fix: NeuralTracker tests loaded wrong ONNX Runtime DLL
14 июл 2026, 19:51
14 июл 2026, 19:51
5cfaf7a
Код
Авторство
О чём код?
#include <gtest/gtest.h> #include <QCoreApplication> #include <QTemporaryDir> #include <QDir> #include <QFileInfo> #include <pcl/point_cloud.h> #include <pcl/point_types.h> #include <Eigen/Dense> #include "test_helpers.h" #include "../src/tracking/NeuralTracker.h" class NeuralTrackerTest : public ::testing::Test { protected: void SetUp() override { if (!QCoreApplication::instance()) { static int argc = 1; static char arg0[] = "test_neural_tracker"; static char* argv[] = { arg0 }; new QCoreApplication(argc, argv); } tempDir.reset(new QTemporaryDir()); ASSERT_TRUE(tempDir->isValid()); // Путь к модели (должна существовать в репозитории). #ifdef ASTRA_TEST_MODEL_PATH modelPath = QString::fromUtf8(ASTRA_TEST_MODEL_PATH); #else modelPath = QDir(QCoreApplication::applicationDirPath()).filePath("../models/pose_regressor.onnx"); #endif modelPath = QFileInfo(modelPath).absoluteFilePath(); if (!QFileInfo::exists(modelPath)) { qWarning() << "[NeuralTrackerTest] Model file not found at:" << modelPath; } // Check ONNX Runtime version compatibility modelCompatible = false; try { Ort::Env env(ORT_LOGGING_LEVEL_WARNING, "version_check"); auto* api = OrtGetApiBase()->GetApi(ORT_API_VERSION); modelCompatible = (api != nullptr); if (!modelCompatible) { qWarning() << "[NeuralTrackerTest] ONNX Runtime API version mismatch" << "(header=" << ORT_API_VERSION << ", DLL supports lower)"; } } catch (...) { modelCompatible = false; } } void TearDown() override { tempDir.reset(); } CloudPtr createTestCloud(int numPoints = 100) { CloudPtr cloud(new pcl::PointCloud<pcl::PointXYZRGB>); for (int i = 0; i < numPoints; ++i) { pcl::PointXYZRGB pt; pt.x = 0.1 * (i % 10) * 0.01f; pt.y = 0.1 * (i / 10) * 0.01f; pt.z = 0.01 * (i % 5) * 0.01f; pt.r = 255; pt.g = 255; pt.b = 255; cloud->push_back(pt); } return cloud; } std::unique_ptr<QTemporaryDir> tempDir; QString modelPath; bool modelCompatible = false; }; // Тест: Загрузка модели TEST_F(NeuralTrackerTest, LoadModel) { if (!modelCompatible) GTEST_SKIP() << "ONNX Runtime API version mismatch"; NeuralTracker tracker; bool result = tracker.loadModel(modelPath.toStdString()); ASSERT_TRUE(result); EXPECT_TRUE(tracker.isLoaded()); } // Тест: Проверка isLoaded после загрузки TEST_F(NeuralTrackerTest, IsLoadedAfterLoad) { if (!modelCompatible) GTEST_SKIP() << "ONNX Runtime API version mismatch"; NeuralTracker tracker; tracker.loadModel(modelPath.toStdString()); EXPECT_TRUE(tracker.isLoaded()); } // Тест: Ошибка при неверном пути TEST_F(NeuralTrackerTest, ErrorInvalidPath) { NeuralTracker tracker; bool result = tracker.loadModel("/nonexistent/path/to/model.onnx"); ASSERT_FALSE(result); EXPECT_FALSE(tracker.isLoaded()); } // Тест: Ошибка при пустом пути TEST_F(NeuralTrackerTest, ErrorEmptyPath) { NeuralTracker tracker; bool result = tracker.loadModel(""); ASSERT_FALSE(result); EXPECT_FALSE(tracker.isLoaded()); } // Тест: Оценка позы с валидными облаками TEST_F(NeuralTrackerTest, EstimatePoseValidClouds) { if (!modelCompatible) GTEST_SKIP() << "ONNX Runtime API version mismatch"; NeuralTracker tracker; if (!tracker.loadModel(modelPath.toStdString())) { GTEST_SKIP() << "Failed to load model, skipping pose estimation test"; } CloudPtr source = createTestCloud(200); CloudPtr target = createTestCloud(200); Eigen::Matrix4f result = tracker.estimatePose(source, target, 2048); // Результат должен быть валидной матрицей 4x4 EXPECT_EQ(result.rows(), 4); EXPECT_EQ(result.cols(), 4); // Проверяем, что матрица не содержит NaN for (int i = 0; i < 4; ++i) { for (int j = 0; j < 4; ++j) { EXPECT_FALSE(std::isnan(result(i, j))) << "NaN in result at (" << i << ", " << j << ")"; } } } // Тест: Оценка позы с пустым входом - должен вернуть Identity TEST_F(NeuralTrackerTest, EstimatePoseEmptyInput) { if (!modelCompatible) GTEST_SKIP() << "ONNX Runtime API version mismatch"; NeuralTracker tracker; if (!tracker.loadModel(modelPath.toStdString())) { GTEST_SKIP() << "Failed to load model, skipping empty input test"; } CloudPtr empty(new pcl::PointCloud<pcl::PointXYZRGB>); CloudPtr target = createTestCloud(100); Eigen::Matrix4f result = tracker.estimatePose(empty, target, 2048); // Должен вернуть Identity матрицу Eigen::Matrix4f expected = Eigen::Matrix4f::Identity(); // Сравниваем с небольшим допуском for (int i = 0; i < 4; ++i) { for (int j = 0; j < 4; ++j) { EXPECT_NEAR(result(i, j), expected(i, j), 1e-6) << "Mismatch at (" << i << ", " << j << ")"; } } } // Тест: Оценка позы с облаком без цвета (только XYZ) TEST_F(NeuralTrackerTest, EstimatePoseNoColor) { if (!modelCompatible) GTEST_SKIP() << "ONNX Runtime API version mismatch"; NeuralTracker tracker; if (!tracker.loadModel(modelPath.toStdString())) { GTEST_SKIP() << "Failed to load model, skipping no-color test"; } CloudPtr source(new pcl::PointCloud<pcl::PointXYZRGB>); CloudPtr target(new pcl::PointCloud<pcl::PointXYZRGB>); // Создаем облака только с XYZ (цвет будет дефолтным 255,255,255) for (int i = 0; i < 100; ++i) { pcl::PointXYZRGB pt; pt.x = 0.1 * (i % 10) * 0.01f; pt.y = 0.1 * (i / 10) * 0.01f; pt.z = 0.01 * (i % 5) * 0.01f; source->push_back(pt); target->push_back(pt); } Eigen::Matrix4f result = tracker.estimatePose(source, target, 2048); EXPECT_EQ(result.rows(), 4); EXPECT_EQ(result.cols(), 4); } // Тест: GPU/CPU режим TEST_F(NeuralTrackerTest, GPUorCPU) { if (!modelCompatible) GTEST_SKIP() << "ONNX Runtime API version mismatch"; NeuralTracker tracker; if (!tracker.loadModel(modelPath.toStdString())) { GTEST_SKIP() << "Failed to load model, skipping GPU/CPU test"; } // После последних изменений должно быть CPU EXPECT_FALSE(tracker.isUsingGPU()); } // Тест: Множественные загрузки модели TEST_F(NeuralTrackerTest, MultipleLoads) { if (!modelCompatible) GTEST_SKIP() << "ONNX Runtime API version mismatch"; NeuralTracker tracker; // Первая загрузка bool result1 = tracker.loadModel(modelPath.toStdString()); EXPECT_TRUE(result1); EXPECT_TRUE(tracker.isLoaded()); // Вторая загрузка (переопределение) bool result2 = tracker.loadModel(modelPath.toStdString()); EXPECT_TRUE(result2); EXPECT_TRUE(tracker.isLoaded()); } // Тест: Оценка позы с разными размерами облаков TEST_F(NeuralTrackerTest, DifferentCloudSizes) { if (!modelCompatible) GTEST_SKIP() << "ONNX Runtime API version mismatch"; NeuralTracker tracker; if (!tracker.loadModel(modelPath.toStdString())) { GTEST_SKIP() << "Failed to load model, skipping different sizes test"; } CloudPtr small = createTestCloud(10); CloudPtr large = createTestCloud(1000); // Сначала small -> large Eigen::Matrix4f result1 = tracker.estimatePose(small, large, 2048); EXPECT_EQ(result1.rows(), 4); // Потом large -> small Eigen::Matrix4f result2 = tracker.estimatePose(large, small, 2048); EXPECT_EQ(result2.rows(), 4); } // Тест: Тест с идентичными облаками (должен вернуть Identity или близкое к нему) TEST_F(NeuralTrackerTest, IdenticalClouds) { if (!modelCompatible) GTEST_SKIP() << "ONNX Runtime API version mismatch"; NeuralTracker tracker; if (!tracker.loadModel(modelPath.toStdString())) { GTEST_SKIP() << "Failed to load model, skipping identical clouds test"; } CloudPtr cloud = createTestCloud(200); Eigen::Matrix4f result = tracker.estimatePose(cloud, cloud, 2048); // Должен вернуть Identity (или очень близкое) Eigen::Matrix4f expected = Eigen::Matrix4f::Identity(); for (int i = 0; i < 4; ++i) { for (int j = 0; j < 4; ++j) { EXPECT_NEAR(result(i, j), expected(i, j), 0.1) << "Mismatch at (" << i << ", " << j << ")"; } } } // Тест: Негативные значения в облаке TEST_F(NeuralTrackerTest, NegativeCoordinates) { if (!modelCompatible) GTEST_SKIP() << "ONNX Runtime API version mismatch"; NeuralTracker tracker; if (!tracker.loadModel(modelPath.toStdString())) { GTEST_SKIP() << "Failed to load model, skipping negative coords test"; } CloudPtr source(new pcl::PointCloud<pcl::PointXYZRGB>); CloudPtr target(new pcl::PointCloud<pcl::PointXYZRGB>); for (int i = 0; i < 50; ++i) { pcl::PointXYZRGB pt; pt.x = -0.1 + 0.002 * (i % 10); pt.y = -0.1 + 0.002 * (i / 10); pt.z = -0.01 + 0.0002 * (i % 5); source->push_back(pt); target->push_back(pt); } Eigen::Matrix4f result = tracker.estimatePose(source, target, 2048); EXPECT_EQ(result.rows(), 4); EXPECT_EQ(result.cols(), 4); }