Skip to content

Commit

Permalink
[sysid] Load DataLog files directly for analysis (#6103)
Browse files Browse the repository at this point in the history
Co-authored-by: Oblarg <emichaelbrnett@gmail.com>
  • Loading branch information
PeterJohnson and Oblarg authored Jan 6, 2024
1 parent f94e3d8 commit 7c26bc7
Show file tree
Hide file tree
Showing 33 changed files with 1,088 additions and 2,015 deletions.
72 changes: 0 additions & 72 deletions datalogtool/src/main/native/cpp/DataLogThread.cpp

This file was deleted.

71 changes: 0 additions & 71 deletions datalogtool/src/main/native/cpp/DataLogThread.h

This file was deleted.

25 changes: 13 additions & 12 deletions datalogtool/src/main/native/cpp/Exporter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
#include <fmt/chrono.h>
#include <fmt/format.h>
#include <glass/Storage.h>
#include <glass/support/DataLogReaderThread.h>
#include <imgui.h>
#include <imgui_internal.h>
#include <imgui_stdlib.h>
Expand All @@ -32,11 +33,10 @@
#include <wpi/raw_ostream.h>

#include "App.h"
#include "DataLogThread.h"

namespace {
struct InputFile {
explicit InputFile(std::unique_ptr<DataLogThread> datalog);
explicit InputFile(std::unique_ptr<glass::DataLogReaderThread> datalog);

InputFile(std::string_view filename, std::string_view status)
: filename{filename},
Expand All @@ -47,7 +47,7 @@ struct InputFile {

std::string filename;
std::string stem;
std::unique_ptr<DataLogThread> datalog;
std::unique_ptr<glass::DataLogReaderThread> datalog;
std::string status;
bool highlight = false;
};
Expand Down Expand Up @@ -135,7 +135,7 @@ static void RebuildEntryTree() {
}
}

InputFile::InputFile(std::unique_ptr<DataLogThread> datalog_)
InputFile::InputFile(std::unique_ptr<glass::DataLogReaderThread> datalog_)
: filename{datalog_->GetBufferIdentifier()},
stem{fs::path{filename}.stem().string()},
datalog{std::move(datalog_)} {
Expand Down Expand Up @@ -192,7 +192,7 @@ static std::unique_ptr<InputFile> LoadDataLog(std::string_view filename) {
}

return std::make_unique<InputFile>(
std::make_unique<DataLogThread>(std::move(reader)));
std::make_unique<glass::DataLogReaderThread>(std::move(reader)));
}

void DisplayInputFiles() {
Expand Down Expand Up @@ -284,9 +284,10 @@ static bool EmitEntry(const std::string& name, Entry& entry) {
if (ImGui::IsItemHovered()) {
ImGui::BeginTooltip();
for (auto inputFile : entry.inputFiles) {
ImGui::Text(
"%s: %s", inputFile->stem.c_str(),
std::string{inputFile->datalog->GetEntry(entry.name).type}.c_str());
if (auto info = inputFile->datalog->GetEntry(entry.name)) {
ImGui::Text("%s: %s", inputFile->stem.c_str(),
std::string{info->type}.c_str());
}
}
ImGui::EndTooltip();
}
Expand All @@ -300,10 +301,10 @@ static bool EmitEntry(const std::string& name, Entry& entry) {
if (ImGui::IsItemHovered()) {
ImGui::BeginTooltip();
for (auto inputFile : entry.inputFiles) {
ImGui::Text(
"%s: %s", inputFile->stem.c_str(),
std::string{inputFile->datalog->GetEntry(entry.name).metadata}
.c_str());
if (auto info = inputFile->datalog->GetEntry(entry.name)) {
ImGui::Text("%s: %s", inputFile->stem.c_str(),
std::string{info->metadata}.c_str());
}
}
ImGui::EndTooltip();
}
Expand Down
124 changes: 124 additions & 0 deletions glass/src/lib/native/cpp/support/DataLogReaderThread.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
// Copyright (c) FIRST and other WPILib contributors.
// Open Source Software; you can modify and/or share it under the terms of
// the WPILib BSD license file in the root directory of this project.

#include "glass/support/DataLogReaderThread.h"

#include <utility>

#include <fmt/format.h>
#include <wpi/StringExtras.h>

using namespace glass;

DataLogReaderThread::~DataLogReaderThread() {
if (m_thread.joinable()) {
m_active = false;
m_thread.join();
}
}

void DataLogReaderThread::ReadMain() {
wpi::SmallDenseMap<
int, std::pair<DataLogReaderEntry*, std::span<const uint8_t>>, 8>
schemaEntries;

for (auto recordIt = m_reader.begin(), recordEnd = m_reader.end();
recordIt != recordEnd; ++recordIt) {
auto& record = *recordIt;
if (!m_active) {
break;
}
++m_numRecords;
if (record.IsStart()) {
DataLogReaderEntry data;
if (record.GetStartData(&data)) {
std::scoped_lock lock{m_mutex};
auto& entryPtr = m_entriesById[data.entry];
if (entryPtr) {
fmt::print("...DUPLICATE entry ID, overriding\n");
}
auto [it, isNew] = m_entriesByName.emplace(data.name, data);
if (isNew) {
it->second.ranges.emplace_back(recordIt, recordEnd);
}
entryPtr = &it->second;
if (data.type == "structschema" ||
data.type == "proto:FileDescriptorProto") {
schemaEntries.try_emplace(data.entry, entryPtr,
std::span<const uint8_t>{});
}
sigEntryAdded(data);
} else {
fmt::print("Start(INVALID)\n");
}
} else if (record.IsFinish()) {
int entry;
if (record.GetFinishEntry(&entry)) {
std::scoped_lock lock{m_mutex};
auto it = m_entriesById.find(entry);
if (it == m_entriesById.end()) {
fmt::print("...ID not found\n");
} else {
it->second->ranges.back().m_end = recordIt;
m_entriesById.erase(it);
}
} else {
fmt::print("Finish(INVALID)\n");
}
} else if (record.IsSetMetadata()) {
wpi::log::MetadataRecordData data;
if (record.GetSetMetadataData(&data)) {
std::scoped_lock lock{m_mutex};
auto it = m_entriesById.find(data.entry);
if (it == m_entriesById.end()) {
fmt::print("...ID not found\n");
} else {
it->second->metadata = data.metadata;
}
} else {
fmt::print("SetMetadata(INVALID)\n");
}
} else if (record.IsControl()) {
fmt::print("Unrecognized control record\n");
} else {
auto it = schemaEntries.find(record.GetEntry());
if (it != schemaEntries.end()) {
it->second.second = record.GetRaw();
}
}
}

// build schema databases
for (auto&& schemaPair : schemaEntries) {
auto name = schemaPair.second.first->name;
auto data = schemaPair.second.second;
if (data.empty()) {
continue;
}
if (wpi::starts_with(name, "NT:")) {
name = wpi::drop_front(name, 3);
}
if (wpi::starts_with(name, "/.schema/struct:")) {
auto typeStr = wpi::drop_front(name, 16);
std::string_view schema{reinterpret_cast<const char*>(data.data()),
data.size()};
std::string err;
auto desc = m_structDb.Add(typeStr, schema, &err);
if (!desc) {
fmt::print("could not decode struct '{}' schema '{}': {}\n", name,
schema, err);
}
} else if (wpi::starts_with(name, "/.schema/proto:")) {
// protobuf descriptor handling
auto filename = wpi::drop_front(name, 15);
if (!m_protoDb.Add(filename, data)) {
fmt::print("could not decode protobuf '{}' filename '{}'\n", name,
filename);
}
}
}

sigDone();
m_done = true;
}
Loading

0 comments on commit 7c26bc7

Please sign in to comment.