From 2eb6a986c65f7ec423d02ac4601cd760c249672b Mon Sep 17 00:00:00 2001 From: Christian Berger Date: Tue, 10 Apr 2018 21:57:29 +0200 Subject: [PATCH] * Updating cluon-rec2fuse to include timestamps Signed-off-by: Christian Berger --- CMakeLists.txt | 27 +--- ...v0.0.68.hpp => cluon-complete-v0.0.70.hpp} | 146 +++++++++++------- src/cluon-rec2fuse.cpp | 26 +++- 3 files changed, 113 insertions(+), 86 deletions(-) rename src/{cluon-complete-v0.0.68.hpp => cluon-complete-v0.0.70.hpp} (99%) diff --git a/CMakeLists.txt b/CMakeLists.txt index cc01424..1bcb1ef 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -18,9 +18,8 @@ cmake_minimum_required(VERSION 3.2) project(cluon-rec2fuse) ################################################################################ -# Defining the relevant versions of OpenDLV Standard Message Set and libcluon. -set(OPENDLV_STANDARD_MESSAGE_SET opendlv-standard-message-set-v0.9.1.odvd) -set(CLUON_COMPLETE cluon-complete-v0.0.68.hpp) +# Defining libcluon. +set(CLUON_COMPLETE cluon-complete-v0.0.70.hpp) ################################################################################ # This project requires C++14 or newer. @@ -63,42 +62,24 @@ endif() ################################################################################ # Extract cluon-msc from cluon-complete.hpp. -add_custom_command(OUTPUT ${CMAKE_BINARY_DIR}/cluon-msc +add_custom_command(OUTPUT ${CMAKE_BINARY_DIR}/cluon-complete.hpp WORKING_DIRECTORY ${CMAKE_BINARY_DIR} COMMAND ${CMAKE_COMMAND} -E create_symlink ${CMAKE_CURRENT_SOURCE_DIR}/src/${CLUON_COMPLETE} ${CMAKE_BINARY_DIR}/cluon-complete.hpp - COMMAND ${CMAKE_COMMAND} -E create_symlink ${CMAKE_BINARY_DIR}/cluon-complete.hpp ${CMAKE_BINARY_DIR}/cluon-complete.cpp - COMMAND ${CMAKE_CXX_COMPILER} -o ${CMAKE_BINARY_DIR}/cluon-msc ${CMAKE_BINARY_DIR}/cluon-complete.cpp -std=c++14 -pthread -D HAVE_CLUON_MSC DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/src/${CLUON_COMPLETE}) -################################################################################ -# Generate opendlv-standard-message-set.{hpp,cpp} from ${OPENDLV_STANDARD_MESSAGE_SET} file. -add_custom_command(OUTPUT ${CMAKE_BINARY_DIR}/opendlv-standard-message-set.cpp - WORKING_DIRECTORY ${CMAKE_BINARY_DIR} - COMMAND ${CMAKE_BINARY_DIR}/cluon-msc --cpp-sources --cpp-add-include-file=opendlv-standard-message-set.hpp --out=${CMAKE_BINARY_DIR}/opendlv-standard-message-set.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/${OPENDLV_STANDARD_MESSAGE_SET} - COMMAND ${CMAKE_BINARY_DIR}/cluon-msc --cpp-headers --out=${CMAKE_BINARY_DIR}/opendlv-standard-message-set.hpp ${CMAKE_CURRENT_SOURCE_DIR}/src/${OPENDLV_STANDARD_MESSAGE_SET} - DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/src/${OPENDLV_STANDARD_MESSAGE_SET} ${CMAKE_BINARY_DIR}/cluon-msc) - # Add current build directory as include directory as it contains generated files. include_directories(SYSTEM ${CMAKE_BINARY_DIR}) include_directories(${CMAKE_CURRENT_SOURCE_DIR}/src) ################################################################################ # Gather all object code first to avoid double compilation. -add_library(${PROJECT_NAME}-core OBJECT ${CMAKE_BINARY_DIR}/opendlv-standard-message-set.cpp) set(LIBRARIES ${LIBRARIES} Threads::Threads) ################################################################################ # Create executable. -add_executable(${PROJECT_NAME} ${CMAKE_CURRENT_SOURCE_DIR}/src/${PROJECT_NAME}.cpp $) +add_executable(${PROJECT_NAME} ${CMAKE_CURRENT_SOURCE_DIR}/src/${PROJECT_NAME}.cpp ${CMAKE_BINARY_DIR}/cluon-complete.hpp) target_link_libraries(${PROJECT_NAME} ${LIBRARIES}) -################################################################################ -# Enable unit testing. -#enable_testing() -#add_executable(${PROJECT_NAME}-runner ${CMAKE_CURRENT_SOURCE_DIR}/test/tests-pos-decoder.cpp $) -#target_link_libraries(${PROJECT_NAME}-runner ${LIBRARIES}) -#add_test(NAME ${PROJECT_NAME}-runner COMMAND ${PROJECT_NAME}-runner) - ################################################################################ # Install executable. install(TARGETS ${PROJECT_NAME} DESTINATION bin COMPONENT ${PROJECT_NAME}) diff --git a/src/cluon-complete-v0.0.68.hpp b/src/cluon-complete-v0.0.70.hpp similarity index 99% rename from src/cluon-complete-v0.0.68.hpp rename to src/cluon-complete-v0.0.70.hpp index be3f38a..e08e9e1 100644 --- a/src/cluon-complete-v0.0.68.hpp +++ b/src/cluon-complete-v0.0.70.hpp @@ -1,6 +1,6 @@ // This is an auto-generated header-only single-file distribution of libcluon. -// Date: Mon, 09 Apr 2018 19:47:57 +0200 -// Version: 0.0.68 +// Date: Tue, 10 Apr 2018 21:42:45 +0200 +// Version: 0.0.70 // // // Implementation of N4562 std::experimental::any (merged into C++17) for C++11 compilers. @@ -6296,6 +6296,7 @@ class LIBCLUON_API ToJSONVisitor { //#include "cluon/cluon.hpp" #include +#include #include #include @@ -6332,8 +6333,11 @@ class LIBCLUON_API ToCSVVisitor { * @param delimiter Delimiter character. * @param withHeader If true, the first line in the output contains the * column headers. + * @param mask Map describing which fields to render. If empty, all + * fields will be emitted; individual field identifiers + * can be masked setting them to false. */ - ToCSVVisitor(char delimiter = ';', bool withHeader = true) noexcept; + ToCSVVisitor(char delimiter = ';', bool withHeader = true, const std::map &mask = {}) noexcept; protected: /** @@ -6394,6 +6398,7 @@ class LIBCLUON_API ToCSVVisitor { } private: + std::map m_mask{}; std::string m_prefix{}; char m_delimiter{';'}; bool m_withHeader{true}; @@ -11462,8 +11467,12 @@ inline std::string ToJSONVisitor::encodeBase64(const std::string &input) const n namespace cluon { -inline ToCSVVisitor::ToCSVVisitor(char delimiter, bool withHeader) noexcept - : ToCSVVisitor::ToCSVVisitor("", delimiter, withHeader, false) {} +inline ToCSVVisitor::ToCSVVisitor(char delimiter, bool withHeader, const std::map &mask) noexcept + : m_mask(mask) + , m_prefix("") + , m_delimiter(delimiter) + , m_withHeader(withHeader) + , m_isNested(false) {} inline ToCSVVisitor::ToCSVVisitor(const std::string &prefix, char delimiter, bool withHeader, bool isNested) noexcept : m_prefix(prefix) @@ -11502,120 +11511,133 @@ inline void ToCSVVisitor::postVisit() noexcept { } inline void ToCSVVisitor::visit(uint32_t id, std::string &&typeName, std::string &&name, bool &v) noexcept { - (void)id; (void)typeName; - if (m_fillHeader) { - m_bufferHeader << m_prefix << (!m_prefix.empty() ? "." : "") << name << m_delimiter; + if ((0 == m_mask.count(id)) || m_mask[id]) { + if (m_fillHeader) { + m_bufferHeader << m_prefix << (!m_prefix.empty() ? "." : "") << name << m_delimiter; + } + m_bufferValues << v << m_delimiter; } - m_bufferValues << v << m_delimiter; } inline void ToCSVVisitor::visit(uint32_t id, std::string &&typeName, std::string &&name, char &v) noexcept { - (void)id; (void)typeName; - if (m_fillHeader) { - m_bufferHeader << m_prefix << (!m_prefix.empty() ? "." : "") << name << m_delimiter; + if ((0 == m_mask.count(id)) || m_mask[id]) { + if (m_fillHeader) { + m_bufferHeader << m_prefix << (!m_prefix.empty() ? "." : "") << name << m_delimiter; + } + m_bufferValues << v << m_delimiter; } - m_bufferValues << v << m_delimiter; } inline void ToCSVVisitor::visit(uint32_t id, std::string &&typeName, std::string &&name, int8_t &v) noexcept { - (void)id; (void)typeName; - if (m_fillHeader) { - m_bufferHeader << m_prefix << (!m_prefix.empty() ? "." : "") << name << m_delimiter; + if ((0 == m_mask.count(id)) || m_mask[id]) { + if (m_fillHeader) { + m_bufferHeader << m_prefix << (!m_prefix.empty() ? "." : "") << name << m_delimiter; + } + m_bufferValues << +v << m_delimiter; } - m_bufferValues << +v << m_delimiter; } inline void ToCSVVisitor::visit(uint32_t id, std::string &&typeName, std::string &&name, uint8_t &v) noexcept { - (void)id; (void)typeName; - if (m_fillHeader) { - m_bufferHeader << m_prefix << (!m_prefix.empty() ? "." : "") << name << m_delimiter; + if ((0 == m_mask.count(id)) || m_mask[id]) { + if (m_fillHeader) { + m_bufferHeader << m_prefix << (!m_prefix.empty() ? "." : "") << name << m_delimiter; + } + m_bufferValues << +v << m_delimiter; } - m_bufferValues << +v << m_delimiter; } inline void ToCSVVisitor::visit(uint32_t id, std::string &&typeName, std::string &&name, int16_t &v) noexcept { - (void)id; (void)typeName; - if (m_fillHeader) { - m_bufferHeader << m_prefix << (!m_prefix.empty() ? "." : "") << name << m_delimiter; + if ((0 == m_mask.count(id)) || m_mask[id]) { + if (m_fillHeader) { + m_bufferHeader << m_prefix << (!m_prefix.empty() ? "." : "") << name << m_delimiter; + } + m_bufferValues << v << m_delimiter; } - m_bufferValues << v << m_delimiter; } inline void ToCSVVisitor::visit(uint32_t id, std::string &&typeName, std::string &&name, uint16_t &v) noexcept { - (void)id; (void)typeName; - if (m_fillHeader) { - m_bufferHeader << m_prefix << (!m_prefix.empty() ? "." : "") << name << m_delimiter; + if ((0 == m_mask.count(id)) || m_mask[id]) { + if (m_fillHeader) { + m_bufferHeader << m_prefix << (!m_prefix.empty() ? "." : "") << name << m_delimiter; + } + m_bufferValues << v << m_delimiter; } - m_bufferValues << v << m_delimiter; } inline void ToCSVVisitor::visit(uint32_t id, std::string &&typeName, std::string &&name, int32_t &v) noexcept { - (void)id; (void)typeName; - if (m_fillHeader) { - m_bufferHeader << m_prefix << (!m_prefix.empty() ? "." : "") << name << m_delimiter; + if ((0 == m_mask.count(id)) || m_mask[id]) { + if (m_fillHeader) { + m_bufferHeader << m_prefix << (!m_prefix.empty() ? "." : "") << name << m_delimiter; + } + m_bufferValues << v << m_delimiter; } - m_bufferValues << v << m_delimiter; } inline void ToCSVVisitor::visit(uint32_t id, std::string &&typeName, std::string &&name, uint32_t &v) noexcept { - (void)id; (void)typeName; - if (m_fillHeader) { - m_bufferHeader << m_prefix << (!m_prefix.empty() ? "." : "") << name << m_delimiter; + if ((0 == m_mask.count(id)) || m_mask[id]) { + if (m_fillHeader) { + m_bufferHeader << m_prefix << (!m_prefix.empty() ? "." : "") << name << m_delimiter; + } + m_bufferValues << v << m_delimiter; } - m_bufferValues << v << m_delimiter; } inline void ToCSVVisitor::visit(uint32_t id, std::string &&typeName, std::string &&name, int64_t &v) noexcept { - (void)id; (void)typeName; - if (m_fillHeader) { - m_bufferHeader << m_prefix << (!m_prefix.empty() ? "." : "") << name << m_delimiter; + if ((0 == m_mask.count(id)) || m_mask[id]) { + if (m_fillHeader) { + m_bufferHeader << m_prefix << (!m_prefix.empty() ? "." : "") << name << m_delimiter; + } + m_bufferValues << v << m_delimiter; } - m_bufferValues << v << m_delimiter; } inline void ToCSVVisitor::visit(uint32_t id, std::string &&typeName, std::string &&name, uint64_t &v) noexcept { - (void)id; (void)typeName; - if (m_fillHeader) { - m_bufferHeader << m_prefix << (!m_prefix.empty() ? "." : "") << name << m_delimiter; + if ((0 == m_mask.count(id)) || m_mask[id]) { + if (m_fillHeader) { + m_bufferHeader << m_prefix << (!m_prefix.empty() ? "." : "") << name << m_delimiter; + } + m_bufferValues << v << m_delimiter; } - m_bufferValues << v << m_delimiter; } inline void ToCSVVisitor::visit(uint32_t id, std::string &&typeName, std::string &&name, float &v) noexcept { - (void)id; (void)typeName; - if (m_fillHeader) { - m_bufferHeader << m_prefix << (!m_prefix.empty() ? "." : "") << name << m_delimiter; + if ((0 == m_mask.count(id)) || m_mask[id]) { + if (m_fillHeader) { + m_bufferHeader << m_prefix << (!m_prefix.empty() ? "." : "") << name << m_delimiter; + } + m_bufferValues << std::setprecision(7) << v << std::setprecision(6) << m_delimiter; } - m_bufferValues << std::setprecision(7) << v << std::setprecision(6) << m_delimiter; } inline void ToCSVVisitor::visit(uint32_t id, std::string &&typeName, std::string &&name, double &v) noexcept { - (void)id; (void)typeName; - if (m_fillHeader) { - m_bufferHeader << m_prefix << (!m_prefix.empty() ? "." : "") << name << m_delimiter; + if ((0 == m_mask.count(id)) || m_mask[id]) { + if (m_fillHeader) { + m_bufferHeader << m_prefix << (!m_prefix.empty() ? "." : "") << name << m_delimiter; + } + m_bufferValues << std::setprecision(11) << v << std::setprecision(6) << m_delimiter; } - m_bufferValues << std::setprecision(11) << v << std::setprecision(6) << m_delimiter; } inline void ToCSVVisitor::visit(uint32_t id, std::string &&typeName, std::string &&name, std::string &v) noexcept { - (void)id; (void)typeName; - if (m_fillHeader) { - m_bufferHeader << m_prefix << (!m_prefix.empty() ? "." : "") << name << m_delimiter; + if ((0 == m_mask.count(id)) || m_mask[id]) { + if (m_fillHeader) { + m_bufferHeader << m_prefix << (!m_prefix.empty() ? "." : "") << name << m_delimiter; + } + m_bufferValues << '\"' << v << '\"' << m_delimiter; } - m_bufferValues << '\"' << v << '\"' << m_delimiter; } } // namespace cluon @@ -14871,12 +14893,16 @@ int main(int argc, char **argv) { const std::string PROGRAM{argv[0]}; // NOLINT auto commandlineArguments = cluon::getCommandlineArguments(argc, argv); if (1 == argc) { - std::cerr << PROGRAM << " replays a .rec file into an OpenDaVINCI session or to stdout." << std::endl; - std::cerr << "Usage: " << PROGRAM << " [--cid=] recording.rec" << std::endl; + std::cerr << PROGRAM << " replays a .rec file into an OpenDaVINCI session or to stdout; if playing back to an OD4Session using parameter --cid, you can specify the optional parameter --stdout to also playback to stdout." << std::endl; + std::cerr << "Usage: " << PROGRAM << " [--cid= [--stdout]] recording.rec" << std::endl; std::cerr << "Example: " << PROGRAM << " --cid=111 file.rec" << std::endl; + std::cerr << " " << PROGRAM << " --cid=111 --stdout file.rec" << std::endl; + std::cerr << " " << PROGRAM << " file.rec" << std::endl; retCode = 1; } else { + const bool playBackToStdout = ( (0 != commandlineArguments.count("stdout")) || (0 == commandlineArguments.count("cid")) ); + std::string recFile; for (auto e : commandlineArguments) { if (recFile.empty() && e.second.empty() && e.first != PROGRAM) { @@ -15027,7 +15053,7 @@ int main(int argc, char **argv) { if (od4 && od4->isRunning()) { od4->send(std::move(next.second)); } - else { + if (playBackToStdout) { std::cout << cluon::serializeEnvelope(std::move(next.second)); std::cout.flush(); } diff --git a/src/cluon-rec2fuse.cpp b/src/cluon-rec2fuse.cpp index b0bdbc3..b9d0104 100644 --- a/src/cluon-rec2fuse.cpp +++ b/src/cluon-rec2fuse.cpp @@ -16,11 +16,11 @@ */ #include "cluon-complete.hpp" -#include "opendlv-standard-message-set.hpp" #define FUSE_USE_VERSION 26 #include +#include #include #include #include @@ -170,14 +170,34 @@ int32_t main(int32_t argc, char **argv) { mapOfFilenames[KEY] = _FILENAME; if (mapOfEntries.count(KEY) > 0) { + // Extract timestamps. + std::string timeStamps; + { + cluon::ToCSVVisitor csv(';', false, { {1,false}, {2,false}, {3,true}, {4,true}, {5,true}, {6,false} }); + env.accept(csv); + timeStamps = csv.csv(); + } + cluon::ToCSVVisitor csv(';', false); gm.accept(csv); - mapOfEntries[KEY] += csv.csv(); + mapOfEntries[KEY] += stringtoolbox::split(timeStamps, '\n')[0] + csv.csv(); } else { + // Extract timestamps. + std::vector timeStampsWithHeader; + { + // Skip senderStamp (as it is in file name) and serialzedData. + cluon::ToCSVVisitor csv(';', true, { {1,false}, {2,false}, {3,true}, {4,true}, {5,true}, {6,false} }); + env.accept(csv); + timeStampsWithHeader = stringtoolbox::split(csv.csv(), '\n'); + } + cluon::ToCSVVisitor csv(';', true); gm.accept(csv); - mapOfEntries[KEY] += csv.csv(); + + std::vector valuesWithHeader = stringtoolbox::split(csv.csv(), '\n'); + + mapOfEntries[KEY] += timeStampsWithHeader.at(0) + valuesWithHeader.at(0) + '\n' + timeStampsWithHeader.at(1) + valuesWithHeader.at(1) + '\n'; } mapOfEntrySizes[KEY] = mapOfEntries[KEY].size(); }