mirror of
https://github.com/hyblocker/OpenVR-SpaceCalibrator.git
synced 2026-10-27 10:01:31 +01:00
216 lines
5.3 KiB
C++
216 lines
5.3 KiB
C++
#include "stdafx.h"
|
|
#include "CalibrationMetrics.h"
|
|
#include <shlobj_core.h>
|
|
#include <fstream>
|
|
#include <vector>
|
|
|
|
namespace Metrics {
|
|
double TimeSpan = 30, CurrentTime;
|
|
|
|
TimeSeries<Eigen::Vector3d> posOffset_rawComputed; // , rotOffset_rawComputed;
|
|
TimeSeries<Eigen::Vector3d> posOffset_currentCal; // , rotOffset_currentCal;
|
|
TimeSeries<Eigen::Vector3d> posOffset_lastSample; // , rotOffset_lastSample;
|
|
TimeSeries<Eigen::Vector3d> posOffset_byRelPose;
|
|
|
|
TimeSeries<double> error_rawComputed, error_currentCal, error_byRelPose, error_currentCalRelPose;
|
|
TimeSeries<double> axisIndependence;
|
|
TimeSeries<double> computationTime;
|
|
|
|
// true - full calibration, false - static calibration
|
|
TimeSeries<bool> calibrationApplied;
|
|
|
|
double timestamp() {
|
|
static long long ts_start = ~0LL;
|
|
|
|
LARGE_INTEGER ts, freq;
|
|
QueryPerformanceCounter(&ts);
|
|
QueryPerformanceFrequency(&freq);
|
|
|
|
if (ts_start == ~0LL) ts_start = ts.QuadPart;
|
|
|
|
ts.QuadPart -= ts_start;
|
|
|
|
return ts.QuadPart / (double)freq.QuadPart;
|
|
}
|
|
|
|
void RecordTimestamp() {
|
|
CurrentTime = timestamp();
|
|
}
|
|
|
|
bool enableLogs = false;
|
|
|
|
static std::ofstream logFile;
|
|
static bool logFileIsOpen = false;
|
|
static bool failedToOpenLogFile = false;
|
|
|
|
struct CsvField {
|
|
const char* name;
|
|
void (*writer)(std::ofstream& s);
|
|
};
|
|
|
|
#define TS_FIELD(n) \
|
|
{ #n, [](auto &s) { s << n.last(); } }
|
|
|
|
#define TS_VECTOR_FIELD(n) \
|
|
{ #n ".x", [](auto &s) { s << n.last()(0); } }, \
|
|
{ #n ".y", [](auto &s) { s << n.last()(1); } }, \
|
|
{ #n ".z", [](auto &s) { s << n.last()(2); } }
|
|
|
|
static const CsvField fields[] = {
|
|
{
|
|
"Timestamp",
|
|
[](auto& s) { s << CurrentTime; }
|
|
},
|
|
|
|
TS_VECTOR_FIELD(posOffset_rawComputed),
|
|
TS_VECTOR_FIELD(posOffset_currentCal),
|
|
TS_VECTOR_FIELD(posOffset_lastSample),
|
|
TS_VECTOR_FIELD(posOffset_byRelPose),
|
|
|
|
TS_FIELD(error_rawComputed),
|
|
TS_FIELD(error_currentCal),
|
|
TS_FIELD(error_byRelPose),
|
|
TS_FIELD(error_currentCalRelPose),
|
|
TS_FIELD(axisIndependence),
|
|
TS_FIELD(computationTime),
|
|
|
|
{
|
|
"calibrationApplied",
|
|
[](auto& s) {
|
|
if (calibrationApplied.lastTs() == CurrentTime) {
|
|
if (calibrationApplied.last()) {
|
|
s << "FULL";
|
|
}
|
|
else {
|
|
s << "STATIC";
|
|
}
|
|
}
|
|
}
|
|
}
|
|
};
|
|
|
|
|
|
static void ClearOldLogs(const std::wstring& path) {
|
|
std::wstring search_path = path + L"\\spacecal_log.*.txt";
|
|
WIN32_FIND_DATA find_data;
|
|
|
|
SYSTEMTIME st_now;
|
|
FILETIME ft_now;
|
|
GetSystemTime(&st_now);
|
|
SystemTimeToFileTime(&st_now, &ft_now);
|
|
|
|
ULARGE_INTEGER ft_tmp;
|
|
ft_tmp.HighPart = ft_now.dwHighDateTime;
|
|
ft_tmp.LowPart = ft_now.dwLowDateTime;
|
|
// one day ago
|
|
uint64_t limit = ft_tmp.QuadPart - (uint64_t)(24LL * 3600LL * 10LL * 1000LL * 1000LL);
|
|
|
|
HANDLE find_handle = FindFirstFile(search_path.c_str(), &find_data);
|
|
if (find_handle != INVALID_HANDLE_VALUE) {
|
|
do {
|
|
ft_tmp.HighPart = find_data.ftLastWriteTime.dwHighDateTime;
|
|
ft_tmp.LowPart = find_data.ftLastWriteTime.dwLowDateTime;
|
|
if (ft_tmp.QuadPart < limit) {
|
|
std::wstring file_path = path + L"\\" + find_data.cFileName;
|
|
DeleteFile(file_path.c_str());
|
|
}
|
|
} while (FindNextFile(find_handle, &find_data));
|
|
FindClose(find_handle);
|
|
}
|
|
}
|
|
|
|
static bool OpenLogFile() {
|
|
PWSTR RootPath = NULL;
|
|
if (S_OK != SHGetKnownFolderPath(FOLDERID_LocalAppDataLow, 0, NULL, &RootPath)) {
|
|
CoTaskMemFree(RootPath);
|
|
return false;
|
|
}
|
|
|
|
std::wstring path(RootPath);
|
|
CoTaskMemFree(RootPath);
|
|
|
|
path += LR"(\OpenVR-SpaceCalibrator)";
|
|
if (CreateDirectoryW(path.c_str(), 0) == 0 && GetLastError() != ERROR_ALREADY_EXISTS) {
|
|
return false;
|
|
}
|
|
|
|
path += LR"(\Logs)";
|
|
if (CreateDirectoryW(path.c_str(), 0) == 0 && GetLastError() != ERROR_ALREADY_EXISTS) {
|
|
return false;
|
|
}
|
|
|
|
ClearOldLogs(path);
|
|
|
|
SYSTEMTIME now;
|
|
GetSystemTime(&now);
|
|
|
|
size_t dateBufLen = GetDateFormatW(LOCALE_USER_DEFAULT, 0, &now, L"yyyy-MM-dd", NULL, 0);
|
|
std::vector<WCHAR> dateBuf(dateBufLen);
|
|
if (!GetDateFormatEx(LOCALE_NAME_INVARIANT, 0, &now, L"yyyy-MM-dd", &dateBuf[0], dateBufLen, NULL)) return false;
|
|
|
|
size_t timeBufLen = GetTimeFormatW(LOCALE_USER_DEFAULT, 0, &now, L"HH-mm-ss", NULL, 0);
|
|
std::vector<WCHAR> timeBuf(timeBufLen);
|
|
if (!GetTimeFormatEx(LOCALE_NAME_INVARIANT, 0, &now, L"HH-mm-ss", &timeBuf[0], timeBufLen)) return false;
|
|
|
|
path += LR"(\spacecal_log.)";
|
|
path += &dateBuf[0];
|
|
path += L"T";
|
|
path += &timeBuf[0];
|
|
path += L".txt";
|
|
|
|
logFile.open(path);
|
|
if (logFile.fail()) {
|
|
return false;
|
|
}
|
|
|
|
for (int i = 0; i < sizeof fields / sizeof fields[0]; i++) {
|
|
if (i > 0) logFile << ",";
|
|
logFile << fields[i].name;
|
|
}
|
|
logFile << "\n";
|
|
|
|
logFileIsOpen = true;
|
|
|
|
return true;
|
|
}
|
|
|
|
static bool CheckLogOpen() {
|
|
if (!enableLogs) {
|
|
if (logFileIsOpen) {
|
|
logFile.close();
|
|
}
|
|
logFileIsOpen = false;
|
|
failedToOpenLogFile = false;
|
|
|
|
return false;
|
|
}
|
|
|
|
if (failedToOpenLogFile) return false;
|
|
if (!logFileIsOpen && !OpenLogFile()) {
|
|
failedToOpenLogFile = true;
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
void WriteLogAnnotation(const char *s) {
|
|
if (!CheckLogOpen()) return;
|
|
|
|
logFile << "# [" << timestamp() << "] " << s << "\n";
|
|
logFile.flush();
|
|
}
|
|
|
|
void WriteLogEntry() {
|
|
if (!CheckLogOpen()) return;
|
|
|
|
if (logFileIsOpen) {
|
|
for (int i = 0; i < sizeof fields / sizeof fields[0]; i++) {
|
|
if (i > 0) logFile << ",";
|
|
fields[i].writer(logFile);
|
|
}
|
|
logFile << "\n";
|
|
}
|
|
logFile.flush();
|
|
}
|
|
}
|