From a3ac723fe11acb21b3062c9c465ea8751c5e45c6 Mon Sep 17 00:00:00 2001 From: Wiktor-Laska Date: Mon, 30 Mar 2026 14:02:57 +0200 Subject: [PATCH 1/3] =?UTF-8?q?ca=C5=82y=20kod=20dzia=C5=82aj=C4=85cy?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- MODULE.bazel | 5 +- MODULE.bazel.lock | 17 +- README.md | 7 + WORKSPACE | 0 app/BUILD.bazel | 28 +- app/apogee.cpp | 100 +- app/apogee_detector_test.cc | 100 + app/testy.cpp | 71 + data/.DS_Store | Bin 6148 -> 0 bytes data/BUILD.bazel | 5 - data/accelerometer.csv | 3666 ----------------------------------- data/barometer.csv | 3666 ----------------------------------- lib/BUILD.bazel | 5 +- lib/DataLoader.cpp | 161 ++ lib/DataLoader.h | 19 + lib/KalmanFilter.cpp | 6 +- lib/KalmanFilter.h | 5 +- lib/KalmanFilterR7.cpp | 48 +- lib/KalmanFilterR7.h | 5 +- lib/Matrix.cpp | 177 ++ lib/Matrix.h | 29 + 21 files changed, 685 insertions(+), 7435 deletions(-) delete mode 100644 WORKSPACE create mode 100644 app/apogee_detector_test.cc create mode 100644 app/testy.cpp delete mode 100644 data/.DS_Store delete mode 100644 data/BUILD.bazel delete mode 100644 data/accelerometer.csv delete mode 100644 data/barometer.csv create mode 100644 lib/DataLoader.cpp create mode 100644 lib/DataLoader.h create mode 100644 lib/Matrix.cpp create mode 100644 lib/Matrix.h diff --git a/MODULE.bazel b/MODULE.bazel index 5f3fe5a..d71cddd 100644 --- a/MODULE.bazel +++ b/MODULE.bazel @@ -2,6 +2,7 @@ module( name = "bazel_apogeum", version = "0.1.0", ) -bazel_dep(name = "eigen", version = "4.0.0-20241125.bcr.2") -bazel_dep(name = "rules_cc", version = "0.0.17") +bazel_dep(name = "eigen", version = "4.0.0-20241125.bcr.2") +bazel_dep(name = "googletest", version = "1.17.0.bcr.2", repo_name = "com_google_googletest") +bazel_dep(name = "rules_cc", version = "0.0.17") \ No newline at end of file diff --git a/MODULE.bazel.lock b/MODULE.bazel.lock index cb746a4..ce9e6a0 100644 --- a/MODULE.bazel.lock +++ b/MODULE.bazel.lock @@ -18,6 +18,7 @@ "https://bcr.bazel.build/modules/apple_support/1.15.1/MODULE.bazel": "a0556fefca0b1bb2de8567b8827518f94db6a6e7e7d632b4c48dc5f865bc7c85", "https://bcr.bazel.build/modules/apple_support/1.21.0/MODULE.bazel": "ac1824ed5edf17dee2fdd4927ada30c9f8c3b520be1b5fd02a5da15bc10bff3e", "https://bcr.bazel.build/modules/apple_support/1.21.1/MODULE.bazel": "5809fa3efab15d1f3c3c635af6974044bac8a4919c62238cce06acee8a8c11f1", + "https://bcr.bazel.build/modules/apple_support/1.22.1/MODULE.bazel": "90bd1a660590f3ceffbdf524e37483094b29352d85317060b2327fff8f3f4458", "https://bcr.bazel.build/modules/apple_support/1.24.2/MODULE.bazel": "0e62471818affb9f0b26f128831d5c40b074d32e6dda5a0d3852847215a41ca4", "https://bcr.bazel.build/modules/apple_support/1.24.2/source.json": "2c22c9827093250406c5568da6c54e6fdf0ef06238def3d99c71b12feb057a8d", "https://bcr.bazel.build/modules/bazel_features/1.1.1/MODULE.bazel": "27b8c79ef57efe08efccbd9dd6ef70d61b4798320b8d3c134fd571f78963dbcd", @@ -61,8 +62,9 @@ "https://bcr.bazel.build/modules/googletest/1.14.0.bcr.1/MODULE.bazel": "22c31a561553727960057361aa33bf20fb2e98584bc4fec007906e27053f80c6", "https://bcr.bazel.build/modules/googletest/1.14.0/MODULE.bazel": "cfbcbf3e6eac06ef9d85900f64424708cc08687d1b527f0ef65aa7517af8118f", "https://bcr.bazel.build/modules/googletest/1.15.2/MODULE.bazel": "6de1edc1d26cafb0ea1a6ab3f4d4192d91a312fd2d360b63adaa213cd00b2108", + "https://bcr.bazel.build/modules/googletest/1.17.0.bcr.2/MODULE.bazel": "827f54f492a3ce549c940106d73de332c2b30cebd0c20c0bc5d786aba7f116cb", + "https://bcr.bazel.build/modules/googletest/1.17.0.bcr.2/source.json": "3664514073a819992320ffbce5825e4238459df344d8b01748af2208f8d2e1eb", "https://bcr.bazel.build/modules/googletest/1.17.0/MODULE.bazel": "dbec758171594a705933a29fcf69293d2468c49ec1f2ebca65c36f504d72df46", - "https://bcr.bazel.build/modules/googletest/1.17.0/source.json": "38e4454b25fc30f15439c0378e57909ab1fd0a443158aa35aec685da727cd713", "https://bcr.bazel.build/modules/jsoncpp/1.9.5/MODULE.bazel": "31271aedc59e815656f5736f282bb7509a97c7ecb43e927ac1a37966e0578075", "https://bcr.bazel.build/modules/jsoncpp/1.9.6/MODULE.bazel": "2f8d20d3b7d54143213c4dfc3d98225c42de7d666011528dc8fe91591e2e17b0", "https://bcr.bazel.build/modules/jsoncpp/1.9.6/source.json": "a04756d367a2126c3541682864ecec52f92cdee80a35735a3cb249ce015ca000", @@ -80,6 +82,8 @@ "https://bcr.bazel.build/modules/platforms/1.0.0/MODULE.bazel": "f05feb42b48f1b3c225e4ccf351f367be0371411a803198ec34a389fb22aa580", "https://bcr.bazel.build/modules/platforms/1.0.0/source.json": "f4ff1fd412e0246fd38c82328eb209130ead81d62dcd5a9e40910f867f733d96", "https://bcr.bazel.build/modules/protobuf/21.7/MODULE.bazel": "a5a29bb89544f9b97edce05642fac225a808b5b7be74038ea3640fae2f8e66a7", + "https://bcr.bazel.build/modules/protobuf/23.1/MODULE.bazel": "88b393b3eb4101d18129e5db51847cd40a5517a53e81216144a8c32dfeeca52a", + "https://bcr.bazel.build/modules/protobuf/24.4/MODULE.bazel": "7bc7ce5f2abf36b3b7b7c8218d3acdebb9426aeb35c2257c96445756f970eb12", "https://bcr.bazel.build/modules/protobuf/27.0/MODULE.bazel": "7873b60be88844a0a1d8f80b9d5d20cfbd8495a689b8763e76c6372998d3f64c", "https://bcr.bazel.build/modules/protobuf/29.0-rc2/MODULE.bazel": "6241d35983510143049943fc0d57937937122baf1b287862f9dc8590fc4c37df", "https://bcr.bazel.build/modules/protobuf/29.0-rc3/MODULE.bazel": "33c2dfa286578573afc55a7acaea3cada4122b9631007c594bf0729f41c8de92", @@ -90,11 +94,13 @@ "https://bcr.bazel.build/modules/protobuf/33.4/source.json": "555f8686b4c7d6b5ba731fbea13bf656b4bfd9a7ff629c1d9d3f6e1d6155de79", "https://bcr.bazel.build/modules/pybind11_bazel/2.11.1/MODULE.bazel": "88af1c246226d87e65be78ed49ecd1e6f5e98648558c14ce99176da041dc378e", "https://bcr.bazel.build/modules/pybind11_bazel/2.12.0/MODULE.bazel": "e6f4c20442eaa7c90d7190d8dc539d0ab422f95c65a57cc59562170c58ae3d34", - "https://bcr.bazel.build/modules/pybind11_bazel/2.12.0/source.json": "6900fdc8a9e95866b8c0d4ad4aba4d4236317b5c1cd04c502df3f0d33afed680", + "https://bcr.bazel.build/modules/pybind11_bazel/2.13.6/MODULE.bazel": "2d746fda559464b253b2b2e6073cb51643a2ac79009ca02100ebbc44b4548656", + "https://bcr.bazel.build/modules/pybind11_bazel/2.13.6/source.json": "6aa0703de8efb20cc897bbdbeb928582ee7beaf278bcd001ac253e1605bddfae", "https://bcr.bazel.build/modules/re2/2023-09-01/MODULE.bazel": "cb3d511531b16cfc78a225a9e2136007a48cf8a677e4264baeab57fe78a80206", "https://bcr.bazel.build/modules/re2/2024-07-02.bcr.1/MODULE.bazel": "b4963dda9b31080be1905ef085ecd7dd6cd47c05c79b9cdf83ade83ab2ab271a", - "https://bcr.bazel.build/modules/re2/2024-07-02.bcr.1/source.json": "2ff292be6ef3340325ce8a045ecc326e92cbfab47c7cbab4bd85d28971b97ac4", "https://bcr.bazel.build/modules/re2/2024-07-02/MODULE.bazel": "0eadc4395959969297cbcf31a249ff457f2f1d456228c67719480205aa306daa", + "https://bcr.bazel.build/modules/re2/2025-08-12.bcr.1/MODULE.bazel": "e09b434b122bfb786a69179f9b325e35cb1856c3f56a7a81dd61609260ed46e1", + "https://bcr.bazel.build/modules/re2/2025-08-12.bcr.1/source.json": "a8ae7c09533bf67f9f6e5122d884d5741600b09d78dca6fc0f2f8d2ee0c2d957", "https://bcr.bazel.build/modules/rules_android/0.1.1/MODULE.bazel": "48809ab0091b07ad0182defb787c4c5328bd3a278938415c00a7b69b50c4d3a8", "https://bcr.bazel.build/modules/rules_android/0.1.1/source.json": "e6986b41626ee10bdc864937ffb6d6bf275bb5b9c65120e6137d56e6331f089e", "https://bcr.bazel.build/modules/rules_apple/3.16.0/MODULE.bazel": "0d1caf0b8375942ce98ea944be754a18874041e4e0459401d925577624d3a54a", @@ -112,6 +118,7 @@ "https://bcr.bazel.build/modules/rules_cc/0.0.9/MODULE.bazel": "836e76439f354b89afe6a911a7adf59a6b2518fafb174483ad78a2a2fde7b1c5", "https://bcr.bazel.build/modules/rules_cc/0.1.1/MODULE.bazel": "2f0222a6f229f0bf44cd711dc13c858dad98c62d52bd51d8fc3a764a83125513", "https://bcr.bazel.build/modules/rules_cc/0.1.2/MODULE.bazel": "557ddc3a96858ec0d465a87c0a931054d7dcfd6583af2c7ed3baf494407fd8d0", + "https://bcr.bazel.build/modules/rules_cc/0.1.4/MODULE.bazel": "bb03a452a7527ac25a7518fb86a946ef63df860b9657d8323a0c50f8504fb0b9", "https://bcr.bazel.build/modules/rules_cc/0.1.5/MODULE.bazel": "88dfc9361e8b5ae1008ac38f7cdfd45ad738e4fa676a3ad67d19204f045a1fd8", "https://bcr.bazel.build/modules/rules_cc/0.2.0/MODULE.bazel": "b5c17f90458caae90d2ccd114c81970062946f49f355610ed89bebf954f5783c", "https://bcr.bazel.build/modules/rules_cc/0.2.13/MODULE.bazel": "eecdd666eda6be16a8d9dc15e44b5c75133405e820f620a234acc4b1fdc5aa37", @@ -123,6 +130,7 @@ "https://bcr.bazel.build/modules/rules_java/4.0.0/MODULE.bazel": "5a78a7ae82cd1a33cef56dc578c7d2a46ed0dca12643ee45edbb8417899e6f74", "https://bcr.bazel.build/modules/rules_java/5.3.5/MODULE.bazel": "a4ec4f2db570171e3e5eb753276ee4b389bae16b96207e9d3230895c99644b86", "https://bcr.bazel.build/modules/rules_java/6.5.2/MODULE.bazel": "1d440d262d0e08453fa0c4d8f699ba81609ed0e9a9a0f02cd10b3e7942e61e31", + "https://bcr.bazel.build/modules/rules_java/7.1.0/MODULE.bazel": "30d9135a2b6561c761bd67bd4990da591e6bdc128790ce3e7afd6a3558b2fb64", "https://bcr.bazel.build/modules/rules_java/7.10.0/MODULE.bazel": "530c3beb3067e870561739f1144329a21c851ff771cd752a49e06e3dc9c2e71a", "https://bcr.bazel.build/modules/rules_java/7.12.2/MODULE.bazel": "579c505165ee757a4280ef83cda0150eea193eed3bef50b1004ba88b99da6de6", "https://bcr.bazel.build/modules/rules_java/7.2.0/MODULE.bazel": "06c0334c9be61e6cef2c8c84a7800cef502063269a5af25ceb100b192453d4ab", @@ -159,9 +167,11 @@ "https://bcr.bazel.build/modules/rules_python/0.28.0/MODULE.bazel": "cba2573d870babc976664a912539b320cbaa7114cd3e8f053c720171cde331ed", "https://bcr.bazel.build/modules/rules_python/0.31.0/MODULE.bazel": "93a43dc47ee570e6ec9f5779b2e64c1476a6ce921c48cc9a1678a91dd5f8fd58", "https://bcr.bazel.build/modules/rules_python/0.33.2/MODULE.bazel": "3e036c4ad8d804a4dad897d333d8dce200d943df4827cb849840055be8d2e937", + "https://bcr.bazel.build/modules/rules_python/0.34.0/MODULE.bazel": "1d623d026e075b78c9fde483a889cda7996f5da4f36dffb24c246ab30f06513a", "https://bcr.bazel.build/modules/rules_python/0.4.0/MODULE.bazel": "9208ee05fd48bf09ac60ed269791cf17fb343db56c8226a720fbb1cdf467166c", "https://bcr.bazel.build/modules/rules_python/1.3.0/MODULE.bazel": "8361d57eafb67c09b75bf4bbe6be360e1b8f4f18118ab48037f2bd50aa2ccb13", "https://bcr.bazel.build/modules/rules_python/1.4.1/MODULE.bazel": "8991ad45bdc25018301d6b7e1d3626afc3c8af8aaf4bc04f23d0b99c938b73a6", + "https://bcr.bazel.build/modules/rules_python/1.5.1/MODULE.bazel": "acfe65880942d44a69129d4c5c3122d57baaf3edf58ae5a6bd4edea114906bf5", "https://bcr.bazel.build/modules/rules_python/1.6.0/MODULE.bazel": "7e04ad8f8d5bea40451cf80b1bd8262552aa73f841415d20db96b7241bd027d8", "https://bcr.bazel.build/modules/rules_python/1.7.0/MODULE.bazel": "d01f995ecd137abf30238ad9ce97f8fc3ac57289c8b24bd0bf53324d937a14f8", "https://bcr.bazel.build/modules/rules_python/1.7.0/source.json": "028a084b65dcf8f4dc4f82f8778dbe65df133f234b316828a82e060d81bdce32", @@ -183,6 +193,7 @@ "https://bcr.bazel.build/modules/swift_argument_parser/1.3.1.2/MODULE.bazel": "75aab2373a4bbe2a1260b9bf2a1ebbdbf872d3bd36f80bff058dccd82e89422f", "https://bcr.bazel.build/modules/swift_argument_parser/1.3.1.2/source.json": "5fba48bbe0ba48761f9e9f75f92876cafb5d07c0ce059cc7a8027416de94a05b", "https://bcr.bazel.build/modules/upb/0.0.0-20220923-a547704/MODULE.bazel": "7298990c00040a0e2f121f6c32544bab27d4452f80d9ce51349b1a28f3005c43", + "https://bcr.bazel.build/modules/upb/0.0.0-20230516-61a97ef/MODULE.bazel": "c0df5e35ad55e264160417fd0875932ee3c9dda63d9fccace35ac62f45e1b6f9", "https://bcr.bazel.build/modules/zlib/1.2.11/MODULE.bazel": "07b389abc85fdbca459b69e2ec656ae5622873af3f845e1c9d80fe179f3effa0", "https://bcr.bazel.build/modules/zlib/1.3.1.bcr.5/MODULE.bazel": "eec517b5bbe5492629466e11dae908d043364302283de25581e3eb944326c4ca", "https://bcr.bazel.build/modules/zlib/1.3.1.bcr.5/source.json": "22bc55c47af97246cfc093d0acf683a7869377de362b5d1c552c2c2e16b7a806", diff --git a/README.md b/README.md index e69de29..988648d 100644 --- a/README.md +++ b/README.md @@ -0,0 +1,7 @@ +INSTRUKCJA DO TESTOWANIA WIELU PLIKÓW DO WYKRYWANIA APOGEUM: +dane powinny znajdywać się w folderze /data w własnym folderze +muszą być nazwane accelerometer.csv i barometer.csv +na każdą parę musi być inny folder +Program odpalać bazel run //app:testy + +żeby ręcznie odpalić testy należy teraz w folderze data utworzyć podane pliki data \ No newline at end of file diff --git a/WORKSPACE b/WORKSPACE deleted file mode 100644 index e69de29..0000000 diff --git a/app/BUILD.bazel b/app/BUILD.bazel index d4954f5..bb0c5bd 100644 --- a/app/BUILD.bazel +++ b/app/BUILD.bazel @@ -1,15 +1,37 @@ -load("@rules_cc//cc:defs.bzl", "cc_binary") +load("@rules_cc//cc:defs.bzl", "cc_test") -cc_binary( +cc_test( name = "main", srcs = ["main.cpp"], deps = ["//lib:apogee_lib"], data = ["//data:data_files"], ) -cc_binary( +cc_test( name = "csv_apogee_test", srcs = ["apogee.cpp"], deps = ["//lib:apogee_lib"], + data = ["//data:data_files"], +) + +cc_test( + name = "testy", + srcs = ["testy.cpp"], + data = [ + ":csv_apogee_test", + ], +) + +cc_test( + name = "test-cc", + srcs = [ + "apogee_detector_test.cc" + ], + visibility = ["//visibility:public"], + deps = [ + "@com_google_googletest//:gtest_main", + "//lib:apogee_lib", + ], + data = ["//data:data_files"], ) \ No newline at end of file diff --git a/app/apogee.cpp b/app/apogee.cpp index 234149a..3f4f36a 100644 --- a/app/apogee.cpp +++ b/app/apogee.cpp @@ -1,74 +1,80 @@ #include #include -#include +#include +#include // dodane do std::abs +#include "lib/Matrix.h" #include "lib/KalmanFilterR7.h" #include "lib/ApogeeDetector.h" +#include "lib/DataLoader.h" -std::vector readColumnCSV(const std::string& path, size_t colIndex) { - std::vector data; - - try { - if (path.find("accelerometer") != std::string::npos) { - CsvReader csvReader(path); - for (size_t i = 0; i < csvReader.rowCount(); ++i) { - auto row = csvReader[i]; - switch (colIndex) { - case 0: data.push_back(row.template get<0>()); break; - case 1: data.push_back(row.template get<1>()); break; - case 2: data.push_back(row.template get<2>()); break; - case 3: data.push_back(row.template get<3>()); break; - default: break; - } - } - } else if (path.find("barometer") != std::string::npos) { - CsvReader csvReader(path); - for (size_t i = 0; i < csvReader.rowCount(); ++i) { - auto row = csvReader[i]; - switch (colIndex) { - case 0: data.push_back(row.template get<0>()); break; - case 1: data.push_back(row.template get<1>()); break; - default: break; - } - } - } - } catch (const std::exception& e) { - std::cerr << "Error reading CSV file " << path << ": " << e.what() << std::endl; +int main(int argc, char *argv[]) +{ + if (argc != 4 && argc != 1) + { + std::cerr << "Usage: " << argv[0] << " [barometer_file accelerometer_file config_file]\n"; + return 1; } - - return data; -} -int main() { - KalmanFilterR7 kf(0.1); - RealTimeApogee apogee(15, -0.5, 0.0); + std::string barometerPath = "data/barometer.csv"; + std::string accelerometerPath = "data/accelerometer.csv"; + std::string configPath = "data/config.txt"; + + if (argc == 4) { + barometerPath = argv[1]; + accelerometerPath = argv[2]; + configPath = argv[3]; + } + + // --- 1. Aktualizacja lub generowanie config.txt --- + checkAndGenerateConfig(configPath); - const double dt = 0.1; + // --- 2. Wczytanie przygotowanego configu --- + ConfigData config = readConfig(configPath); - std::vector accelData = readColumnCSV("data/accelerometer.csv", 3); - std::vector pressureData = readColumnCSV("data/barometer.csv", 1); + const double dt = config.hz > 0 ? 1.0 / config.hz : 0.1; + KalmanFilterR7 kf(dt); + RealTimeApogee apogee(15, -0.5, 0.0); - if (accelData.empty() || pressureData.empty()) { + // --- 3. Wczytanie sensorów --- + std::vector pressureData = readColumnCSV(barometerPath, 1); + std::vector accelData = readColumnCSV(accelerometerPath, 3); + + if (accelData.empty() || pressureData.empty()) + { std::cerr << "Error: data is not loaded!\n"; return 1; } - + size_t dataSize = accelData.size(); + // --- 4. Główna pętla detekcji --- for (size_t i = 0; i < dataSize; ++i) { double t = i * dt; double accel = accelData[i]; double pressure = pressureData[i]; - Eigen::Vector2d state = kf.processMeasurement(accel, pressure); - double height = state(0); - double velocity = state(1); + Matrix state = kf.processMeasurement(accel, pressure); + double height = state(0,0); + double velocity = state(1,0); apogee.update(height, velocity); - std::cout << "t=" << t << " s, h=" << height << " m, v=" << velocity << " m/s\n"; + if (apogee.isApogeeReached()) { + double apogeeheight = apogee.getApogee(); + std::cout << ">>> Wykryto Apogeum: " << height << " m w czasie t = " << t << " s, max height: " << apogeeheight << " m\n"; - if (apogee.isApogeeReached()) { - std::cout << ">>> Apogee reached: " << apogee.getApogee() << " meters\n"; + if (config.loaded) { + double heightError = config.max_height_clean - height; + double heightErrorPct = (heightError / config.max_height_clean) * 100.0; + double timeError = config.time_to_apogee - t; + double timeErrorPct = (timeError / config.time_to_apogee) * 100.0; + + std::cout << "\n--- Porównanie z danymi referencyjnymi (Config) ---\n"; + std::cout << "Prawdziwa wys. (clean): " << config.max_height_clean << " m\n"; + std::cout << "Błąd wysokości: " << std::abs(heightError) << " m (" << std::abs(heightErrorPct) << "%)\n"; + std::cout << "Prawdziwy czas: " << config.time_to_apogee << " s\n"; + std::cout << "Błąd czasu detekcji: " << std::abs(timeError) << " s (" << std::abs(timeErrorPct) << "%)\n"; + } break; } } diff --git a/app/apogee_detector_test.cc b/app/apogee_detector_test.cc new file mode 100644 index 0000000..7da1257 --- /dev/null +++ b/app/apogee_detector_test.cc @@ -0,0 +1,100 @@ +#include +#include +#include +#include +#include +#include +#include + +#include "lib/Matrix.h" +#include "lib/KalmanFilterR7.h" +#include "lib/ApogeeDetector.h" +#include "lib/DataLoader.h" +namespace { + static constexpr auto apoogeeError=0.15; +} +namespace fs = std::filesystem; + +TEST(detect_test, test_apogee_detecotr) { + fs::path base_path = "data/10hz_1000m"; + + fs::path barometerPath = base_path / "exported_barometer_data.csv"; + fs::path accelerometerPath = base_path / "exported_accel_data.csv"; + fs::path configPath = base_path / "config.txt"; + checkAndGenerateConfig(configPath); + ConfigData config = readConfig(configPath); + const double dt = config.hz > 0 ? 1.0 / config.hz : 0.1; + KalmanFilterR7 kf(dt); + RealTimeApogee apogee(15, -0.5, 0.0); + + std::vector pressureData = readColumnCSV(barometerPath, 1); + std::vector accelData = readColumnCSV(accelerometerPath, 3); + size_t dataSize = accelData.size(); + + double height = 0.0; + for (size_t i = 0; i < dataSize; ++i) { + double accel = accelData[i]; + double pressure = pressureData[i]; + Matrix state = kf.processMeasurement(accel, pressure); + height = state(0,0); + double velocity = state(1,0); + apogee.update(height, velocity); + if (apogee.isApogeeReached()) { + break; + } + } + EXPECT_NEAR(config.max_height_clean, height, 1.0); +} +class ApogeeFlightDataTest : public ::testing::TestWithParam{}; +TEST_P(ApogeeFlightDataTest, CalculatesApogeeCorrectly){ + fs::path base_path = GetParam(); + fs::path barometerPath = base_path / "exported_barometer_data.csv"; + fs::path accelerometerPath = base_path / "exported_accel_data.csv"; + fs::path configPath = base_path / "config.txt"; + checkAndGenerateConfig(configPath); + ConfigData config = readConfig(configPath); + const double dt = config.hz > 0 ? 1.0 / config.hz : 0.1; + KalmanFilterR7 kf(dt); + RealTimeApogee apogee(15, -0.5, 0.0); + + std::vector pressureData = readColumnCSV(barometerPath, 1); + std::vector accelData = readColumnCSV(accelerometerPath, 3); + size_t dataSize = accelData.size(); + + double height = 0.0; + for (size_t i = 0; i < dataSize; ++i) { + double accel = accelData[i]; + double pressure = pressureData[i]; + Matrix state = kf.processMeasurement(accel, pressure); + height = state(0,0); + double velocity = state(1,0); + apogee.update(height, velocity); + if (apogee.isApogeeReached()) { + break; + } + } + EXPECT_NEAR(config.max_height_clean, height, config.max_height_clean*apoogeeError); + +} + +INSTANTIATE_TEST_SUITE_P( + FlightDataSimulation, + ApogeeFlightDataTest, + ::testing::Values( + "data/10hz_1000m", + "data/10hz_2000m", + "data/10hz_4000m", + "data/10hz_5000m", + "data/10hz_6000m", + "data/100hz_1000m", + "data/100hz_2000m", + "data/100hz_3000m", + "data/100hz_4000m", + "data/100hz_5000m", + "data/100hz_6000m", + "data/1000hz_1000m", + "data/1000hz_2000m", + "data/1000hz_5000m", + "data/1000hz_6000m" + ) +); \ No newline at end of file diff --git a/app/testy.cpp b/app/testy.cpp new file mode 100644 index 0000000..1de198a --- /dev/null +++ b/app/testy.cpp @@ -0,0 +1,71 @@ +#include +#include +#include +#include + +namespace fs = std::filesystem; + +int main() +{ + const char *workspace_dir = std::getenv("BUILD_WORKSPACE_DIRECTORY"); + + if (workspace_dir == nullptr) + { + return 1; + } + + fs::path base_path = workspace_dir; + fs::path data_path = base_path / "data"; + + fs::path executable_path = base_path / "bazel-bin" / "app" / "csv_apogee_test"; + + if (!fs::exists(data_path) || !fs::is_directory(data_path)) + { + std::cerr << "Błąd: Folder " << data_path << " nie istnieje\n"; + return 1; + } + + if (!fs::exists(executable_path)) + { + std::cerr << "Błąd: Plik wykonywalny " << executable_path << " nie istnieje.\n"; + return 1; + } + for (const auto &entry : fs::directory_iterator(data_path)) + { + + if (entry.is_directory()) + { + fs::path barometr_file = entry.path() / "exported_barometer_data.csv"; + fs::path akcelerometr_file = entry.path() / "exported_accel_data.csv"; + fs::path config_file = entry.path() / "config.txt"; + + if (fs::exists(barometr_file) && fs::exists(akcelerometr_file)) + { + std::string command = executable_path.string() + + " \"" + barometr_file.string() + "\"" + + " \"" + akcelerometr_file.string() + "\""+ + " \"" + config_file.string() + "\""; + + std::cout << "----------------------------------------\n"; + std::cout << "Testowanie dla danych: " << entry.path().filename() << "\n"; + + int result = std::system(command.c_str()); + + if (result != 0) + { + std::cerr << "Ostrzeżenie: Program csv_apogee_test zwrócił kod błędu (" << result << ") dla " << entry.path().filename() << "\n"; + } + } + else + { + std::cout << "----------------------------------------\n"; + std::cerr << "Pominięto folder: " << entry.path().filename(); + } + } + } + + std::cout << "----------------------------------------\n"; + std::cout << "Zakończono wszystkie testy.\n"; + + return 0; +} \ No newline at end of file diff --git a/data/.DS_Store b/data/.DS_Store deleted file mode 100644 index 1f3ab452bc94bf71017623245865a4fa5d90091c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6148 zcmeHL%TB{E5FA4fl@L<7ar75d;t#BmUNKiQYoA|*pv+E)P5ywiP-Do}Q z^{yR{6h8tWtzI8*fCYd#RhVQeiMc`%^`T%uzi$C>|@`Ti}_(xV6lf`MQl7zhSV$N=|j$^61G z%3vTE2nIeG(E5<6!qTuh+S0*7$7i+Agc901APaND(y%(Rg_1m#=&7k)F_Nd#pIcmM zSRFkb$wp>BZRF$SCE4ioXA4Ivj!^~!!N8b-bFVJ6|8MxoOkVQGDNzdsf`Na=K$@-Z z*7~K@_SPTM(_WjY_f(1EstgM4(IJ2pts~dg= +#include +#include +#include +#include +#include +#include "csvReader/CsvReader.h" + +// Funkcja pomocnicza do usuwania spacji i znaków nowej linii z brzegów stringa +std::string trim(const std::string& str) { + size_t first = str.find_first_not_of(" \t\r\n"); + if (std::string::npos == first) return ""; + size_t last = str.find_last_not_of(" \t\r\n"); + return str.substr(first, (last - first + 1)); +} + +// Funkcja pomocnicza do wyciągnięcia ścieżki do flight_truth.csv na podstawie ścieżki do config.txt +std::string getTruthPath(const std::string& configPath) { + size_t lastSlash = configPath.find_last_of("/\\"); + if (lastSlash != std::string::npos) { + return configPath.substr(0, lastSlash + 1) + "flight_truth.csv"; + } + return "flight_truth.csv"; +} + +void checkAndGenerateConfig(const std::string& configPath) { + std::string truthPath = getTruthPath(configPath); + std::ifstream truthFile(truthPath); + + // 1. Sprawdzamy czy istnieje flight_truth.csv + if (truthFile.is_open()) { + std::cout << ">>> Znaleziono plik referencyjny: " << truthPath << ". Nadpisuje config...\n"; + + std::string line; + // Pomiń nagłówek (t,x,y,z,vx,vy,vz,ax,ay,az) + std::getline(truthFile, line); + + double max_z = -std::numeric_limits::infinity(); + double time_at_apogee = 0.0; + double t0 = -1.0, t1 = -1.0; + + // 2. Analiza danych z pliku prawdy + while (std::getline(truthFile, line)) { + std::stringstream ss(line); + std::string cell; + std::vector row; + + while (std::getline(ss, cell, ',')) { + try { + row.push_back(std::stod(cell)); + } catch (...) { + row.push_back(0.0); + } + } + + if (row.size() >= 4) { + double t = row[0]; + double z = row[3]; + + if (t0 < 0) t0 = t; + else if (t1 < 0) t1 = t; + + if (z > max_z) { + max_z = z; + time_at_apogee = t; + } + } + } + + // Wyliczenie częstotliwości (hz) + double hz = 100.0; + if (t0 >= 0 && t1 > t0) { + hz = 1.0 / (t1 - t0); + } + + // 3. Nadpisanie pliku config.txt + std::ofstream outConfig(configPath); + if (outConfig.is_open()) { + outConfig << "max_height=" << max_z << "\n"; + outConfig << "time_to_apogee=" << time_at_apogee << "\n"; + outConfig << "hz=" << hz << "\n"; + std::cout << ">>> Pomyslnie zaktualizowano: " << configPath << "\n"; + } + } else { + // 4. Jeśli nie ma flight_truth.csv, polegamy na tym, co użytkownik wpisał w config.txt + std::cout << ">>> Brak " << truthPath << ". Uzywam istniejacego " << configPath << " (jesli istnieje).\n"; + } +} + +ConfigData readConfig(const std::string& path) { + ConfigData config; + config.hz = 10.0; // Ustawienie domyślnego hz, w razie jakby config był pusty + + std::ifstream file(path); + if (!file.is_open()) { + std::cerr << "Ostrzezenie: Nie udalo sie otworzyc pliku konfiguracyjnego (txt): " << path << std::endl; + return config; + } + + std::string line; + while (std::getline(file, line)) { + if (line.empty() || line[0] == '#') continue; + + auto delimiterPos = line.find('='); + if (delimiterPos != std::string::npos) { + std::string key = trim(line.substr(0, delimiterPos)); + std::string valueStr = trim(line.substr(delimiterPos + 1)); + + try { + if (key == "max_height") { + config.max_height_clean = std::stod(valueStr); + } else if (key == "time_to_apogee") { + config.time_to_apogee = std::stod(valueStr); + } else if (key == "hz") { + config.hz = std::stod(valueStr); + } + } catch (const std::exception& e) { + std::cerr << "Blad parsowania wartosci dla klucza '" << key << "': " << e.what() << std::endl; + } + } + } + config.loaded = true; + return config; +} + +std::vector readColumnCSV(const std::string &path, size_t colIndex) { + std::vector data; + + try { + if (path.find("accel") != std::string::npos) { + CsvReader csvReader(path); + for (int i = 0; i < csvReader.rowCount(); ++i) { + auto row = csvReader[i]; + switch (colIndex) { + case 0: data.push_back(row.template get<0>()); break; + case 1: data.push_back(row.template get<1>()); break; + case 2: data.push_back(row.template get<2>()); break; + case 3: data.push_back(row.template get<3>()); break; + default: break; + } + } + } else if (path.find("baromet") != std::string::npos) { + CsvReader csvReader(path); + for (int i = 0; i < csvReader.rowCount(); ++i) { + auto row = csvReader[i]; + switch (colIndex) { + case 0: data.push_back(row.template get<0>()); break; + case 1: data.push_back(row.template get<1>()); break; + default: break; + } + } + } else { + std::cerr << "Ostrzezenie: Typ pliku nierozpoznany po sciezce: " << path << std::endl; + } + } catch (const std::exception &e) { + std::cerr << "Error reading CSV file " << path << ": " << e.what() << std::endl; + } + + return data; +} \ No newline at end of file diff --git a/lib/DataLoader.h b/lib/DataLoader.h new file mode 100644 index 0000000..b8fb564 --- /dev/null +++ b/lib/DataLoader.h @@ -0,0 +1,19 @@ +#ifndef DATALOADER_H +#define DATALOADER_H + +#include +#include + +struct ConfigData { + double max_height_clean = 0.0; + double time_to_apogee = 0.0; + double hz = 0.0; + bool loaded = false; +}; +void checkAndGenerateConfig(const std::string& configPath); + +ConfigData readConfig(const std::string& path); + +std::vector readColumnCSV(const std::string &path, size_t colIndex); + +#endif \ No newline at end of file diff --git a/lib/KalmanFilter.cpp b/lib/KalmanFilter.cpp index 0cf3a31..476fd1b 100644 --- a/lib/KalmanFilter.cpp +++ b/lib/KalmanFilter.cpp @@ -15,13 +15,13 @@ void KalmanFilter::update(const Vector &z) { Vector y = z - H * x; Matrix S = H * P * H.transpose() + R; - Matrix K = P * H.transpose() * S.inverse(); + Matrix K = P * H.transpose() * S.inverse1x1(); x = x + K * y; - Matrix I = Matrix::Identity(P.rows(), P.cols()); + Matrix I = Matrix::Identity(P.getRows()); P = (I - K * H) * P; } -Eigen::VectorXd KalmanFilter::getState() const +Matrix KalmanFilter::getState() const { return x; } diff --git a/lib/KalmanFilter.h b/lib/KalmanFilter.h index 8c0561b..1ba3eac 100644 --- a/lib/KalmanFilter.h +++ b/lib/KalmanFilter.h @@ -1,9 +1,8 @@ -#include +#include "Matrix.h" class KalmanFilter { public: - using Matrix = Eigen::MatrixXd; - using Vector = Eigen::VectorXd; + using Vector = Matrix; KalmanFilter(const Matrix& F, const Matrix& B, const Matrix& H, const Matrix& Q, const Matrix& R, const Matrix& P, diff --git a/lib/KalmanFilterR7.cpp b/lib/KalmanFilterR7.cpp index 0b71d66..77bd623 100644 --- a/lib/KalmanFilterR7.cpp +++ b/lib/KalmanFilterR7.cpp @@ -1,44 +1,28 @@ +#include #include "KalmanFilterR7.h" -KalmanFilterR7::KalmanFilterR7(float dt):KalmanFilter( - makeMatrix({{1, dt}, {0, 1}}), // F - macierz przejścia stanu - makeMatrix({{0},{dt}}), // B - macierz sterowania - makeMatrix({{1, 0}}), // H - macierz obserwacji - makeMatrix({{0.01, 0}, {0, 0.01}}), // Q - szum procesu - makeMatrix({{19}}), // R - szum pomiaru - Eigen::MatrixXd::Identity(2, 2), // P - kowariancja stanu - makeMatrix({{0},{0}}) // x - wektor stanu (pozycja, prędkość) - ){} - -Eigen::Vector2d KalmanFilterR7::processMeasurement(float acceleration, float pressure) +KalmanFilterR7::KalmanFilterR7(float dt) : KalmanFilter( + Matrix{{1.0f, dt}, {0.0f, 1.0f}}, // F - macierz przejścia stanu + Matrix{{0.0f}, {dt}}, // B - macierz sterowania + Matrix{{1.0f, 0.0f}}, // H - macierz obserwacji + Matrix{{0.01f, 0.0f}, {0.0f, 0.01f}}, // Q - szum procesu + Matrix{{19.0f}}, // R - szum pomiaru + Matrix::Identity(2), // P - kowariancja stanu (Identity na 1 argumencie) + Matrix{{0.0f}, {0.0f}} // x - wektor stanu (pozycja, prędkość) +) {} + +Matrix KalmanFilterR7::processMeasurement(float acceleration, float pressure) { - Eigen::VectorXd u(1); - u(0) = acceleration; + Matrix u(1, 1); + u(0,0) = acceleration; predict(u); - Eigen::VectorXd z(1); - z(0) = pressureToAltitude(pressure); + Matrix z(1,1); + z(0, 0) = static_cast(pressureToAltitude(pressure)); update(z); return getState(); } -Eigen::MatrixXd KalmanFilterR7::makeMatrix(std::initializer_list> list) { - size_t rows = list.size(); - size_t cols = list.begin()->size(); - - Eigen::MatrixXd m(rows, cols); - - size_t r = 0; - for (const auto& row : list) { - size_t c = 0; - for (double val : row) { - m(r, c) = val; - ++c; - } - ++r; - } - return m; -} double KalmanFilterR7::pressureToAltitude(double p) { const double p0 = 101325.0, // standardowe ciśnienie na poziomie morza (Pa) diff --git a/lib/KalmanFilterR7.h b/lib/KalmanFilterR7.h index c2580bd..0f27e42 100644 --- a/lib/KalmanFilterR7.h +++ b/lib/KalmanFilterR7.h @@ -1,14 +1,11 @@ -#include #include "KalmanFilter.h" class KalmanFilterR7 : public KalmanFilter { public: KalmanFilterR7(float dt); - Eigen::Vector2d processMeasurement(float acceleration, float pressure); - + Matrix processMeasurement(float acceleration, float pressure); private: - Eigen::MatrixXd makeMatrix(std::initializer_list> list); double pressureToAltitude(double p); using KalmanFilter::predict; using KalmanFilter::update; diff --git a/lib/Matrix.cpp b/lib/Matrix.cpp new file mode 100644 index 0000000..0834037 --- /dev/null +++ b/lib/Matrix.cpp @@ -0,0 +1,177 @@ +#include "Matrix.h" +#include +#include +#include + +Matrix::Matrix(std::initializer_list> list){ + rows = list.size(); + columns = list.begin()->size(); + for(const auto& row : list){ + if(row.size() != columns){ + throw std::invalid_argument("All rows in the matrix must have the same number of columns."); + } + } + + array = std::make_unique[]>(rows); + for (size_t i = 0; i < rows; ++i) { + array[i] = std::make_unique(columns); + } + + size_t r = 0; + for (const auto& row : list) { + size_t c = 0; + for (double val : row) { + array[r][c] = val; + ++c; + } + ++r; + } +} + +Matrix::Matrix(size_t rows, size_t columns) +{ + array = std::make_unique[]>(rows); + for (size_t r = 0; r < rows; ++r) { + array[r] = std::make_unique(columns); + for(size_t c = 0; c < columns; ++c){ + (*this)(r,c) = 0; + } + } + this->rows = rows; + this->columns = columns; +} + +Matrix::Matrix(const Matrix &other) : rows(other.getRows()), columns(other.getColumns()) +{ + array = std::make_unique[]>(rows); + for (size_t r = 0; r < rows; ++r) { + array[r] = std::make_unique(columns); + for(size_t c = 0; c < columns; ++c){ + (*this)(r,c) = other(r,c); + } + } +} + +Matrix Matrix::Identity(size_t size) +{ + Matrix m(size, size); + for (size_t i = 0; i < size; i++){ + m(i,i)= 1; + } + + return m; +} + +float& Matrix::operator ()(size_t r, size_t c) { + return array[r][c]; +} + +const float &Matrix::operator()(size_t r, size_t c) const +{ + return array[r][c]; +} + +Matrix Matrix::operator+(const Matrix &other) const +{ + if(rows != other.rows || columns != other.columns) + throw std::invalid_argument("Cannot add matrices: both matrices must have the same dimensions."); + Matrix result(rows, columns); + + for(size_t r = 0; r < rows; ++r){ + for(size_t c = 0; c < columns; ++c){ + result(r,c) = (*this)(r,c) + other(r,c); + } + } + + return result; +} + +Matrix Matrix::operator*(const Matrix &other) const +{ + if(columns != other.rows) + throw std::invalid_argument("Cannot multiply matrices: the number of columns in the first matrix must equal the number of rows in the second matrix."); + Matrix result(rows, other.columns); + + for (size_t r = 0; r < rows; ++r) { + for (size_t c = 0; c < other.columns; ++c) { + float sum = 0; + for (size_t k = 0; k < columns; ++k) { + sum += (*this)(r, k) * other(k, c); + } + result(r, c) = sum; + } + } + + return result; +} + +Matrix Matrix::operator-(const Matrix &other) const +{ + if(rows != other.rows || columns != other.columns) + throw std::invalid_argument("Cannot substract matrices: both matrices must have the same dimensions."); + Matrix result(rows, columns); + + for(size_t r = 0; r < rows; ++r){ + for(size_t c = 0; c < columns; ++c){ + result(r,c) = (*this)(r,c) - other(r,c); + } + } + + return result; +} + +Matrix &Matrix::operator=(Matrix &&other) +{ + rows = other.getRows(); + columns = other.getColumns(); + array = std::move(other.array); + return *this; +} + +Matrix Matrix::transpose() const +{ + Matrix result(columns, rows); + + for(size_t r = 0; r < rows; r++){ + for(size_t c = 0; c < columns; c++){ + result(c,r) = (*this)(r,c); + } + } + + return result; +} + +Matrix Matrix::inverse1x1() const +{ + Matrix result(1, 1); + result(0,0) = 1 / (*this)(0,0); + return result; +} + + + +size_t Matrix::getRows() const +{ + return rows; +} + +size_t Matrix::getColumns() const +{ + return columns; +} + +std::string Matrix::toString() const +{ + std::string str = ""; + for(size_t r=0; r < rows; r++){ + str += "|"; + for(size_t c=0; c < columns; c++){ + str += std::to_string(array[r][c]); + if(c!=columns-1) str += ", "; + } + str += "|\n"; + } + + + return str; +} diff --git a/lib/Matrix.h b/lib/Matrix.h new file mode 100644 index 0000000..140c879 --- /dev/null +++ b/lib/Matrix.h @@ -0,0 +1,29 @@ +#pragma once +#include +#include +#include + +class Matrix { +private: + size_t rows = 0; + size_t columns = 0; + std::unique_ptr[]> array; +public: + Matrix(std::initializer_list> list); + Matrix(size_t rows, size_t columns); + Matrix(const Matrix& other); + + static Matrix Identity(size_t size); + + float& operator ()(size_t r, size_t c); + const float& operator ()(size_t r, size_t c) const; + Matrix operator +(const Matrix& other) const; + Matrix operator *(const Matrix& other) const; + Matrix operator -(const Matrix& other) const; + Matrix& operator=(Matrix&&); + Matrix transpose() const; + Matrix inverse1x1() const; + size_t getRows() const; + size_t getColumns() const; + std::string toString() const; +}; \ No newline at end of file From 7d0cde7b6206c16009edaa060694697d92b219b1 Mon Sep 17 00:00:00 2001 From: Wiktor-Laska Date: Mon, 30 Mar 2026 14:14:01 +0200 Subject: [PATCH 2/3] =?UTF-8?q?dodanie=20obs=C5=82ugi=20zip?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitattributes | 1 + app/BUILD.bazel | 4 ++-- app/apogee_detector_test.cc | 40 +++++++++++++++++++++++++++++++++---- 3 files changed, 39 insertions(+), 6 deletions(-) create mode 100644 .gitattributes diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..1f2957e --- /dev/null +++ b/.gitattributes @@ -0,0 +1 @@ +data/**/*.csv filter=lfs diff=lfs merge=lfs -text diff --git a/app/BUILD.bazel b/app/BUILD.bazel index bb0c5bd..350e806 100644 --- a/app/BUILD.bazel +++ b/app/BUILD.bazel @@ -31,7 +31,7 @@ cc_test( deps = [ "@com_google_googletest//:gtest_main", "//lib:apogee_lib", + "@bazel_tools//tools/cpp/runfiles", # <--- DODANA BIBLIOTEKA ], - - data = ["//data:data_files"], + data = ["//data:data_files"], # To zostaje bez zmian ) \ No newline at end of file diff --git a/app/apogee_detector_test.cc b/app/apogee_detector_test.cc index 7da1257..039b928 100644 --- a/app/apogee_detector_test.cc +++ b/app/apogee_detector_test.cc @@ -5,22 +5,46 @@ #include #include #include +#include "tools/cpp/runfiles/runfiles.h" // <--- DODANY INCLUDE #include "lib/Matrix.h" #include "lib/KalmanFilterR7.h" #include "lib/ApogeeDetector.h" #include "lib/DataLoader.h" + +using bazel::tools::cpp::runfiles::Runfiles; // <--- DODANA PRZESTRZEŃ NAZW +namespace fs = std::filesystem; + namespace { static constexpr auto apoogeeError=0.15; } -namespace fs = std::filesystem; + +// Funkcja pomocnicza do pobierania bezpiecznej ścieżki +fs::path GetRunfilesPath(Runfiles* runfiles, const std::string& relative_path) { + // Bzlmod domyślnie nazywa główne repozytorium "_main" lub tak jak w MODULE.bazel ("bazel_apogeum") + std::string runfiles_path = "bazel_apogeum/" + relative_path; + fs::path resolved_path = runfiles->Rlocation(runfiles_path); + + // Fallback dla nowszych wersji Bazela, które mogą używać nazwy "_main" + if (!fs::exists(resolved_path)) { + runfiles_path = "_main/" + relative_path; + resolved_path = runfiles->Rlocation(runfiles_path); + } + return resolved_path; +} TEST(detect_test, test_apogee_detecotr) { - fs::path base_path = "data/10hz_1000m"; + // Inicjalizacja Runfiles + std::string error; + std::unique_ptr runfiles(Runfiles::CreateForTest(&error)); + ASSERT_NE(runfiles, nullptr) << "Nie udalo sie zainicjowac runfiles: " << error; + + fs::path base_path = GetRunfilesPath(runfiles.get(), "data/10hz_1000m"); fs::path barometerPath = base_path / "exported_barometer_data.csv"; fs::path accelerometerPath = base_path / "exported_accel_data.csv"; fs::path configPath = base_path / "config.txt"; + checkAndGenerateConfig(configPath); ConfigData config = readConfig(configPath); const double dt = config.hz > 0 ? 1.0 / config.hz : 0.1; @@ -45,12 +69,21 @@ TEST(detect_test, test_apogee_detecotr) { } EXPECT_NEAR(config.max_height_clean, height, 1.0); } + class ApogeeFlightDataTest : public ::testing::TestWithParam{}; + TEST_P(ApogeeFlightDataTest, CalculatesApogeeCorrectly){ - fs::path base_path = GetParam(); + // Inicjalizacja Runfiles + std::string error; + std::unique_ptr runfiles(Runfiles::CreateForTest(&error)); + ASSERT_NE(runfiles, nullptr) << "Nie udalo sie zainicjowac runfiles: " << error; + + fs::path base_path = GetRunfilesPath(runfiles.get(), GetParam()); + fs::path barometerPath = base_path / "exported_barometer_data.csv"; fs::path accelerometerPath = base_path / "exported_accel_data.csv"; fs::path configPath = base_path / "config.txt"; + checkAndGenerateConfig(configPath); ConfigData config = readConfig(configPath); const double dt = config.hz > 0 ? 1.0 / config.hz : 0.1; @@ -74,7 +107,6 @@ TEST_P(ApogeeFlightDataTest, CalculatesApogeeCorrectly){ } } EXPECT_NEAR(config.max_height_clean, height, config.max_height_clean*apoogeeError); - } INSTANTIATE_TEST_SUITE_P( From 5513f746f6361329dd9b983cc21dfb594a353714 Mon Sep 17 00:00:00 2001 From: Wiktor-Laska Date: Mon, 30 Mar 2026 14:43:49 +0200 Subject: [PATCH 3/3] =?UTF-8?q?-testy=20zippowanie=20dzia=C5=82aj=C4=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- MODULE.bazel | 24 ++++++++++++- app/BUILD.bazel | 4 +-- app/apogee_detector_test.cc | 68 +++++++++++++++++-------------------- data/BUILD.bazel | 8 +++++ 4 files changed, 64 insertions(+), 40 deletions(-) create mode 100644 data/BUILD.bazel diff --git a/MODULE.bazel b/MODULE.bazel index d71cddd..79c8617 100644 --- a/MODULE.bazel +++ b/MODULE.bazel @@ -5,4 +5,26 @@ module( bazel_dep(name = "eigen", version = "4.0.0-20241125.bcr.2") bazel_dep(name = "googletest", version = "1.17.0.bcr.2", repo_name = "com_google_googletest") -bazel_dep(name = "rules_cc", version = "0.0.17") \ No newline at end of file +bazel_dep(name = "rules_cc", version = "0.0.17") + +# Importujemy regułę do pobierania paczek +http_archive = use_repo_rule("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive") + +http_archive( + name = "moje_wielkie_dane", + url = "https://github.com/Simba-Avionic/srp-common/releases/download/v1.0/data.zip", + integrity = "sha256-1vPb5VyAvPpXCEAbIfftT7OJgjA9yYpdkZSrbALR3Jw=", + patch_cmds = [ + "rm -f data/BUILD.bazel data/BUILD", + ], + build_file_content = """ +filegroup( + name = "data_files", + srcs = glob([ + "**/*.csv", + "**/*.txt", + ]), + visibility = ["//visibility:public"], +) + """, +) \ No newline at end of file diff --git a/app/BUILD.bazel b/app/BUILD.bazel index 350e806..5266e58 100644 --- a/app/BUILD.bazel +++ b/app/BUILD.bazel @@ -31,7 +31,7 @@ cc_test( deps = [ "@com_google_googletest//:gtest_main", "//lib:apogee_lib", - "@bazel_tools//tools/cpp/runfiles", # <--- DODANA BIBLIOTEKA + "@bazel_tools//tools/cpp/runfiles", ], - data = ["//data:data_files"], # To zostaje bez zmian + data = ["@moje_wielkie_dane//:data_files"], ) \ No newline at end of file diff --git a/app/apogee_detector_test.cc b/app/apogee_detector_test.cc index 039b928..2f042e3 100644 --- a/app/apogee_detector_test.cc +++ b/app/apogee_detector_test.cc @@ -5,41 +5,26 @@ #include #include #include -#include "tools/cpp/runfiles/runfiles.h" // <--- DODANY INCLUDE +#include "tools/cpp/runfiles/runfiles.h" #include "lib/Matrix.h" #include "lib/KalmanFilterR7.h" #include "lib/ApogeeDetector.h" #include "lib/DataLoader.h" -using bazel::tools::cpp::runfiles::Runfiles; // <--- DODANA PRZESTRZEŃ NAZW +using bazel::tools::cpp::runfiles::Runfiles; namespace fs = std::filesystem; namespace { static constexpr auto apoogeeError=0.15; } -// Funkcja pomocnicza do pobierania bezpiecznej ścieżki -fs::path GetRunfilesPath(Runfiles* runfiles, const std::string& relative_path) { - // Bzlmod domyślnie nazywa główne repozytorium "_main" lub tak jak w MODULE.bazel ("bazel_apogeum") - std::string runfiles_path = "bazel_apogeum/" + relative_path; - fs::path resolved_path = runfiles->Rlocation(runfiles_path); - - // Fallback dla nowszych wersji Bazela, które mogą używać nazwy "_main" - if (!fs::exists(resolved_path)) { - runfiles_path = "_main/" + relative_path; - resolved_path = runfiles->Rlocation(runfiles_path); - } - return resolved_path; -} - TEST(detect_test, test_apogee_detecotr) { - // Inicjalizacja Runfiles std::string error; std::unique_ptr runfiles(Runfiles::CreateForTest(&error)); ASSERT_NE(runfiles, nullptr) << "Nie udalo sie zainicjowac runfiles: " << error; - fs::path base_path = GetRunfilesPath(runfiles.get(), "data/10hz_1000m"); + fs::path base_path = runfiles->Rlocation("moje_wielkie_dane/data/10hz_1000m"); fs::path barometerPath = base_path / "exported_barometer_data.csv"; fs::path accelerometerPath = base_path / "exported_accel_data.csv"; @@ -73,17 +58,25 @@ TEST(detect_test, test_apogee_detecotr) { class ApogeeFlightDataTest : public ::testing::TestWithParam{}; TEST_P(ApogeeFlightDataTest, CalculatesApogeeCorrectly){ - // Inicjalizacja Runfiles std::string error; std::unique_ptr runfiles(Runfiles::CreateForTest(&error)); ASSERT_NE(runfiles, nullptr) << "Nie udalo sie zainicjowac runfiles: " << error; - fs::path base_path = GetRunfilesPath(runfiles.get(), GetParam()); + std::string param = GetParam(); + if (param.find("data/") == std::string::npos) { + param = "data/" + param; + } + std::string path_in_zip = "moje_wielkie_dane/" + param; + fs::path base_path = runfiles->Rlocation(path_in_zip); fs::path barometerPath = base_path / "exported_barometer_data.csv"; fs::path accelerometerPath = base_path / "exported_accel_data.csv"; fs::path configPath = base_path / "config.txt"; + ASSERT_TRUE(fs::exists(configPath)) << "BRAK PLIKU: " << configPath; + ASSERT_TRUE(fs::exists(barometerPath)) << "BRAK PLIKU: " << barometerPath; + ASSERT_TRUE(fs::exists(accelerometerPath)) << "BRAK PLIKU: " << accelerometerPath; + checkAndGenerateConfig(configPath); ConfigData config = readConfig(configPath); const double dt = config.hz > 0 ? 1.0 / config.hz : 0.1; @@ -94,6 +87,8 @@ TEST_P(ApogeeFlightDataTest, CalculatesApogeeCorrectly){ std::vector accelData = readColumnCSV(accelerometerPath, 3); size_t dataSize = accelData.size(); + ASSERT_GT(dataSize, 0) << "Wczytano 0 wierszy z pliku CSV!"; + double height = 0.0; for (size_t i = 0; i < dataSize; ++i) { double accel = accelData[i]; @@ -106,27 +101,26 @@ TEST_P(ApogeeFlightDataTest, CalculatesApogeeCorrectly){ break; } } - EXPECT_NEAR(config.max_height_clean, height, config.max_height_clean*apoogeeError); + EXPECT_NEAR(config.max_height_clean, height, config.max_height_clean * apoogeeError); } - INSTANTIATE_TEST_SUITE_P( FlightDataSimulation, ApogeeFlightDataTest, ::testing::Values( - "data/10hz_1000m", - "data/10hz_2000m", - "data/10hz_4000m", - "data/10hz_5000m", - "data/10hz_6000m", - "data/100hz_1000m", - "data/100hz_2000m", - "data/100hz_3000m", - "data/100hz_4000m", - "data/100hz_5000m", - "data/100hz_6000m", - "data/1000hz_1000m", - "data/1000hz_2000m", - "data/1000hz_5000m", - "data/1000hz_6000m" + "10hz_1000m", + "10hz_2000m", + "10hz_4000m", + "10hz_5000m", + "10hz_6000m", + "100hz_1000m", + "100hz_2000m", + "100hz_3000m", + "100hz_4000m", + "100hz_5000m", + "100hz_6000m", + "1000hz_1000m", + "1000hz_2000m", + "1000hz_5000m", + "1000hz_6000m" ) ); \ No newline at end of file diff --git a/data/BUILD.bazel b/data/BUILD.bazel new file mode 100644 index 0000000..c01c0fa --- /dev/null +++ b/data/BUILD.bazel @@ -0,0 +1,8 @@ + filegroup( + name = "data_files", + srcs = glob([ + "**/*.csv", + "**/*.txt", + ]), + visibility = ["//visibility:public"], + ) \ No newline at end of file