From 7b3be452b6be528de753a1a633a3aacdb11be86c Mon Sep 17 00:00:00 2001 From: DaMichel Date: Fri, 29 Jul 2016 11:12:22 +0200 Subject: new track logging: record poses in various stages of processing into a file --- gui/options-dialog.cpp | 21 +++++++++++++ gui/options-dialog.hpp | 3 ++ gui/settings.ui | 82 +++++++++++++++++++++++++++++++++++++++++++++++++- gui/ui.cpp | 61 ++++++++++++++++++++++++++++++++++++- gui/ui.h | 3 ++ 5 files changed, 168 insertions(+), 2 deletions(-) (limited to 'gui') diff --git a/gui/options-dialog.cpp b/gui/options-dialog.cpp index 3b54ae9a..8987ba34 100644 --- a/gui/options-dialog.cpp +++ b/gui/options-dialog.cpp @@ -11,6 +11,7 @@ #include #include #include +#include static QString kopts_to_string(const key_opts& kopts) { @@ -72,6 +73,9 @@ OptionsDialog::OptionsDialog(std::function pause_keybindings) : tie_setting(main.center_method, ui.center_method); + tie_setting(main.tracklogging_enabled, ui.tracklogging_enabled); + tie_setting(main.tracklogging_filename, ui.tracklogging_filenameedit); + struct tmp { key_opts& opt; @@ -102,6 +106,8 @@ OptionsDialog::OptionsDialog(std::function pause_keybindings) : connect(val.button, &QPushButton::pressed, this, [=]() -> void { bind_key(val.opt, val.label); }); } } + + connect(ui.tracklogging_fileselectbtn, SIGNAL(clicked()), this, SLOT(browse_datalogging_file())); } void OptionsDialog::bind_key(key_opts& kopts, QLabel* label) @@ -163,3 +169,18 @@ void OptionsDialog::doCancel() close(); } +void OptionsDialog::browse_datalogging_file() +{ + QString filename = ui.tracklogging_filenameedit->text(); + if (filename.isEmpty()) + filename = QDir::currentPath(); + QString newfilename = QFileDialog::getSaveFileName(this, tr("Select Filename"), filename, tr("CSV File (*.csv)")); + if (!newfilename.isEmpty()) + ui.tracklogging_filenameedit->setText(newfilename); +} + +void OptionsDialog::update_widgets_states(bool tracker_is_running) +{ + ui.tracklogging_enabled->setEnabled(!tracker_is_running); + ui.tracklogging_fileselectbtn->setEnabled(!tracker_is_running); +} \ No newline at end of file diff --git a/gui/options-dialog.hpp b/gui/options-dialog.hpp index 66386a79..f84ee8f6 100644 --- a/gui/options-dialog.hpp +++ b/gui/options-dialog.hpp @@ -13,6 +13,8 @@ signals: void saving(); public: OptionsDialog(std::function pause_keybindings); +public slots: + void update_widgets_states(bool tracker_is_running); private: main_settings main; std::function pause_keybindings; @@ -22,4 +24,5 @@ private slots: void doOK(); void doCancel(); void bind_key(key_opts &kopts, QLabel* label); + void browse_datalogging_file(); }; diff --git a/gui/settings.ui b/gui/settings.ui index 4654dd85..9c573da2 100644 --- a/gui/settings.ui +++ b/gui/settings.ui @@ -33,7 +33,7 @@ - 0 + 2 @@ -1204,6 +1204,86 @@ + + + + + 0 + 0 + + + + + 0 + 20 + + + + Data Logging + + + + + + + 0 + 0 + + + + Record pose data in a csv file. WARNING: overwrites file contents without warning every time the tracker is started. + + + true + + + + + + + Enable + + + + + + + 0 + + + 0 + + + + + Select File ... + + + + + + + false + + + true + + + + + + + + + true + + + + + + + + diff --git a/gui/ui.cpp b/gui/ui.cpp index 85d5d029..3bda6ee2 100644 --- a/gui/ui.cpp +++ b/gui/ui.cpp @@ -15,6 +15,7 @@ #include #include #include +#include #ifdef _WIN32 # include @@ -285,6 +286,45 @@ void MainWindow::reload_options() ensure_tray(); } +/* + Allocates a new logger instance depending on main settings. Result is assigned to logger variable of State object. + May open warning dialogs. + May also assign nullptr in case of an error. +*/ +void MainWindow::initialize_logger() +{ + logger = nullptr; + if (s.tracklogging_enabled) + { + if (static_cast(s.tracklogging_filename).isEmpty()) + { + QMessageBox::warning(this, tr("Logging Error"), + tr("No filename given for track logging. Aborting."), + QMessageBox::Ok, + QMessageBox::NoButton); + return; + } + try + { + logger = TrackLoggerCSV::make(s); + } + catch (std::ios_base::failure &) + { + QMessageBox::warning(this, tr("Logging Error"), + tr("Unable to open file: ") + s.tracklogging_filename + tr(". Aborting."), + QMessageBox::Ok, + QMessageBox::NoButton); + return; + } + } + else + { + logger = TrackLogger::make(); + } + assert(logger != nullptr); +} + + void MainWindow::startTracker() { if (work) @@ -310,9 +350,17 @@ void MainWindow::startTracker() return; } + initialize_logger(); + if (logger == nullptr) + { + // error -> rollback + libs = SelectedLibraries(); + return; + } + save_modules(); - work = std::make_shared(pose, libs, winId()); + work = std::make_shared(pose, libs, *logger, winId()); reload_options(); @@ -331,6 +379,12 @@ void MainWindow::startTracker() // trackers take care of layout state updates const bool is_inertial = ui.video_frame->layout() == nullptr; updateButtonState(true, is_inertial); + + // Update the state of the options window directly. + // Might be better to emit signals and allow the options window + // to connect its slots to them (?) + if (options_widget) + options_widget->update_widgets_states(true); ui.btnStopTracker->setFocus(); } @@ -358,12 +412,16 @@ void MainWindow::stopTracker() work = nullptr; libs = SelectedLibraries(); + logger = nullptr; { double p[6] = {0,0,0, 0,0,0}; display_pose(p, p); } updateButtonState(false, false); + + if (options_widget) + options_widget->update_widgets_states(false); set_title(); @@ -495,6 +553,7 @@ void MainWindow::show_options_dialog() if (mk_window(&options_widget, [&](bool flag) -> void { set_keys_enabled(!flag); })) { connect(options_widget.get(), &OptionsDialog::saving, this, &MainWindow::reload_options); + options_widget->update_widgets_states(work != nullptr); } } diff --git a/gui/ui.h b/gui/ui.h index 7415d3d4..acec615e 100644 --- a/gui/ui.h +++ b/gui/ui.h @@ -102,6 +102,9 @@ private slots: void startTracker(); void stopTracker(); void reload_options(); + + void initialize_logger(); + signals: void emit_start_tracker(); void emit_stop_tracker(); -- cgit v1.2.3 From 12d2080865958cc07d37dddd28240f40423fb292 Mon Sep 17 00:00:00 2001 From: DaMichel Date: Fri, 29 Jul 2016 16:32:54 +0200 Subject: logger: it is definitely nicer to not have things all over the place --- gui/ui.cpp | 50 +---------------------------------------- gui/ui.h | 2 -- opentrack-logic/state.hpp | 2 -- opentrack-logic/tracklogger.hpp | 7 +----- opentrack-logic/work.cpp | 45 +++++++++++++++++++++++++++++++++++-- opentrack-logic/work.hpp | 10 ++++++--- 6 files changed, 52 insertions(+), 64 deletions(-) (limited to 'gui') diff --git a/gui/ui.cpp b/gui/ui.cpp index 3bda6ee2..94fd0cbf 100644 --- a/gui/ui.cpp +++ b/gui/ui.cpp @@ -15,7 +15,6 @@ #include #include #include -#include #ifdef _WIN32 # include @@ -286,44 +285,6 @@ void MainWindow::reload_options() ensure_tray(); } -/* - Allocates a new logger instance depending on main settings. Result is assigned to logger variable of State object. - May open warning dialogs. - May also assign nullptr in case of an error. -*/ -void MainWindow::initialize_logger() -{ - logger = nullptr; - if (s.tracklogging_enabled) - { - if (static_cast(s.tracklogging_filename).isEmpty()) - { - QMessageBox::warning(this, tr("Logging Error"), - tr("No filename given for track logging. Aborting."), - QMessageBox::Ok, - QMessageBox::NoButton); - return; - } - try - { - logger = TrackLoggerCSV::make(s); - } - catch (std::ios_base::failure &) - { - QMessageBox::warning(this, tr("Logging Error"), - tr("Unable to open file: ") + s.tracklogging_filename + tr(". Aborting."), - QMessageBox::Ok, - QMessageBox::NoButton); - return; - } - } - else - { - logger = TrackLogger::make(); - } - assert(logger != nullptr); -} - void MainWindow::startTracker() { @@ -350,17 +311,9 @@ void MainWindow::startTracker() return; } - initialize_logger(); - if (logger == nullptr) - { - // error -> rollback - libs = SelectedLibraries(); - return; - } - save_modules(); - work = std::make_shared(pose, libs, *logger, winId()); + work = std::make_shared(pose, libs, winId()); reload_options(); @@ -412,7 +365,6 @@ void MainWindow::stopTracker() work = nullptr; libs = SelectedLibraries(); - logger = nullptr; { double p[6] = {0,0,0, 0,0,0}; diff --git a/gui/ui.h b/gui/ui.h index acec615e..d6f5e400 100644 --- a/gui/ui.h +++ b/gui/ui.h @@ -103,8 +103,6 @@ private slots: void stopTracker(); void reload_options(); - void initialize_logger(); - signals: void emit_start_tracker(); void emit_stop_tracker(); diff --git a/opentrack-logic/state.hpp b/opentrack-logic/state.hpp index bdab9afe..1c608f7a 100644 --- a/opentrack-logic/state.hpp +++ b/opentrack-logic/state.hpp @@ -14,7 +14,6 @@ using namespace options; #include "main-settings.hpp" #include "mappings.hpp" #include "selected-libraries.hpp" -#include "tracklogger.hpp" #include "work.hpp" #include #include @@ -30,5 +29,4 @@ struct State main_settings s; Mappings pose; mem work; - mem logger; }; diff --git a/opentrack-logic/tracklogger.hpp b/opentrack-logic/tracklogger.hpp index 99bc71b0..65128d48 100644 --- a/opentrack-logic/tracklogger.hpp +++ b/opentrack-logic/tracklogger.hpp @@ -14,8 +14,6 @@ public: { } - static mem make() { return std::make_shared(); } - virtual void write(const char *) { } @@ -45,12 +43,9 @@ public: first_col(true) { out.open(filename.toStdString()); - if (!out.is_open()) - throw std::ios_base::failure("unable to open file"); } - static mem make(const main_settings &s) { return std::static_pointer_cast(std::make_shared(s.tracklogging_filename)); } - + bool is_open() const { return out.is_open(); } virtual void write(const char *s); virtual void write(const double *p, int n); virtual void next_line(); diff --git a/opentrack-logic/work.cpp b/opentrack-logic/work.cpp index e5b08c18..8d00270b 100644 --- a/opentrack-logic/work.cpp +++ b/opentrack-logic/work.cpp @@ -1,9 +1,50 @@ #include "work.hpp" +#include -Work::Work(Mappings& m, SelectedLibraries& libs, TrackLogger &logger, WId handle) : + +std::shared_ptr Work::make_logger(const main_settings &s) +{ + if (s.tracklogging_enabled) + { + if (static_cast(s.tracklogging_filename).isEmpty()) + { + QMessageBox::warning(nullptr, "Logging Error", + "No filename given for track logging. Proceeding without logging.", + QMessageBox::Ok, + QMessageBox::NoButton); + } + else + { + auto logger = std::make_shared(s.tracklogging_filename); + if (!logger->is_open()) + { + logger = nullptr; + QMessageBox::warning(nullptr, "Logging Error", + "Unable to open file: " + s.tracklogging_filename + ". Proceeding without logging.", + QMessageBox::Ok, + QMessageBox::NoButton); + } + else + { + /* As this function has the potential to fill up the hard drive + of the unwary with junk data, a warning is in order. */ + QMessageBox::warning(nullptr, "Logging Active", + "Just a heads up. You are recoding pose data to " + s.tracklogging_filename + "!", + QMessageBox::Ok, + QMessageBox::NoButton); + return logger; + } + } + } + return std::make_shared(); +} + + +Work::Work(Mappings& m, SelectedLibraries& libs, WId handle) : libs(libs), - tracker(std::make_shared(m, libs, logger)), + logger(make_logger(s)), + tracker(std::make_shared(m, libs, *logger)), sc(std::make_shared()), handle(handle), keys { diff --git a/opentrack-logic/work.hpp b/opentrack-logic/work.hpp index 6425b11c..4afb1da4 100644 --- a/opentrack-logic/work.hpp +++ b/opentrack-logic/work.hpp @@ -13,6 +13,7 @@ #include "tracker.h" #include "shortcuts.h" #include "export.hpp" +#include "tracklogger.hpp" #include #include @@ -25,15 +26,18 @@ struct OPENTRACK_LOGIC_EXPORT Work { using fn_t = std::function; using key_tuple = std::tuple; - + main_settings s; // tracker needs settings, so settings must come before it SelectedLibraries& libs; + std::shared_ptr logger; // must come before tracker, since tracker depends on it std::shared_ptr tracker; std::shared_ptr sc; WId handle; std::vector keys; - main_settings s; - Work(Mappings& m, SelectedLibraries& libs, TrackLogger &logger, WId handle); + Work(Mappings& m, SelectedLibraries& libs, WId handle); ~Work(); void reload_shortcuts(); + +private: + std::shared_ptr make_logger(const main_settings &s); }; -- cgit v1.2.3 From 44428d4b5eeae78fd9cdedce840f7de2ddc6c6b2 Mon Sep 17 00:00:00 2001 From: DaMichel Date: Fri, 29 Jul 2016 18:51:23 +0200 Subject: logging: file selection dialog can freeze. Therefore don't use native dialog?! --- gui/options-dialog.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'gui') diff --git a/gui/options-dialog.cpp b/gui/options-dialog.cpp index 8987ba34..9dcb7879 100644 --- a/gui/options-dialog.cpp +++ b/gui/options-dialog.cpp @@ -174,7 +174,12 @@ void OptionsDialog::browse_datalogging_file() QString filename = ui.tracklogging_filenameedit->text(); if (filename.isEmpty()) filename = QDir::currentPath(); - QString newfilename = QFileDialog::getSaveFileName(this, tr("Select Filename"), filename, tr("CSV File (*.csv)")); + /* Sometimes this function freezes the app before opening the dialog. + Might be related to https://forum.qt.io/topic/49209/qfiledialog-getopenfilename-hangs-in-windows-when-using-the-native-dialog/8 + and be a known problem. Possible solution is to use the QFileDialog::DontUseNativeDialog flag. + Since the freeze is apparently random, I'm not sure it helped. + */ + QString newfilename = QFileDialog::getSaveFileName(this, tr("Select Filename"), filename, tr("CSV File (*.csv)"), nullptr, QFileDialog::DontUseNativeDialog); if (!newfilename.isEmpty()) ui.tracklogging_filenameedit->setText(newfilename); } -- cgit v1.2.3