diff --git a/.gitignore b/.gitignore index 9b89790f971bdc8817c9e536f0eccafcf4009da4..a9f1775b4bc49623280a7697bbb213db7e2b4b91 100644 --- a/.gitignore +++ b/.gitignore @@ -32,3 +32,5 @@ core __pycache__ /scripts/generators/generated /scripts/generators/scxmls + +scripts/logdecoder/logdecoder diff --git a/.vscode/c_cpp_properties.json b/.vscode/c_cpp_properties.json index 83c45bdd3c1959aa6fb9ff9bdc05e26e3bb9dac1..78209a5f4446e7dc5eaef63de2a9bf1202863192 100644 --- a/.vscode/c_cpp_properties.json +++ b/.vscode/c_cpp_properties.json @@ -24,6 +24,7 @@ "${workspaceFolder}/libs/mavlink_skyward_lib", "${workspaceFolder}/libs/fmt/include", "${workspaceFolder}/libs/eigen", + "${workspaceFolder}/libs/tscpp", "${workspaceFolder}/libs", "${workspaceFolder}/src/shared", "${workspaceFolder}/src/tests" @@ -77,6 +78,7 @@ "${workspaceFolder}/libs/mavlink_skyward_lib", "${workspaceFolder}/libs/fmt/include", "${workspaceFolder}/libs/eigen", + "${workspaceFolder}/libs/tscpp", "${workspaceFolder}/libs", "${workspaceFolder}/src/shared", "${workspaceFolder}/src/tests" @@ -129,6 +131,7 @@ "${workspaceFolder}/libs/mavlink_skyward_lib", "${workspaceFolder}/libs/fmt/include", "${workspaceFolder}/libs/eigen", + "${workspaceFolder}/libs/tscpp", "${workspaceFolder}/libs", "${workspaceFolder}/src/shared", "${workspaceFolder}/src/tests" diff --git a/.vscode/settings.json b/.vscode/settings.json index 4c48cde6bb08d87f0ba9e4ae3a02cc2dba7fe1df..eff44bf316fabcf0e68b244c992a0807d248dc96 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -124,6 +124,7 @@ "atthr", "AVDD", "Baro", + "Corigliano", "CORTEXM", "cpitch", "croll", @@ -135,8 +136,10 @@ "Ecompass", "Eigen", "elfs", + "Erbetta", "Fatt", "Fatttr", + "fedetft's", "fiprintf", "Gatttr", "getdetahstate", @@ -146,6 +149,8 @@ "GPIOC", "gpstr", "Hatt", + "HSCMAND", + "HSCMRNN", "irqv", "Kalman", "Katt", @@ -156,6 +161,7 @@ "MEKF", "MINC", "miosix", + "MPXHZ", "NATT", "NBAR", "NDTR", @@ -179,15 +185,21 @@ "sqdip", "sqtrp", "sroll", + "SSCDANN", + "SSCDRRN", + "stof", "syaw", "TCIE", "TEIE", "testsuite", + "TSCPP", + "Ublox", "upcounter", "velnord", "Xbee", "xnord", "yned" ], - "cSpell.language": "en,it" + "cSpell.language": "en,it", + "cSpell.enabled": true } diff --git a/libs/tscpp b/libs/tscpp index c8674a48e794c246f79c56b163ebab72d3654846..935bf1944e1ddeaf51fd22cdce04a2a97762890f 160000 --- a/libs/tscpp +++ b/libs/tscpp @@ -1 +1 @@ -Subproject commit c8674a48e794c246f79c56b163ebab72d3654846 +Subproject commit 935bf1944e1ddeaf51fd22cdce04a2a97762890f diff --git a/scripts/logdecoder/Makefile b/scripts/logdecoder/Makefile index 0a30ee85eaf9786bc68f52dcd335486e4766392e..2523965cd9ce3b7e20457d7d5c1f047d90386c7c 100644 --- a/scripts/logdecoder/Makefile +++ b/scripts/logdecoder/Makefile @@ -1,6 +1,12 @@ +BOARDCORE := ../../ all: - g++ -std=c++11 -O2 -o logdecoder logdecoder.cpp ../libs/tscpp/stream.cpp -I ../libs - + g++ -std=c++17 -O2 -o logdecoder logdecoder.cpp \ + -DCOMPILE_FOR_X86 \ + $(BOARDCORE)libs/tscpp/tscpp/stream.cpp \ + -I$(BOARDCORE)libs/mavlink_skyward_lib \ + -I$(BOARDCORE)libs/eigen \ + -I$(BOARDCORE)libs/tscpp \ + -I$(BOARDCORE)src/shared clean: rm logdecoder diff --git a/scripts/logdecoder/logdecoder.cpp b/scripts/logdecoder/logdecoder.cpp index 96b81e338727137ff3d25d077d1c56891226fd15..670873a182784e3a882b1649fb48e69502e3b164 100644 --- a/scripts/logdecoder/logdecoder.cpp +++ b/scripts/logdecoder/logdecoder.cpp @@ -1,59 +1,139 @@ -/*************************************************************************** - * Copyright (C) 2018 by Terraneo Federico * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * As a special exception, if other files instantiate templates or use * - * macros or inline functions from this file, or you compile this file * - * and link it with other works to produce a work based on this file, * - * this file does not by itself cause the resulting work to be covered * - * by the GNU General Public License. However the source code for this * - * file must still be made available in accordance with the GNU General * - * Public License. This exception does not invalidate any other reasons * - * why a work based on this file might be covered by the GNU General * - * Public License. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program; if not, see <http://www.gnu.org/licenses/> * - ***************************************************************************/ - -/* - * This is a stub program for the program that will decode the logged data. - * Fill in the TODO to make it work. +/* Copyright (c) 2018-2022 Skyward Experimental Rocketry + * Authors: Terrane Federico + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. */ -#include <iostream> +#include <logger/Deserializer.h> +#include <logger/LogTypes.h> +#include <tscpp/stream.h> + #include <fstream> +#include <iostream> #include <stdexcept> -#include <tscpp/stream.h> +#include <string> -//TODO: add here include files of serialized classes -#include "../src/shared/logger/LogStats.h" -#include "../src/entrypoints/test_logger.h" +/** + * @brief Binary log files decoder. + * + * This program is to compile for you computer and decodes binary log files + * through the tscpp library. + * + * In LogTypes.h there should be included all the classes you want to + * deserialize. + */ -using namespace std; using namespace tscpp; +using namespace Boardcore; + +void showUsage(string commandName); + +/** + * @brief Deserialize a file. + * + * @param fileName File name complete with extension. + * @return Whether the deserialization was successful. + */ +bool deserialize(string fileName); + +/** + * @brief Deserialize all log file in the directory. Assumes the log files named + * as logXX.dat. + * + * Scans for all the 100 possible log files and decode the ones found. + * + * @return False if an error was encountered. + */ +bool deserializeAll(); + +int main(int argc, char* argv[]) +{ + if (argc < 2) + { + showUsage(string(argv[0])); + return 1; // Error + } + + bool success = false; + string arg1 = string(argv[1]); + + // Help message + if (arg1 == "-h" || arg1 == "--help") + { + showUsage(string(argv[0])); + return 0; + } -int main(int argc, char *argv[]) -try { - TypePoolStream tp; - //TODO: Register the serialized classes - tp.registerType<LogStats>([](LogStats& t){ t.print(cout); cout<<'\n'; }); - tp.registerType<Dummy>([](Dummy& t){ t.print(cout); cout<<'\n'; }); - - if(argc!=2) return 1; - ifstream in(argv[1]); - in.exceptions(ios::eofbit); - UnknownInputArchive ia(in,tp); - for(;;) ia.unserialize(); -} catch(exception&) { + // File deserialization + if (arg1 == "-a" || arg1 == "--all") + success = deserializeAll(); + else + success = deserialize(arg1); + + // End + if (success) + std::cout << "Deserialization completed successfully\n"; + else + std::cout << "Deserialization ended with errors\n"; return 0; } + +void showUsage(string commandName) +{ + std::cerr << "Usage: " << commandName << " {-a | <log_file_name> | -h}" + << "Options:\n" + << "\t-h,--help\t\tShow this help message\n" + << "\t-a,--all Deserialize all logs in the current directory " + "named as logXX.dat\n" + << std::endl; +} + +bool deserialize(string fileName) +{ + std::cout << "Deserializing " << fileName << "...\n"; + + Deserializer d(fileName); + LogTypes::registerTypes(d); + + return d.deserialize(); +} + +bool deserializeAll() +{ + std::cout << "Deserializing all logs in the current directory...\n"; + + for (int i = 0; i < 100; i++) + { + char fileName[11]; + sprintf(fileName, "log%02d.dat", i); + struct stat st; + + // Check if the current logfile exists + if (stat(fileName, &st) != 0) + continue; + + // File found + if (!deserialize(string(fileName))) + return false; + + std::cout << fileName << " deserialized successfully"; + } + + return true; +} diff --git a/scripts/logdecoder/sample_no_cereal.dat.dat b/scripts/logdecoder/sample_no_cereal.dat.dat deleted file mode 100644 index 23dff819fee59674f0cfff237b94fffa191d4a06..0000000000000000000000000000000000000000 Binary files a/scripts/logdecoder/sample_no_cereal.dat.dat and /dev/null differ diff --git a/scripts/logdecoder/xbee/.gitignore b/scripts/logdecoder/xbee/.gitignore deleted file mode 100644 index 3e6fd163051d66dceb9c808d07e314ae4d022ee5..0000000000000000000000000000000000000000 --- a/scripts/logdecoder/xbee/.gitignore +++ /dev/null @@ -1 +0,0 @@ -logdecoder diff --git a/scripts/logdecoder/xbee/LogTypes.h b/scripts/logdecoder/xbee/LogTypes.h deleted file mode 100644 index cb82189b489a302f28b3f62dfd61fec88c1326b7..0000000000000000000000000000000000000000 --- a/scripts/logdecoder/xbee/LogTypes.h +++ /dev/null @@ -1,73 +0,0 @@ -/* Copyright (c) 2015-2018 Skyward Experimental Rocketry - * Author: Luca Erbetta - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#pragma once - -#include <logger/Deserializer.h> -#include <logger/LogStats.h> -#include <radio/Xbee/APIFramesLog.h> -#include <radio/Xbee/Mark.h> -#include <radio/Xbee/XbeeStatus.h> -#include <radio/Xbee/XbeeTestData.h> - -#include <fstream> -#include <iostream> - -// Serialized classes -using std::ofstream; - -namespace Boardcore -{ - -template <typename T> -void print(T& t, ostream& os) -{ - t.print(os); -} - -template <typename T> -void registerType(Deserializer& ds) -{ - ds.registerType<T>(print<T>, T::header()); -} - -void registerTypes(Deserializer& ds) -{ - registerType<LogStats>(ds); - - registerType<Xbee::APIFrameLog>(ds); - registerType<Xbee::ATCommandFrameLog>(ds); - registerType<Xbee::ATCommandResponseFrameLog>(ds); - registerType<Xbee::ModemStatusFrameLog>(ds); - registerType<Xbee::TXRequestFrameLog>(ds); - registerType<Xbee::TXStatusFrameLog>(ds); - registerType<Xbee::RXPacketFrameLog>(ds); - registerType<Xbee::XbeeStatus>(ds); - - registerType<TxData>(ds); - registerType<RxData>(ds); - registerType<Mark>(ds); - registerType<XbeeConfig>(ds); - registerType<EnergyScanData>(ds); -} - -} // namespace Boardcore diff --git a/scripts/logdecoder/xbee/Makefile b/scripts/logdecoder/xbee/Makefile deleted file mode 100644 index 47258b629723d159885432ac1e485023f5d40002..0000000000000000000000000000000000000000 --- a/scripts/logdecoder/xbee/Makefile +++ /dev/null @@ -1,13 +0,0 @@ -BASE := ../../../../../ - -all: - g++ -std=c++17 -O2 -o logdecoder logdecoder.cpp \ - -DCOMPILE_FOR_X86 \ - $(BASE)libs/tscpp/stream.cpp \ - -I$(BASE)src/shared \ - -I$(BASE)src/tests \ - -I$(BASE)libs \ - -I$(BASE)libs/miosix-kernel/miosix - -clean: - rm logdecoder diff --git a/scripts/logdecoder/xbee/logdecoder.cpp b/scripts/logdecoder/xbee/logdecoder.cpp deleted file mode 100644 index 40577eef2088983028f356bb13b341f97641ed3d..0000000000000000000000000000000000000000 --- a/scripts/logdecoder/xbee/logdecoder.cpp +++ /dev/null @@ -1,168 +0,0 @@ -/* Copyright (c) 2018 Skyward Experimental Rocketry - * Author: Federico Terraneo - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -/* - * This is a stub program for the program that will decode the logged data. - * You must first define a function - * "void registerTypes(Deserializer& ds);" - * - * that registers all the required log data types in the deserializer and then - * INCLUDE this cpp file in your source. finally compile and run - */ - -#include <sys/stat.h> -#include <sys/types.h> -#include <tscpp/stream.h> - -#include <filesystem> -#include <fstream> -#include <iostream> -#include <stdexcept> -#include <string> -#include <vector> - -#include "LogTypes.h" - -using namespace std; -using namespace tscpp; - -namespace fs = filesystem; - -void showHelp(string cmdName) -{ - std::cerr << "Usage: " << cmdName - << " {-a [logs_diretory] | <log_file_path> | -h}" - << "Options:\n" - << "\t-h,--help\t\tShow help message\n" - << "\t-a,--all [dir=\".\"] Deserialize all logs in the provided " - "directory\n" - << std::endl; -} - -vector<fs::path> listLogFiles(fs::path dir) -{ - vector<fs::path> out; - for (const auto& entry : fs::directory_iterator(dir)) - { - if (entry.exists() && entry.is_regular_file()) - { - if (entry.path().extension() == ".dat") - { - out.push_back(entry.path()); - } - } - } - return out; -} - -bool deserialize(fs::path log_path) -{ - cout << "Deserializing " << log_path << ".dat...\n"; - - // remove extension - log_path.replace_extension(""); - Deserializer d(log_path); - registerTypes(d); - - return d.deserialize(); -} - -bool deserializeAll(fs::path dir = ".") -{ - vector<fs::path> logs = listLogFiles(dir); - for (auto log : logs) - { - if (!deserialize(log.string())) - { - return false; - } - } - - return true; -} - -int main(int argc, char* argv[]) -{ - if (argc < 2) - { - showHelp(string(argv[0])); - return 1; - } - - bool success = false; - string arg1 = string(argv[1]); - if (arg1 == "-h" || arg1 == "--help") - { - showHelp(string(argv[0])); - return 0; - } - - if (arg1 == "-a" || arg1 == "--all") - { - fs::path dir = "."; - if (argc == 3) - { - string arg2 = string(argv[2]); - fs::directory_entry entry(arg2); - if (entry.exists() && entry.is_directory()) - { - dir = arg2; - } - else - { - cout << "Second argument after '-a' or '--all' must be a " - "directory\n"; - showHelp(string(argv[0])); - return 1; - } - } - cout << "Deserializing all logs...\n"; - success = deserializeAll(dir); - } - else if (arg1[0] == '-') - { - cerr << "Unknown option\n"; - return 1; - } - else - { - fs::directory_entry entry(arg1); - if (entry.exists() && entry.is_regular_file()) - { - success = deserialize(arg1); - } - else - { - showHelp(string(argv[0])); - return 1; - } - } - - if (success) - { - cout << "Deserialization completed successfully.\n"; - } - else - { - cout << "Deserialization ended with errors.\n"; - } -} diff --git a/src/shared/logger/Deserializer.h b/src/shared/logger/Deserializer.h index 63bdfbe53bec423e99ff24544062da452b0adba7..e0382dffcaec69b821faa0b7f28b81f0095c0a4a 100644 --- a/src/shared/logger/Deserializer.h +++ b/src/shared/logger/Deserializer.h @@ -27,6 +27,7 @@ #include <cstdio> #include <fstream> +#include <iostream> #include <limits> #include <ostream> #include <string> @@ -51,151 +52,155 @@ typedef std::numeric_limits<float> flt; class Deserializer { public: - Deserializer(std::string logfile, std::string prefix = "") - : prefix(prefix), logFile(logfile), - logFileWithExt(prefix + logFile + ".dat") - { - } + Deserializer(std::string fileName); - ~Deserializer() - { - if (!closed) - { - for (auto it = fileStreams.begin(); it != fileStreams.end(); it++) - { - (*it)->close(); - delete *it; - } - } - } + ~Deserializer(); /** - * Register a type to be deserialized, and the associated print function + * Register a type to be deserialized, and the associated print function. * - * @param t the object to be deserialized - * @param fncPrint function that prints the deserialized data on the + * @param t The object to be deserialized. + * @param fncPrint Function that prints the deserialized data on the * provided output stream. + * @param header Optional CSV header text. */ template <typename T> bool registerType(std::function<void(T& t, std::ostream& os)> fncPrint, - std::string header = "") - { - if (closed) - { - printf("Error: Deserializer is closed.\n"); - return false; - } + std::string header = ""); - char cFilename[128]; - sprintf(cFilename, "%s%s_%s.csv", prefix.c_str(), logFile.c_str(), - typeid(T).name()); + /** + * @brief Deserializes the provided file. + * + * @return Whether the deserialization was successful. + */ + bool deserialize(); - std::string filename(cFilename); + void close(); - std::ofstream* stream = new std::ofstream(); - stream->open(filename); +private: + bool closed = false; - if (!stream->is_open()) - { - printf("Error opening file %s.\n", filename.c_str()); - perror("Error is:"); - delete stream; - return false; - } + std::vector<std::ofstream*> fileStreams; + tscpp::TypePoolStream tps; + + std::string fileName; +}; + +Deserializer::Deserializer(std::string fileName) : fileName(fileName) {} - fileStreams.push_back(stream); - stream->precision(flt::max_digits10); // Set stream precision to - // maximum float precision - // Print the header - if (header.length() > 0) +Deserializer::~Deserializer() +{ + if (!closed) + for (auto it = fileStreams.begin(); it != fileStreams.end(); it++) { - *stream << header; + (*it)->close(); + delete *it; } +} - using namespace std::placeholders; // for _1 +template <typename T> +bool Deserializer::registerType( + std::function<void(T& t, std::ostream& os)> fncPrint, std::string header) +{ + if (closed) + { + printf("Error: Deserializer is closed.\n"); + return false; + } - std::function<void(T & t)> callback = - std::bind(fncPrint, _1, std::ref(*stream)); + char cFilename[128]; + sprintf(cFilename, "%s_%s.csv", fileName.c_str(), typeid(T).name()); - tps.registerType<T>(callback); + std::string filename(cFilename); - return true; + std::ofstream* stream = new std::ofstream(); + stream->open(filename); + + if (!stream->is_open()) + { + printf("Error opening file %s.\n", filename.c_str()); + perror("Error is:"); + delete stream; + return false; } - /** - * @brief Deserializes the provided file. - * - * @return Wheter the deserialization was successful. - */ - bool deserialize() + fileStreams.push_back(stream); + stream->precision(flt::max_digits10); // Set stream precision to + // maximum float precision + // Print the header + if (header.length() > 0) { - if (closed) - { - return false; - } + *stream << header; + } + + using namespace std::placeholders; // for _1 + + std::function<void(T & t)> callback = + std::bind(fncPrint, _1, std::ref(*stream)); - bool success = true; - std::string unknownTypeName; + tps.registerType<T>(callback); + + return true; +} + +bool Deserializer::deserialize() +{ + if (closed) + return false; + + bool success = true; + std::string unknownTypeName; + + std::ifstream file(fileName); + + // Check if the file exists + if (!file) + { + std::cout << fileName << " does not exists." << std::endl; + return false; + } - struct stat st; - if (stat(logFileWithExt.c_str(), &st) != 0) + tscpp::UnknownInputArchive ia(file, tps); + int i = 0; + while (success) + { + try { - printf("File %s does not exists.\n", logFileWithExt.c_str()); - return false; + ia.unserialize(); } - - std::ifstream file(logFileWithExt); - // file.open; - tscpp::UnknownInputArchive ia(file, tps); - int i = 0; - while (success) + catch (tscpp::TscppException& ex) { - try + // Reached end of file + if (strcmp(ex.what(), "eof") == 0) { - ia.unserialize(); + break; } - catch (tscpp::TscppException& ex) + else if (strcmp(ex.what(), "unknown type") == 0) { - // Reached end of file - if (strcmp(ex.what(), "eof") == 0) - { - break; - } - else if (strcmp(ex.what(), "unknown type") == 0) - { - unknownTypeName = ex.name(); - success = false; - printf("Unknown type found: %s\n", unknownTypeName.c_str()); - break; - } + unknownTypeName = ex.name(); + success = false; + std::cout << "Unknown type found: " << unknownTypeName + << std::endl; + break; } } - file.close(); - return success; } - void close() + file.close(); + return success; +} + +void Deserializer::close() +{ + if (!closed) { - if (!closed) + closed = true; + for (auto it = fileStreams.begin(); it != fileStreams.end(); it++) { - closed = true; - for (auto it = fileStreams.begin(); it != fileStreams.end(); it++) - { - (*it)->close(); - delete *it; - } + (*it)->close(); + delete *it; } } - -private: - bool closed = false; - - std::vector<std::ofstream*> fileStreams; - tscpp::TypePoolStream tps; - - std::string prefix; - std::string logFile; - std::string logFileWithExt; -}; +} } // namespace Boardcore diff --git a/src/shared/logger/LogTypes.h b/src/shared/logger/LogTypes.h new file mode 100644 index 0000000000000000000000000000000000000000..3863ea5d5c79f735c181c347a3a6ab8ab9e1dcbc --- /dev/null +++ b/src/shared/logger/LogTypes.h @@ -0,0 +1,125 @@ +/* Copyright (c) 2015-2022 Skyward Experimental Rocketry + * Author: Luca Erbetta, Alberto Nidasio + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#pragma once + +#include <algorithms/ExtendedKalman/ExtendedKalmanState.h> +#include <diagnostic/PrintLoggerData.h> +#include <drivers/adc/InternalADCData.h> +#include <events/EventData.h> +#include <logger/Deserializer.h> +#include <logger/LoggerStats.h> +#include <radio/MavlinkDriver/MavlinkStatus.h> +#include <radio/Xbee/XbeeStatus.h> +#include <scheduler/TaskSchedulerData.h> +#include <sensors/ADS1118/ADS1118Data.h> +#include <sensors/ADS131M04/ADS131M04Data.h> +#include <sensors/BME280/BME280Data.h> +#include <sensors/BMP280/BMP280Data.h> +#include <sensors/BMX160/BMX160Data.h> +#include <sensors/BMX160/BMX160WithCorrectionData.h> +#include <sensors/HX711/HX711Data.h> +#include <sensors/L3GD20/L3GD20Data.h> +#include <sensors/LIS3DSH/LIS3DSHData.h> +#include <sensors/LIS3MDL/LIS3MDLData.h> +#include <sensors/MBLoadCell/MBLoadCellData.h> +#include <sensors/MPU9250/MPU9250Data.h> +#include <sensors/MS5803/MS5803Data.h> +#include <sensors/SensorData.h> +#include <sensors/UbloxGPS/UbloxGPSData.h> +#include <sensors/VN100/VN100Data.h> +#include <sensors/analog/battery/BatteryVoltageSensorData.h> +#include <sensors/analog/current/CurrentSensorData.h> +#include <sensors/analog/pressure/MPXHZ6130A/MPXHZ6130AData.h> +#include <sensors/analog/pressure/honeywell/HSCMAND015PAData.h> +#include <sensors/analog/pressure/honeywell/HSCMRNN030PAData.h> +#include <sensors/analog/pressure/honeywell/HSCMRNN160KAData.h> +#include <sensors/analog/pressure/honeywell/SSCDANN030PAAData.h> +#include <sensors/analog/pressure/honeywell/SSCDRRN015PDAData.h> + +#include <fstream> +#include <iostream> + +/** + * @brief This file includes all the types the logdecoder script will decode. + * + * All logged classes inside Boardcore should be reported here. + */ + +namespace Boardcore +{ + +namespace LogTypes +{ + +template <typename T> +void print(T& t, std::ostream& os) +{ + t.print(os); +} + +template <typename T> +void registerType(Deserializer& ds) +{ + ds.registerType<T>(print<T>, T::header()); +} + +void registerTypes(Deserializer& ds) +{ + registerType<ExtendedKalmanState>(ds); + registerType<LoggingString>(ds); + registerType<InternalADCData>(ds); + registerType<EventData>(ds); + registerType<LoggerStats>(ds); + registerType<MavlinkStatus>(ds); + registerType<Xbee::XbeeStatus>(ds); + registerType<TaskStatsResult>(ds); + registerType<ADS1118Data>(ds); + registerType<ADS131M04Data>(ds); + registerType<BME280Data>(ds); + registerType<BMP280Data>(ds); + registerType<BMX160Data>(ds); + registerType<BMX160WithCorrectionData>(ds); + registerType<HX711Data>(ds); + registerType<L3GD20Data>(ds); + registerType<LIS3DSHData>(ds); + registerType<LIS3MDLData>(ds); + registerType<MBLoadCellData>(ds); + registerType<MPU9250Data>(ds); + registerType<MS5803Data>(ds); + registerType<TemperatureData>(ds); + registerType<UbloxGPSData>(ds); + registerType<VN100Data>(ds); + registerType<BatteryVoltageSensorData>(ds); + registerType<CurrentSensorData>(ds); + registerType<LoadCellData>(ds); + registerType<MPXHZ6130AData>(ds); + registerType<HSCMAND015PAData>(ds); + registerType<HSCMRNN030PAData>(ds); + registerType<HSCMRNN160KAData>(ds); + registerType<SSCDANN030PAAData>(ds); + registerType<SSCDRRN015PDAData>(ds); +} + +} // namespace LogTypes + +} // namespace Boardcore diff --git a/src/shared/sensors/HX711/HX711Data.h b/src/shared/sensors/HX711/HX711Data.h index 6d4f4940229b86fd157f6b4b133ee6b7ec8c9d14..49e25db1942c56331a90e9bbe6cd29f21741607d 100644 --- a/src/shared/sensors/HX711/HX711Data.h +++ b/src/shared/sensors/HX711/HX711Data.h @@ -32,17 +32,17 @@ struct HX711Data : public LoadCellData { HX711Data() : LoadCellData{0, 0} {} - HX711Data(uint64_t weightTimestamp, float weight) - : LoadCellData{weightTimestamp, weight} + HX711Data(uint64_t loadTimestamp, float load) + : LoadCellData{loadTimestamp, load} { } - static std::string header() { return "weightTimestamp,weight\n"; } + static std::string header() { return "loadTimestamp,load\n"; } void print(std::ostream& os) const { - os << weightTimestamp << "," << weight << "\n"; + os << loadTimestamp << "," << load << "\n"; } }; -} // namespace Boardcore \ No newline at end of file +} // namespace Boardcore diff --git a/src/shared/sensors/MBLoadCell/MBLoadCell.cpp b/src/shared/sensors/MBLoadCell/MBLoadCell.cpp index 1874fff78cb19a8b22ff69cefb07e4c1462c9bb2..4e2a6fa7cf780bcdf8aa4e193700578bc6120595 100644 --- a/src/shared/sensors/MBLoadCell/MBLoadCell.cpp +++ b/src/shared/sensors/MBLoadCell/MBLoadCell.cpp @@ -165,15 +165,15 @@ void MBLoadCell::printData() } } -Data MBLoadCell::getMaxWeight() { return maxWeight; } +MBLoadCellData MBLoadCell::getMaxWeight() { return maxWeight; } -Data MBLoadCell::getMinWeight() { return minWeight; } +MBLoadCellData MBLoadCell::getMinWeight() { return minWeight; } bool MBLoadCell::selfTest() { return true; } -Data MBLoadCell::sampleImpl() +MBLoadCellData MBLoadCell::sampleImpl() { - Data value; + MBLoadCellData value; switch (settings.mode) { case LoadCellModes::CONT_MOD_T: @@ -217,23 +217,23 @@ Data MBLoadCell::sampleImpl() return value; } -Data MBLoadCell::sampleContModT() +MBLoadCellData MBLoadCell::sampleContModT() { DataModT data; receive(&data); - return Data(atof(data.weight) / 10.0); + return MBLoadCellData(atof(data.weight) / 10.0); } -Data MBLoadCell::sampleContModTd() +MBLoadCellData MBLoadCell::sampleContModTd() { DataModTd data; receive(&data); - return Data(atof(data.weightT) / 10.0); + return MBLoadCellData(atof(data.weightT) / 10.0); } -Data MBLoadCell::sampleAsciiModTd() +MBLoadCellData MBLoadCell::sampleAsciiModTd() { DataAsciiRequest request; @@ -262,7 +262,7 @@ Data MBLoadCell::sampleAsciiModTd() else { // Taking the value returned - return Data(stof(response.substr(3, 6)) / 10.0); + return MBLoadCellData(stof(response.substr(3, 6)) / 10.0); } } diff --git a/src/shared/sensors/MBLoadCell/MBLoadCell.h b/src/shared/sensors/MBLoadCell/MBLoadCell.h index aefe3c6808653ca2ca93abd0742feae5d8f23273..d8e57f5f65bdded510a9ad6830bed13d1c053106 100644 --- a/src/shared/sensors/MBLoadCell/MBLoadCell.h +++ b/src/shared/sensors/MBLoadCell/MBLoadCell.h @@ -47,7 +47,7 @@ namespace Boardcore * - ASCII-modTd: bidirectional mode that consists in sending a request and * receiving a response with the data requested or an error message */ -class MBLoadCell : public Sensor<Data> +class MBLoadCell : public Sensor<MBLoadCellData> { public: /** @@ -86,12 +86,12 @@ public: /** * @brief Returns a copy of the max weight detected. */ - Data getMaxWeight(); + MBLoadCellData getMaxWeight(); /** * @brief Returns a copy of the min weight detected. */ - Data getMinWeight(); + MBLoadCellData getMinWeight(); bool selfTest() override; @@ -102,22 +102,22 @@ protected: * * @return The weight measured from the load cell. */ - Data sampleImpl() override; + MBLoadCellData sampleImpl() override; /** * @brief Sampling in the "continuous Mod T" mode. */ - Data sampleContModT(void); + MBLoadCellData sampleContModT(void); /** * @brief Sampling in the "continuous Mod Td" mode. */ - Data sampleContModTd(void); + MBLoadCellData sampleContModTd(void); /** * @brief Sampling in the "ASCII Mod Td" mode. */ - Data sampleAsciiModTd(void); + MBLoadCellData sampleAsciiModTd(void); /** * @brief Forges a request for the ascii mode. @@ -158,8 +158,8 @@ protected: private: MBLoadCellSettings settings; ///< Contains all the configuration - Data maxWeight; ///< Maximum weight detected by the load cell - Data minWeight; ///< Minimum weight detected by the load cell + MBLoadCellData maxWeight; ///< Maximum weight detected by the load cell + MBLoadCellData minWeight; ///< Minimum weight detected by the load cell bool maxSetted; bool maxPrint; bool minSetted; diff --git a/src/shared/sensors/MBLoadCell/MBLoadCellData.h b/src/shared/sensors/MBLoadCell/MBLoadCellData.h index c576fa20e15f691d11f8a060e6545f449c786310..3c9c12495040743ac5dc2bfd0a7647f62115ee94 100644 --- a/src/shared/sensors/MBLoadCell/MBLoadCellData.h +++ b/src/shared/sensors/MBLoadCell/MBLoadCellData.h @@ -22,9 +22,9 @@ #pragma once -#include <drivers/timer/TimestampTimer.h> #include <utils/Debug.h> +#include <cstdio> #include <map> #include "sensors/SensorData.h" @@ -87,24 +87,25 @@ enum ReturnsStates * @brief Structure that stores a data value, with his timestamp and his * validity. */ -struct Data : public LoadCellData +struct MBLoadCellData : public LoadCellData { bool valid = false; - Data() : LoadCellData{0, 0.0}, valid(false) {} + MBLoadCellData() : LoadCellData{0, 0.0}, valid(false) {} - explicit Data(float data) - : LoadCellData{TimestampTimer::getInstance().getTimestamp(), data}, - valid(true) + explicit MBLoadCellData(float data) : MBLoadCellData{0, data} {} + + explicit MBLoadCellData(uint64_t loadTimestamp, float data) + : LoadCellData{loadTimestamp, data}, valid(true) { } - static std::string header() { return "weightTimestamp,weight\n"; } + static std::string header() { return "loadTimestamp,weight\n"; } void print(std::ostream& os) const { if (valid) - os << weightTimestamp / 1000000.0 << "," << weight << "\n"; + os << loadTimestamp / 1000000.0 << "," << load << "\n"; } }; @@ -115,10 +116,10 @@ struct MBLoadCellSettings { LoadCellModes mode; bool grossMode; - Data peakWeight; - Data setpoint1; - Data setpoint2; - Data setpoint3; + MBLoadCellData peakWeight; + MBLoadCellData setpoint1; + MBLoadCellData setpoint2; + MBLoadCellData setpoint3; /** * @brief Updates the correct value with the data passed. Also, memorizes @@ -129,16 +130,16 @@ struct MBLoadCellSettings switch (val) { case PEAK_WEIGHT: - peakWeight = Data(data); + peakWeight = MBLoadCellData(data); break; case GET_SETPOINT_1: - setpoint1 = Data(data); + setpoint1 = MBLoadCellData(data); break; case GET_SETPOINT_2: - setpoint2 = Data(data); + setpoint2 = MBLoadCellData(data); break; case GET_SETPOINT_3: - setpoint3 = Data(data); + setpoint3 = MBLoadCellData(data); break; default: break; @@ -151,22 +152,22 @@ struct MBLoadCellSettings void print() const { /*if (netWeight.valid) - TRACE("Net Weight : %f [Kg]\n", netWeight.data); + TRACE("Net Weight : %f [Kg]\n", netWeight.load); if (grossWeight.valid) - TRACE("Gross Weight : %f [Kg]\n", grossWeight.data); + TRACE("Gross Weight : %f [Kg]\n", grossWeight.load); */ if (peakWeight.valid) - TRACE("Peak Weight : %f [Kg]\n", peakWeight.weight); + TRACE("Peak Weight : %f [Kg]\n", peakWeight.load); if (setpoint1.valid) - TRACE("Setpoint 1 : %f [Kg]\n", setpoint1.weight); + TRACE("Setpoint 1 : %f [Kg]\n", setpoint1.load); if (setpoint2.valid) - TRACE("Setpoint 2 : %f [Kg]\n", setpoint2.weight); + TRACE("Setpoint 2 : %f [Kg]\n", setpoint2.load); if (setpoint3.valid) - TRACE("Setpoint 3 : %f [Kg]\n", setpoint3.weight); + TRACE("Setpoint 3 : %f [Kg]\n", setpoint3.load); } }; @@ -223,7 +224,7 @@ struct DataAsciiRequest checksum ^= str[i]; } - itoa(checksum, ck, 16); + sprintf(ck, "%x", checksum); } /** diff --git a/src/shared/sensors/SensorData.h b/src/shared/sensors/SensorData.h index f4aeb4e642155d38e0054796e840b77bd30d0d36..b945640e9cb8a5f31a888361469c8db7b9a11801 100644 --- a/src/shared/sensors/SensorData.h +++ b/src/shared/sensors/SensorData.h @@ -56,8 +56,16 @@ struct TimestampData struct LoadCellData { - uint64_t weightTimestamp; - float weight; + uint64_t loadTimestamp; + float voltage; + float load; + + static std::string header() { return "loadTimestamp,voltage,load\n"; } + + void print(std::ostream& os) const + { + os << loadTimestamp << "," << voltage << "," << load << "\n"; + } }; struct TemperatureData diff --git a/src/shared/sensors/analog/loadcell/LoadCell.h b/src/shared/sensors/analog/loadcell/LoadCell.h index 76d678ce2304542247fb0fa57b33aed73972ff4d..ac36f900faf2f98ce613bf3ff3cd94924745f0d4 100644 --- a/src/shared/sensors/analog/loadcell/LoadCell.h +++ b/src/shared/sensors/analog/loadcell/LoadCell.h @@ -26,8 +26,6 @@ #include <functional> -#include "LoadCellData.h" - namespace Boardcore { @@ -50,7 +48,7 @@ public: { LoadCellData data; - std::tie(data.timestamp, data.voltage) = getVoltage(); + std::tie(data.loadTimestamp, data.voltage) = getVoltage(); data.load = data.voltage / conversionCoeff; diff --git a/src/shared/sensors/analog/loadcell/LoadCellData.h b/src/shared/sensors/analog/loadcell/LoadCellData.h deleted file mode 100644 index 665ae93111656de0f1c756d2a4003d27093fd1fc..0000000000000000000000000000000000000000 --- a/src/shared/sensors/analog/loadcell/LoadCellData.h +++ /dev/null @@ -1,44 +0,0 @@ -/* Copyright (c) 2022 Skyward Experimental Rocketry - * Author: Alberto Nidasio - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#pragma once - -#include <ostream> - -namespace Boardcore -{ - -struct LoadCellData -{ - uint64_t timestamp; - float voltage; - float load; - - static std::string header() { return "timestamp,voltage,load\n"; } - - void print(std::ostream& os) const - { - os << timestamp << "," << voltage << "," << load << "\n"; - } -}; - -} // namespace Boardcore diff --git a/src/shared/utils/CSVReader/CSVReader.h b/src/shared/utils/CSVReader/CSVReader.h index 32388292c5890d88e3fa43182e049ac89ddaa477..a8f59a5efae736e8de7fb31193163d7fb4964f16 100644 --- a/src/shared/utils/CSVReader/CSVReader.h +++ b/src/shared/utils/CSVReader/CSVReader.h @@ -123,6 +123,9 @@ private: /** * @brief Iterable parser of CSV files. * + * If the CSV file has an header row, you must specify true as the second + * parameter in the constructor. + * * Given the file name, reads the contents as elements of type Data. Can be used * with CSVIterator to iterate through all the CSV rows. * You can retrieve all data inside the file as a vector with collect(). @@ -134,7 +137,14 @@ template <typename Data> class CSVParser { public: - CSVParser(const char* fileName) : fileStream(fileName) {} + CSVParser(const char* fileName, bool hasHeader = false) + : fileStream(fileName) + { + // If the file has the header, ignore everithing in the first line + if (hasHeader) + fileStream.ignore(std::numeric_limits<std::streamsize>::max(), + '\n'); + } ~CSVParser() { fileStream.close(); }