mirror of
https://github.com/wpilibsuite/allwpilib
synced 2026-06-19 00:41:43 +00:00
SCRIPT namespace replacements
This commit is contained in:
committed by
Peter Johnson
parent
ae6c043632
commit
9aca8e0fd6
@@ -64,7 +64,7 @@ static void DisplayDownload() {
|
||||
if (ImGui::Begin("Download", gDownloadVisible)) {
|
||||
if (!gDownloader) {
|
||||
gDownloader = std::make_unique<Downloader>(
|
||||
glass::GetStorageRoot().GetChild("download"));
|
||||
wpi::glass::GetStorageRoot().GetChild("download"));
|
||||
}
|
||||
gDownloader->Display();
|
||||
}
|
||||
@@ -74,7 +74,7 @@ static void DisplayDownload() {
|
||||
static void DisplayMainMenu() {
|
||||
ImGui::BeginMainMenuBar();
|
||||
|
||||
static glass::MainMenuBar mainMenu;
|
||||
static wpi::glass::MainMenuBar mainMenu;
|
||||
mainMenu.WorkspaceMenu();
|
||||
gui::EmitViewMenu();
|
||||
|
||||
@@ -110,7 +110,7 @@ static void DisplayMainMenu() {
|
||||
ImGui::Separator();
|
||||
ImGui::Text("v%s", GetWPILibVersion());
|
||||
ImGui::Separator();
|
||||
ImGui::Text("Save location: %s", glass::GetStorageDir().c_str());
|
||||
ImGui::Text("Save location: %s", wpi::glass::GetStorageDir().c_str());
|
||||
ImGui::Text("%.3f ms/frame (%.1f FPS)", 1000.0f / ImGui::GetIO().Framerate,
|
||||
ImGui::GetIO().Framerate);
|
||||
if (ImGui::Button("Close")) {
|
||||
@@ -124,7 +124,7 @@ static void DisplayGui() {
|
||||
DisplayMainMenu();
|
||||
DisplayInputFiles();
|
||||
DisplayEntries();
|
||||
DisplayOutput(glass::GetStorageRoot().GetChild("output"));
|
||||
DisplayOutput(wpi::glass::GetStorageRoot().GetChild("output"));
|
||||
DisplayDownload();
|
||||
}
|
||||
|
||||
@@ -132,7 +132,7 @@ void Application(std::string_view saveDir) {
|
||||
ssh_init();
|
||||
|
||||
gui::CreateContext();
|
||||
glass::CreateContext();
|
||||
wpi::glass::CreateContext();
|
||||
|
||||
// Add icons
|
||||
gui::AddIcon(dlt::GetResource_dlt_16_png());
|
||||
@@ -143,8 +143,8 @@ void Application(std::string_view saveDir) {
|
||||
gui::AddIcon(dlt::GetResource_dlt_256_png());
|
||||
gui::AddIcon(dlt::GetResource_dlt_512_png());
|
||||
|
||||
glass::SetStorageName("datalogtool");
|
||||
glass::SetStorageDir(saveDir.empty() ? gui::GetPlatformSaveFileDir()
|
||||
wpi::glass::SetStorageName("datalogtool");
|
||||
wpi::glass::SetStorageDir(saveDir.empty() ? gui::GetPlatformSaveFileDir()
|
||||
: saveDir);
|
||||
|
||||
gui::AddWindowScaler([](float scale) { gDefaultScale = scale; });
|
||||
@@ -152,12 +152,12 @@ void Application(std::string_view saveDir) {
|
||||
gui::Initialize("Datalog Tool", 925, 510);
|
||||
|
||||
gDownloadVisible =
|
||||
&glass::GetStorageRoot().GetChild("download").GetBool("visible", true);
|
||||
&wpi::glass::GetStorageRoot().GetChild("download").GetBool("visible", true);
|
||||
|
||||
gui::Main();
|
||||
|
||||
gShutdown = true;
|
||||
glass::DestroyContext();
|
||||
wpi::glass::DestroyContext();
|
||||
gui::DestroyContext();
|
||||
|
||||
gDownloader.reset();
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
#include "wpi/util/StringExtras.hpp"
|
||||
#include "wpi/util/fs.hpp"
|
||||
|
||||
Downloader::Downloader(glass::Storage& storage)
|
||||
Downloader::Downloader(wpi::glass::Storage& storage)
|
||||
: m_serverTeam{storage.GetString("serverTeam")},
|
||||
m_remoteDir{storage.GetString("remoteDir", "/home/systemcore/logs")},
|
||||
m_username{storage.GetString("username", "systemcore")},
|
||||
@@ -104,15 +104,15 @@ void Downloader::DisplayRemoteDirSelector() {
|
||||
for (auto&& dir : m_dirList) {
|
||||
if (ImGui::Selectable(dir.c_str())) {
|
||||
if (dir == "..") {
|
||||
if (wpi::ends_with(m_remoteDir, '/')) {
|
||||
if (wpi::util::ends_with(m_remoteDir, '/')) {
|
||||
m_remoteDir.resize(m_remoteDir.size() - 1);
|
||||
}
|
||||
m_remoteDir = wpi::rsplit(m_remoteDir, '/').first;
|
||||
m_remoteDir = wpi::util::rsplit(m_remoteDir, '/').first;
|
||||
if (m_remoteDir.empty()) {
|
||||
m_remoteDir = "/";
|
||||
}
|
||||
} else {
|
||||
if (!wpi::ends_with(m_remoteDir, '/')) {
|
||||
if (!wpi::util::ends_with(m_remoteDir, '/')) {
|
||||
m_remoteDir += '/';
|
||||
}
|
||||
m_remoteDir += dir;
|
||||
@@ -286,7 +286,7 @@ void Downloader::ThreadMain() {
|
||||
try {
|
||||
switch (m_state) {
|
||||
case kConnecting:
|
||||
if (auto team = wpi::parse_integer<unsigned int>(m_serverTeam, 10)) {
|
||||
if (auto team = wpi::util::parse_integer<unsigned int>(m_serverTeam, 10)) {
|
||||
// team number
|
||||
session = std::make_unique<sftp::Session>(
|
||||
fmt::format("roborio-{}-frc.local", team.value()), 22,
|
||||
@@ -335,7 +335,7 @@ void Downloader::ThreadMain() {
|
||||
}
|
||||
} else if (attr.type == SSH_FILEXFER_TYPE_REGULAR &&
|
||||
(attr.flags & SSH_FILEXFER_ATTR_SIZE) != 0 &&
|
||||
wpi::ends_with(attr.name, ".wpilog")) {
|
||||
wpi::util::ends_with(attr.name, ".wpilog")) {
|
||||
m_fileList.emplace_back(attr.name, attr.size);
|
||||
}
|
||||
}
|
||||
@@ -359,7 +359,7 @@ void Downloader::ThreadMain() {
|
||||
|
||||
auto remoteFilename = fmt::format(
|
||||
"{}{}{}", m_remoteDir,
|
||||
wpi::ends_with(m_remoteDir, '/') ? "" : "/", file.name);
|
||||
wpi::util::ends_with(m_remoteDir, '/') ? "" : "/", file.name);
|
||||
auto localFilename = fs::path{m_localDir} / file.name;
|
||||
uint64_t fileSize = file.size;
|
||||
|
||||
@@ -450,7 +450,7 @@ void Downloader::ThreadMain() {
|
||||
|
||||
auto remoteFilename = fmt::format(
|
||||
"{}{}{}", m_remoteDir,
|
||||
wpi::ends_with(m_remoteDir, '/') ? "" : "/", file.name);
|
||||
wpi::util::ends_with(m_remoteDir, '/') ? "" : "/", file.name);
|
||||
|
||||
lock.unlock();
|
||||
try {
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
#include "wpi/util/condition_variable.hpp"
|
||||
#include "wpi/util/mutex.hpp"
|
||||
|
||||
namespace glass {
|
||||
namespace wpi::glass {
|
||||
class Storage;
|
||||
} // namespace glass
|
||||
|
||||
@@ -22,7 +22,7 @@ class select_folder;
|
||||
|
||||
class Downloader {
|
||||
public:
|
||||
explicit Downloader(glass::Storage& storage);
|
||||
explicit Downloader(wpi::glass::Storage& storage);
|
||||
~Downloader();
|
||||
|
||||
void Display();
|
||||
@@ -36,7 +36,7 @@ class Downloader {
|
||||
|
||||
void ThreadMain();
|
||||
|
||||
wpi::mutex m_mutex;
|
||||
wpi::util::mutex m_mutex;
|
||||
enum State {
|
||||
kDisconnected,
|
||||
kConnecting,
|
||||
|
||||
@@ -84,7 +84,7 @@ struct EntryTreeNode {
|
||||
|
||||
static std::map<std::string, std::unique_ptr<InputFile>, std::less<>>
|
||||
gInputFiles;
|
||||
static wpi::mutex gEntriesMutex;
|
||||
static wpi::util::mutex gEntriesMutex;
|
||||
static std::map<std::string, std::unique_ptr<Entry>, std::less<>> gEntries;
|
||||
static std::vector<EntryTreeNode> gEntryTree;
|
||||
std::atomic_int gExportCount{0};
|
||||
@@ -92,17 +92,17 @@ std::atomic_int gExportCount{0};
|
||||
// must be called with gEntriesMutex held
|
||||
static void RebuildEntryTree() {
|
||||
gEntryTree.clear();
|
||||
wpi::SmallVector<std::string_view, 16> parts;
|
||||
wpi::util::SmallVector<std::string_view, 16> parts;
|
||||
for (auto& kv : gEntries) {
|
||||
parts.clear();
|
||||
// split on first : if one is present
|
||||
auto [prefix, mainpart] = wpi::split(kv.first, ':');
|
||||
if (mainpart.empty() || wpi::contains(prefix, '/')) {
|
||||
auto [prefix, mainpart] = wpi::util::split(kv.first, ':');
|
||||
if (mainpart.empty() || wpi::util::contains(prefix, '/')) {
|
||||
mainpart = kv.first;
|
||||
} else {
|
||||
parts.emplace_back(prefix);
|
||||
}
|
||||
wpi::split(mainpart, '/', -1, false,
|
||||
wpi::util::split(mainpart, '/', -1, false,
|
||||
[&](auto part) { parts.emplace_back(part); });
|
||||
|
||||
// ignore a raw "/" key
|
||||
@@ -112,7 +112,7 @@ static void RebuildEntryTree() {
|
||||
|
||||
// get to leaf
|
||||
auto nodes = &gEntryTree;
|
||||
for (auto part : wpi::drop_back(std::span{parts.begin(), parts.end()})) {
|
||||
for (auto part : wpi::util::drop_back(std::span{parts.begin(), parts.end()})) {
|
||||
auto it =
|
||||
std::find_if(nodes->begin(), nodes->end(),
|
||||
[&](const auto& node) { return node.name == part; });
|
||||
@@ -183,7 +183,7 @@ InputFile::~InputFile() {
|
||||
}
|
||||
|
||||
static std::unique_ptr<InputFile> LoadDataLog(std::string_view filename) {
|
||||
auto fileBuffer = wpi::MemoryBuffer::GetFile(filename);
|
||||
auto fileBuffer = wpi::util::MemoryBuffer::GetFile(filename);
|
||||
if (!fileBuffer) {
|
||||
return std::make_unique<InputFile>(
|
||||
filename,
|
||||
@@ -436,46 +436,46 @@ void DisplayEntries() {
|
||||
ImGui::End();
|
||||
}
|
||||
|
||||
static wpi::mutex gExportMutex;
|
||||
static wpi::util::mutex gExportMutex;
|
||||
static std::vector<std::string> gExportErrors;
|
||||
|
||||
static void PrintEscapedCsvString(wpi::raw_ostream& os, std::string_view str) {
|
||||
static void PrintEscapedCsvString(wpi::util::raw_ostream& os, std::string_view str) {
|
||||
auto s = str;
|
||||
while (!s.empty()) {
|
||||
std::string_view fragment;
|
||||
std::tie(fragment, s) = wpi::split(s, '"');
|
||||
std::tie(fragment, s) = wpi::util::split(s, '"');
|
||||
os << fragment;
|
||||
if (!s.empty()) {
|
||||
os << '"' << '"';
|
||||
}
|
||||
}
|
||||
if (wpi::ends_with(str, '"')) {
|
||||
if (wpi::util::ends_with(str, '"')) {
|
||||
os << '"' << '"';
|
||||
}
|
||||
}
|
||||
|
||||
static void ValueToCsv(wpi::raw_ostream& os, const Entry& entry,
|
||||
static void ValueToCsv(wpi::util::raw_ostream& os, const Entry& entry,
|
||||
const wpi::log::DataLogRecord& record) {
|
||||
// handle systemTime specially
|
||||
if (entry.name == "systemTime" && entry.type == "int64") {
|
||||
int64_t val;
|
||||
if (record.GetInteger(&val)) {
|
||||
std::time_t timeval = val / 1000000;
|
||||
wpi::print(os, "{:%Y-%m-%d %H:%M:%S}.{:06}", *std::localtime(&timeval),
|
||||
wpi::util::print(os, "{:%Y-%m-%d %H:%M:%S}.{:06}", *std::localtime(&timeval),
|
||||
val % 1000000);
|
||||
return;
|
||||
}
|
||||
} else if (entry.type == "double") {
|
||||
double val;
|
||||
if (record.GetDouble(&val)) {
|
||||
wpi::print(os, "{}", val);
|
||||
wpi::util::print(os, "{}", val);
|
||||
return;
|
||||
}
|
||||
} else if (entry.type == "int64" || entry.type == "int") {
|
||||
// support "int" for compatibility with old NT4 datalogs
|
||||
int64_t val;
|
||||
if (record.GetInteger(&val)) {
|
||||
wpi::print(os, "{}", val);
|
||||
wpi::util::print(os, "{}", val);
|
||||
return;
|
||||
}
|
||||
} else if (entry.type == "string" || entry.type == "json") {
|
||||
@@ -488,31 +488,31 @@ static void ValueToCsv(wpi::raw_ostream& os, const Entry& entry,
|
||||
} else if (entry.type == "boolean") {
|
||||
bool val;
|
||||
if (record.GetBoolean(&val)) {
|
||||
wpi::print(os, "{}", val);
|
||||
wpi::util::print(os, "{}", val);
|
||||
return;
|
||||
}
|
||||
} else if (entry.type == "boolean[]") {
|
||||
std::vector<int> val;
|
||||
if (record.GetBooleanArray(&val)) {
|
||||
wpi::print(os, "{}", fmt::join(val, ";"));
|
||||
wpi::util::print(os, "{}", fmt::join(val, ";"));
|
||||
return;
|
||||
}
|
||||
} else if (entry.type == "double[]") {
|
||||
std::vector<double> val;
|
||||
if (record.GetDoubleArray(&val)) {
|
||||
wpi::print(os, "{}", fmt::join(val, ";"));
|
||||
wpi::util::print(os, "{}", fmt::join(val, ";"));
|
||||
return;
|
||||
}
|
||||
} else if (entry.type == "float[]") {
|
||||
std::vector<float> val;
|
||||
if (record.GetFloatArray(&val)) {
|
||||
wpi::print(os, "{}", fmt::join(val, ";"));
|
||||
wpi::util::print(os, "{}", fmt::join(val, ";"));
|
||||
return;
|
||||
}
|
||||
} else if (entry.type == "int64[]") {
|
||||
std::vector<int64_t> val;
|
||||
if (record.GetIntegerArray(&val)) {
|
||||
wpi::print(os, "{}", fmt::join(val, ";"));
|
||||
wpi::util::print(os, "{}", fmt::join(val, ";"));
|
||||
return;
|
||||
}
|
||||
} else if (entry.type == "string[]") {
|
||||
@@ -531,10 +531,10 @@ static void ValueToCsv(wpi::raw_ostream& os, const Entry& entry,
|
||||
return;
|
||||
}
|
||||
}
|
||||
wpi::print(os, "<invalid>");
|
||||
wpi::util::print(os, "<invalid>");
|
||||
}
|
||||
|
||||
static void ExportCsvFile(InputFile& f, wpi::raw_ostream& os, int style) {
|
||||
static void ExportCsvFile(InputFile& f, wpi::util::raw_ostream& os, int style) {
|
||||
// header
|
||||
if (style == 0) {
|
||||
os << "Timestamp,Name,Value\n";
|
||||
@@ -556,7 +556,7 @@ static void ExportCsvFile(InputFile& f, wpi::raw_ostream& os, int style) {
|
||||
os << '\n';
|
||||
}
|
||||
|
||||
wpi::DenseMap<int, Entry*> nameMap;
|
||||
wpi::util::DenseMap<int, Entry*> nameMap;
|
||||
for (auto&& record : f.datalog->GetReader()) {
|
||||
if (record.IsStart()) {
|
||||
wpi::log::StartRecordData data;
|
||||
@@ -579,13 +579,13 @@ static void ExportCsvFile(InputFile& f, wpi::raw_ostream& os, int style) {
|
||||
Entry* entry = entryIt->second;
|
||||
|
||||
if (style == 0) {
|
||||
wpi::print(os, "{},\"", record.GetTimestamp() / 1000000.0);
|
||||
wpi::util::print(os, "{},\"", record.GetTimestamp() / 1000000.0);
|
||||
PrintEscapedCsvString(os, entry->name);
|
||||
os << '"' << ',';
|
||||
ValueToCsv(os, *entry, record);
|
||||
os << '\n';
|
||||
} else if (style == 1 && entry->column != -1) {
|
||||
wpi::print(os, "{},", record.GetTimestamp() / 1000000.0);
|
||||
wpi::util::print(os, "{},", record.GetTimestamp() / 1000000.0);
|
||||
for (int i = 0; i < entry->column; ++i) {
|
||||
os << ',';
|
||||
}
|
||||
@@ -611,14 +611,14 @@ static void ExportCsv(std::string_view outputFolder, int style) {
|
||||
++gExportCount;
|
||||
continue;
|
||||
}
|
||||
wpi::raw_fd_ostream os{fs::FileToFd(of, ec, fs::OF_Text), true};
|
||||
wpi::util::raw_fd_ostream os{fs::FileToFd(of, ec, fs::OF_Text), true};
|
||||
ExportCsvFile(*f.second, os, style);
|
||||
}
|
||||
++gExportCount;
|
||||
}
|
||||
}
|
||||
|
||||
void DisplayOutput(glass::Storage& storage) {
|
||||
void DisplayOutput(wpi::glass::Storage& storage) {
|
||||
static std::string& outputFolder = storage.GetString("outputFolder");
|
||||
static std::unique_ptr<pfd::select_folder> outputFolderSelector;
|
||||
|
||||
|
||||
@@ -4,12 +4,12 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace glass {
|
||||
namespace wpi::glass {
|
||||
class Storage;
|
||||
} // namespace glass
|
||||
|
||||
void DisplayInputFiles();
|
||||
void DisplayEntries();
|
||||
void DisplayOutput(glass::Storage& storage);
|
||||
void DisplayOutput(wpi::glass::Storage& storage);
|
||||
|
||||
extern bool gShutdown;
|
||||
|
||||
@@ -34,21 +34,21 @@ std::string_view GetResource_ov_256_png();
|
||||
std::string_view GetResource_ov_512_png();
|
||||
} // namespace ov
|
||||
|
||||
static std::unique_ptr<glass::NetworkTablesModel> gModel;
|
||||
static std::unique_ptr<glass::NetworkTablesSettings> gSettings;
|
||||
static glass::LogData gLog;
|
||||
static glass::NetworkTablesFlagsSettings gFlagsSettings;
|
||||
static glass::MainMenuBar gMainMenu;
|
||||
static std::unique_ptr<wpi::glass::NetworkTablesModel> gModel;
|
||||
static std::unique_ptr<wpi::glass::NetworkTablesSettings> gSettings;
|
||||
static wpi::glass::LogData gLog;
|
||||
static wpi::glass::NetworkTablesFlagsSettings gFlagsSettings;
|
||||
static wpi::glass::MainMenuBar gMainMenu;
|
||||
static unsigned int gPrevMode = NT_NET_MODE_NONE;
|
||||
|
||||
/**
|
||||
* Generates the proper title bar title based on current instance state and
|
||||
* event.
|
||||
*/
|
||||
static std::string MakeTitle(NT_Inst inst, nt::Event event) {
|
||||
auto mode = nt::GetNetworkMode(inst);
|
||||
static std::string MakeTitle(NT_Inst inst, wpi::nt::Event event) {
|
||||
auto mode = wpi::nt::GetNetworkMode(inst);
|
||||
if (mode & NT_NET_MODE_SERVER) {
|
||||
auto numClients = nt::GetConnections(inst).size();
|
||||
auto numClients = wpi::nt::GetConnections(inst).size();
|
||||
return fmt::format("OutlineViewer - {} Client{} Connected", numClients,
|
||||
(numClients == 1 ? "" : "s"));
|
||||
} else if (mode & NT_NET_MODE_CLIENT) {
|
||||
@@ -61,22 +61,22 @@ static std::string MakeTitle(NT_Inst inst, nt::Event event) {
|
||||
}
|
||||
|
||||
static void NtInitialize() {
|
||||
auto inst = nt::GetDefaultInstance();
|
||||
auto poller = nt::CreateListenerPoller(inst);
|
||||
nt::AddPolledListener(poller, inst, NT_EVENT_CONNECTION | NT_EVENT_IMMEDIATE);
|
||||
nt::AddPolledLogger(poller, NT_LOG_INFO, 100);
|
||||
auto inst = wpi::nt::GetDefaultInstance();
|
||||
auto poller = wpi::nt::CreateListenerPoller(inst);
|
||||
wpi::nt::AddPolledListener(poller, inst, NT_EVENT_CONNECTION | NT_EVENT_IMMEDIATE);
|
||||
wpi::nt::AddPolledLogger(poller, NT_LOG_INFO, 100);
|
||||
gui::AddEarlyExecute([inst, poller] {
|
||||
auto win = gui::GetSystemWindow();
|
||||
if (!win) {
|
||||
return;
|
||||
}
|
||||
bool updateTitle = false;
|
||||
nt::Event connectionEvent;
|
||||
if (nt::GetNetworkMode(inst) != gPrevMode) {
|
||||
gPrevMode = nt::GetNetworkMode(inst);
|
||||
wpi::nt::Event connectionEvent;
|
||||
if (wpi::nt::GetNetworkMode(inst) != gPrevMode) {
|
||||
gPrevMode = wpi::nt::GetNetworkMode(inst);
|
||||
updateTitle = true;
|
||||
}
|
||||
for (auto&& event : nt::ReadListenerQueue(poller)) {
|
||||
for (auto&& event : wpi::nt::ReadListenerQueue(poller)) {
|
||||
if (event.Is(NT_EVENT_CONNECTION)) {
|
||||
updateTitle = true;
|
||||
connectionEvent = event;
|
||||
@@ -101,13 +101,13 @@ static void NtInitialize() {
|
||||
});
|
||||
|
||||
// NetworkTables table window
|
||||
gModel = std::make_unique<glass::NetworkTablesModel>();
|
||||
gModel = std::make_unique<wpi::glass::NetworkTablesModel>();
|
||||
gui::AddEarlyExecute([] { gModel->Update(); });
|
||||
|
||||
// NetworkTables settings window
|
||||
gSettings = std::make_unique<glass::NetworkTablesSettings>(
|
||||
gSettings = std::make_unique<wpi::glass::NetworkTablesSettings>(
|
||||
"outlineviewer",
|
||||
glass::GetStorageRoot().GetChild("NetworkTables Settings"));
|
||||
wpi::glass::GetStorageRoot().GetChild("NetworkTables Settings"));
|
||||
gui::AddEarlyExecute([] { gSettings->Update(); });
|
||||
}
|
||||
|
||||
@@ -139,7 +139,7 @@ static void DisplayGui() {
|
||||
gui::EmitViewMenu();
|
||||
if (ImGui::BeginMenu("View")) {
|
||||
gFlagsSettings.DisplayMenu();
|
||||
glass::DisplayNetworkTablesAddMenu(gModel.get());
|
||||
wpi::glass::DisplayNetworkTablesAddMenu(gModel.get());
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
|
||||
@@ -197,7 +197,7 @@ static void DisplayGui() {
|
||||
ImGui::CloseCurrentPopup();
|
||||
}
|
||||
ImGui::BeginChild("Lines", ImVec2(width * 0.75f, height * 0.75f));
|
||||
glass::DisplayLog(&gLog, true);
|
||||
wpi::glass::DisplayLog(&gLog, true);
|
||||
ImGui::EndChild();
|
||||
ImGui::EndPopup();
|
||||
}
|
||||
@@ -212,7 +212,7 @@ static void DisplayGui() {
|
||||
ImGui::Separator();
|
||||
ImGui::Text("v%s", GetWPILibVersion());
|
||||
ImGui::Separator();
|
||||
ImGui::Text("Save location: %s", glass::GetStorageDir().c_str());
|
||||
ImGui::Text("Save location: %s", wpi::glass::GetStorageDir().c_str());
|
||||
ImGui::Text("%.3f ms/frame (%.1f FPS)", 1000.0f / ImGui::GetIO().Framerate,
|
||||
ImGui::GetIO().Framerate);
|
||||
if (ImGui::Button("Close")) {
|
||||
@@ -222,9 +222,9 @@ static void DisplayGui() {
|
||||
}
|
||||
|
||||
// display table view
|
||||
glass::DisplayNetworkTablesInfo(gModel.get());
|
||||
wpi::glass::DisplayNetworkTablesInfo(gModel.get());
|
||||
ImGui::Separator();
|
||||
glass::DisplayNetworkTables(gModel.get(), gFlagsSettings.GetFlags());
|
||||
wpi::glass::DisplayNetworkTables(gModel.get(), gFlagsSettings.GetFlags());
|
||||
|
||||
ImGui::End();
|
||||
}
|
||||
@@ -243,7 +243,7 @@ int main(int argc, char** argv) {
|
||||
}
|
||||
|
||||
gui::CreateContext();
|
||||
glass::CreateContext();
|
||||
wpi::glass::CreateContext();
|
||||
|
||||
gui::AddIcon(ov::GetResource_ov_16_png());
|
||||
gui::AddIcon(ov::GetResource_ov_32_png());
|
||||
@@ -253,8 +253,8 @@ int main(int argc, char** argv) {
|
||||
gui::AddIcon(ov::GetResource_ov_256_png());
|
||||
gui::AddIcon(ov::GetResource_ov_512_png());
|
||||
|
||||
glass::SetStorageName("outlineviewer");
|
||||
glass::SetStorageDir(saveDir.empty() ? gui::GetPlatformSaveFileDir()
|
||||
wpi::glass::SetStorageName("outlineviewer");
|
||||
wpi::glass::SetStorageDir(saveDir.empty() ? gui::GetPlatformSaveFileDir()
|
||||
: saveDir);
|
||||
|
||||
gui::AddInit(NtInitialize);
|
||||
@@ -267,7 +267,7 @@ int main(int argc, char** argv) {
|
||||
gModel.reset();
|
||||
gSettings.reset();
|
||||
|
||||
glass::DestroyContext();
|
||||
wpi::glass::DestroyContext();
|
||||
gui::DestroyContext();
|
||||
|
||||
return 0;
|
||||
|
||||
@@ -31,16 +31,16 @@
|
||||
|
||||
namespace gui = wpi::gui;
|
||||
|
||||
static std::unique_ptr<glass::WindowManager> gWindowManager;
|
||||
static std::unique_ptr<wpi::glass::WindowManager> gWindowManager;
|
||||
|
||||
glass::Window* gLogLoaderWindow;
|
||||
glass::Window* gDataSelectorWindow;
|
||||
glass::Window* gAnalyzerWindow;
|
||||
glass::Window* gProgramLogWindow;
|
||||
static glass::MainMenuBar gMainMenu;
|
||||
wpi::glass::Window* gLogLoaderWindow;
|
||||
wpi::glass::Window* gDataSelectorWindow;
|
||||
wpi::glass::Window* gAnalyzerWindow;
|
||||
wpi::glass::Window* gProgramLogWindow;
|
||||
static wpi::glass::MainMenuBar gMainMenu;
|
||||
|
||||
glass::LogData gLog;
|
||||
wpi::Logger gLogger;
|
||||
wpi::glass::LogData gLog;
|
||||
wpi::util::Logger gLogger;
|
||||
|
||||
const char* GetWPILibVersion();
|
||||
|
||||
@@ -57,7 +57,7 @@ std::string_view GetResource_sysid_512_png();
|
||||
void Application(std::string_view saveDir) {
|
||||
// Create the wpigui (along with Dear ImGui) and Glass contexts.
|
||||
gui::CreateContext();
|
||||
glass::CreateContext();
|
||||
wpi::glass::CreateContext();
|
||||
|
||||
// Add icons
|
||||
gui::AddIcon(sysid::GetResource_sysid_16_png());
|
||||
@@ -68,37 +68,37 @@ void Application(std::string_view saveDir) {
|
||||
gui::AddIcon(sysid::GetResource_sysid_256_png());
|
||||
gui::AddIcon(sysid::GetResource_sysid_512_png());
|
||||
|
||||
glass::SetStorageName("sysid");
|
||||
glass::SetStorageDir(saveDir.empty() ? gui::GetPlatformSaveFileDir()
|
||||
wpi::glass::SetStorageName("sysid");
|
||||
wpi::glass::SetStorageDir(saveDir.empty() ? gui::GetPlatformSaveFileDir()
|
||||
: saveDir);
|
||||
|
||||
// Add messages from the global sysid logger into the Log window.
|
||||
gLogger.SetLogger([](unsigned int level, const char* file, unsigned int line,
|
||||
const char* msg) {
|
||||
const char* lvl = "";
|
||||
if (level >= wpi::WPI_LOG_CRITICAL) {
|
||||
if (level >= wpi::util::WPI_LOG_CRITICAL) {
|
||||
lvl = "CRITICAL: ";
|
||||
} else if (level >= wpi::WPI_LOG_ERROR) {
|
||||
} else if (level >= wpi::util::WPI_LOG_ERROR) {
|
||||
lvl = "ERROR: ";
|
||||
} else if (level >= wpi::WPI_LOG_WARNING) {
|
||||
} else if (level >= wpi::util::WPI_LOG_WARNING) {
|
||||
lvl = "WARNING: ";
|
||||
} else if (level >= wpi::WPI_LOG_INFO) {
|
||||
} else if (level >= wpi::util::WPI_LOG_INFO) {
|
||||
lvl = "INFO: ";
|
||||
} else if (level >= wpi::WPI_LOG_DEBUG) {
|
||||
} else if (level >= wpi::util::WPI_LOG_DEBUG) {
|
||||
lvl = "DEBUG: ";
|
||||
}
|
||||
std::string filename = std::filesystem::path{file}.filename().string();
|
||||
gLog.Append(fmt::format("{}{} ({}:{})\n", lvl, msg, filename, line));
|
||||
#ifndef NDEBUG
|
||||
wpi::print(stderr, "{}{} ({}:{})\n", lvl, msg, filename, line);
|
||||
wpi::util::print(stderr, "{}{} ({}:{})\n", lvl, msg, filename, line);
|
||||
#endif
|
||||
});
|
||||
|
||||
gLogger.set_min_level(wpi::WPI_LOG_DEBUG);
|
||||
gLogger.set_min_level(wpi::util::WPI_LOG_DEBUG);
|
||||
|
||||
// Initialize window manager and add views.
|
||||
auto& storage = glass::GetStorageRoot().GetChild("SysId");
|
||||
gWindowManager = std::make_unique<glass::WindowManager>(storage);
|
||||
auto& storage = wpi::glass::GetStorageRoot().GetChild("SysId");
|
||||
gWindowManager = std::make_unique<wpi::glass::WindowManager>(storage);
|
||||
gWindowManager->GlobalInit();
|
||||
|
||||
auto logLoader = std::make_unique<sysid::LogLoader>(storage, gLogger);
|
||||
@@ -122,7 +122,7 @@ void Application(std::string_view saveDir) {
|
||||
gAnalyzerWindow = gWindowManager->AddWindow("Analyzer", std::move(analyzer));
|
||||
|
||||
gProgramLogWindow = gWindowManager->AddWindow(
|
||||
"Program Log", std::make_unique<glass::LogView>(&gLog));
|
||||
"Program Log", std::make_unique<wpi::glass::LogView>(&gLog));
|
||||
|
||||
// Set default positions and sizes for windows.
|
||||
|
||||
@@ -194,7 +194,7 @@ void Application(std::string_view saveDir) {
|
||||
ImGui::Separator();
|
||||
ImGui::Text("v%s", GetWPILibVersion());
|
||||
ImGui::Separator();
|
||||
ImGui::Text("Save location: %s", glass::GetStorageDir().c_str());
|
||||
ImGui::Text("Save location: %s", wpi::glass::GetStorageDir().c_str());
|
||||
if (ImGui::Button("Close")) {
|
||||
ImGui::CloseCurrentPopup();
|
||||
}
|
||||
@@ -206,7 +206,7 @@ void Application(std::string_view saveDir) {
|
||||
sysid::kAppWindowSize.y);
|
||||
gui::Main();
|
||||
|
||||
glass::DestroyContext();
|
||||
wpi::glass::DestroyContext();
|
||||
gui::DestroyContext();
|
||||
}
|
||||
|
||||
|
||||
@@ -67,7 +67,7 @@ void sysid::SaveFile(std::string_view contents,
|
||||
// Open a fd_ostream to write to file.
|
||||
std::error_code ec;
|
||||
// NOLINTNEXTLINE(build/include_what_you_use)
|
||||
wpi::raw_fd_ostream ostream{path.string(), ec};
|
||||
wpi::util::raw_fd_ostream ostream{path.string(), ec};
|
||||
|
||||
// Check error code.
|
||||
if (ec) {
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
|
||||
using namespace sysid;
|
||||
|
||||
static double Lerp(units::second_t time,
|
||||
static double Lerp(wpi::units::second_t time,
|
||||
std::vector<MotorData::Run::Sample<double>>& data) {
|
||||
auto next = std::find_if(data.begin(), data.end(), [&](const auto& entry) {
|
||||
return entry.time > time;
|
||||
@@ -36,7 +36,7 @@ static double Lerp(units::second_t time,
|
||||
|
||||
const auto prev = next - 1;
|
||||
|
||||
return wpi::Lerp(prev->measurement, next->measurement,
|
||||
return wpi::util::Lerp(prev->measurement, next->measurement,
|
||||
(time - prev->time) / (next->time - prev->time));
|
||||
}
|
||||
|
||||
@@ -79,21 +79,21 @@ static std::vector<PreparedData> ConvertToPrepared(const MotorData& data) {
|
||||
|
||||
/**
|
||||
* To preserve a raw copy of the data, this method saves a raw version
|
||||
* in the dataset StringMap where the key of the raw data starts with "raw-"
|
||||
* in the dataset wpi::util::StringMap where the key of the raw data starts with "raw-"
|
||||
* before the name of the original data.
|
||||
*
|
||||
* @tparam S The size of the array data that's being used
|
||||
*
|
||||
* @param dataset A reference to the dataset being used
|
||||
*/
|
||||
static void CopyRawData(wpi::StringMap<MotorData>* dataset) {
|
||||
static void CopyRawData(wpi::util::StringMap<MotorData>* dataset) {
|
||||
auto& data = *dataset;
|
||||
// Loads the Raw Data
|
||||
for (auto& it : data) {
|
||||
auto& key = it.first;
|
||||
auto& motorData = it.second;
|
||||
|
||||
if (!wpi::contains(key, "raw")) {
|
||||
if (!wpi::util::contains(key, "raw")) {
|
||||
data[fmt::format("raw-{}", key)] = motorData;
|
||||
data[fmt::format("original-raw-{}", key)] = motorData;
|
||||
}
|
||||
@@ -116,7 +116,7 @@ static Storage CombineDatasets(const std::vector<PreparedData>& slowForward,
|
||||
}
|
||||
|
||||
void AnalysisManager::PrepareGeneralData() {
|
||||
wpi::StringMap<std::vector<PreparedData>> preparedData;
|
||||
wpi::util::StringMap<std::vector<PreparedData>> preparedData;
|
||||
|
||||
WPI_INFO(m_logger, "{}", "Preprocessing raw data.");
|
||||
|
||||
@@ -167,11 +167,11 @@ void AnalysisManager::PrepareGeneralData() {
|
||||
preparedData["raw-dynamic-reverse"][0].timestamp};
|
||||
}
|
||||
|
||||
AnalysisManager::AnalysisManager(Settings& settings, wpi::Logger& logger)
|
||||
AnalysisManager::AnalysisManager(Settings& settings, wpi::util::Logger& logger)
|
||||
: m_logger{logger}, m_settings{settings} {}
|
||||
|
||||
AnalysisManager::AnalysisManager(TestData data, Settings& settings,
|
||||
wpi::Logger& logger)
|
||||
wpi::util::Logger& logger)
|
||||
: m_data{std::move(data)}, m_logger{logger}, m_settings{settings} {
|
||||
// Reset settings for Dynamic Test Limits
|
||||
m_settings.stepTestDuration = 0_s;
|
||||
|
||||
@@ -27,13 +27,13 @@ ArmSim::ArmSim(double Ks, double Kv, double Ka, double Kg, double offset,
|
||||
Reset(initialPosition, initialVelocity);
|
||||
}
|
||||
|
||||
void ArmSim::Update(units::volt_t voltage, units::second_t dt) {
|
||||
void ArmSim::Update(wpi::units::volt_t voltage, wpi::units::second_t dt) {
|
||||
// Returns arm acceleration under gravity
|
||||
auto f = [=, this](
|
||||
const Eigen::Vector<double, 2>& x,
|
||||
const Eigen::Vector<double, 1>& u) -> Eigen::Vector<double, 2> {
|
||||
return Eigen::Vector<double, 2>{
|
||||
x(1), (m_A * x.block<1, 1>(1, 0) + m_B * u + m_c * wpi::sgn(x(1)) +
|
||||
x(1), (m_A * x.block<1, 1>(1, 0) + m_B * u + m_c * wpi::util::sgn(x(1)) +
|
||||
m_d * std::cos(x(0) + m_offset))(0)};
|
||||
};
|
||||
|
||||
@@ -42,7 +42,7 @@ void ArmSim::Update(units::volt_t voltage, units::second_t dt) {
|
||||
// small for ill-conditioned data (e.g., high velocities with sharp spikes in
|
||||
// acceleration).
|
||||
Eigen::Vector<double, 1> u{voltage.value()};
|
||||
m_x = frc::RKDP(f, m_x, u, dt, 0.25);
|
||||
m_x = wpi::math::RKDP(f, m_x, u, dt, 0.25);
|
||||
}
|
||||
|
||||
double ArmSim::GetPosition() const {
|
||||
@@ -53,10 +53,10 @@ double ArmSim::GetVelocity() const {
|
||||
return m_x(1);
|
||||
}
|
||||
|
||||
double ArmSim::GetAcceleration(units::volt_t voltage) const {
|
||||
double ArmSim::GetAcceleration(wpi::units::volt_t voltage) const {
|
||||
Eigen::Vector<double, 1> u{voltage.value()};
|
||||
return (m_A * m_x.block<1, 1>(1, 0) + m_B * u +
|
||||
m_c * wpi::sgn(GetVelocity()) + m_d * std::cos(m_x(0) + m_offset))(0);
|
||||
m_c * wpi::util::sgn(GetVelocity()) + m_d * std::cos(m_x(0) + m_offset))(0);
|
||||
}
|
||||
|
||||
void ArmSim::Reset(double position, double velocity) {
|
||||
|
||||
@@ -20,16 +20,16 @@ ElevatorSim::ElevatorSim(double Ks, double Kv, double Ka, double Kg,
|
||||
Reset(initialPosition, initialVelocity);
|
||||
}
|
||||
|
||||
void ElevatorSim::Update(units::volt_t voltage, units::second_t dt) {
|
||||
void ElevatorSim::Update(wpi::units::volt_t voltage, wpi::units::second_t dt) {
|
||||
Eigen::Vector<double, 1> u{voltage.value()};
|
||||
|
||||
// Given dx/dt = Ax + Bu + c sgn(x) + d,
|
||||
// x_k+1 = e^(AT) x_k + A^-1 (e^(AT) - 1) (Bu + c sgn(x) + d)
|
||||
Eigen::Matrix<double, 2, 2> Ad;
|
||||
Eigen::Matrix<double, 2, 1> Bd;
|
||||
frc::DiscretizeAB<2, 1>(m_A, m_B, dt, &Ad, &Bd);
|
||||
wpi::math::DiscretizeAB<2, 1>(m_A, m_B, dt, &Ad, &Bd);
|
||||
m_x = Ad * m_x + Bd * u +
|
||||
Bd * m_B.householderQr().solve(m_c * wpi::sgn(GetVelocity()) + m_d);
|
||||
Bd * m_B.householderQr().solve(m_c * wpi::util::sgn(GetVelocity()) + m_d);
|
||||
}
|
||||
|
||||
double ElevatorSim::GetPosition() const {
|
||||
@@ -40,9 +40,9 @@ double ElevatorSim::GetVelocity() const {
|
||||
return m_x(1);
|
||||
}
|
||||
|
||||
double ElevatorSim::GetAcceleration(units::volt_t voltage) const {
|
||||
double ElevatorSim::GetAcceleration(wpi::units::volt_t voltage) const {
|
||||
Eigen::Vector<double, 1> u{voltage.value()};
|
||||
return (m_A * m_x + m_B * u + m_c * wpi::sgn(GetVelocity()) + m_d)(1);
|
||||
return (m_A * m_x + m_B * u + m_c * wpi::util::sgn(GetVelocity()) + m_d)(1);
|
||||
}
|
||||
|
||||
void ElevatorSim::Reset(double position, double velocity) {
|
||||
|
||||
@@ -32,10 +32,10 @@ FeedbackGains sysid::CalculatePositionFeedbackGains(
|
||||
// instabilities in the LQR.
|
||||
if (std::abs(Ka) < 1e-7) {
|
||||
// System has position state and velocity input
|
||||
frc::LinearSystem<1, 1, 1> system{Matrix1d{0.0}, Matrix1d{1.0},
|
||||
wpi::math::LinearSystem<1, 1, 1> system{Matrix1d{0.0}, Matrix1d{1.0},
|
||||
Matrix1d{1.0}, Matrix1d{0.0}};
|
||||
|
||||
frc::LinearQuadraticRegulator<1, 1> controller{
|
||||
wpi::math::LinearQuadraticRegulator<1, 1> controller{
|
||||
system, {params.qp}, {params.r}, preset.period};
|
||||
controller.LatencyCompensate(system, preset.period,
|
||||
preset.measurementDelay);
|
||||
@@ -43,16 +43,16 @@ FeedbackGains sysid::CalculatePositionFeedbackGains(
|
||||
return {Kv * controller.K(0, 0) * preset.outputConversionFactor, 0.0};
|
||||
}
|
||||
|
||||
auto system = frc::LinearSystemId::IdentifyPositionSystem<units::meters>(
|
||||
auto system = wpi::math::LinearSystemId::IdentifyPositionSystem<wpi::units::meters>(
|
||||
Kv_t{Kv}, Ka_t{Ka});
|
||||
|
||||
frc::LinearQuadraticRegulator<2, 1> controller{
|
||||
wpi::math::LinearQuadraticRegulator<2, 1> controller{
|
||||
system, {params.qp, params.qv}, {params.r}, preset.period};
|
||||
controller.LatencyCompensate(system, preset.period, preset.measurementDelay);
|
||||
|
||||
return {controller.K(0, 0) * preset.outputConversionFactor,
|
||||
controller.K(0, 1) * preset.outputConversionFactor /
|
||||
(preset.normalized ? 1 : units::second_t{preset.period}.value())};
|
||||
(preset.normalized ? 1 : wpi::units::second_t{preset.period}.value())};
|
||||
}
|
||||
|
||||
FeedbackGains sysid::CalculateVelocityFeedbackGains(
|
||||
@@ -69,9 +69,9 @@ FeedbackGains sysid::CalculateVelocityFeedbackGains(
|
||||
return {0.0, 0.0};
|
||||
}
|
||||
|
||||
auto system = frc::LinearSystemId::IdentifyVelocitySystem<units::meters>(
|
||||
auto system = wpi::math::LinearSystemId::IdentifyVelocitySystem<wpi::units::meters>(
|
||||
Kv_t{Kv}, Ka_t{Ka});
|
||||
frc::LinearQuadraticRegulator<1, 1> controller{
|
||||
wpi::math::LinearQuadraticRegulator<1, 1> controller{
|
||||
system, {params.qv}, {params.r}, preset.period};
|
||||
controller.LatencyCompensate(system, preset.period, preset.measurementDelay);
|
||||
|
||||
|
||||
@@ -49,7 +49,7 @@ static void CheckSize(const std::vector<PreparedData>& data, size_t window,
|
||||
* @return True, if the key corresponds to a raw dataset.
|
||||
*/
|
||||
static bool IsRaw(std::string_view key) {
|
||||
return wpi::contains(key, "raw") && !wpi::contains(key, "original");
|
||||
return wpi::util::contains(key, "raw") && !wpi::util::contains(key, "original");
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -60,7 +60,7 @@ static bool IsRaw(std::string_view key) {
|
||||
* @return True, if the key corresponds to a filtered dataset.
|
||||
*/
|
||||
static bool IsFiltered(std::string_view key) {
|
||||
return !wpi::contains(key, "raw") && !wpi::contains(key, "original");
|
||||
return !wpi::util::contains(key, "raw") && !wpi::util::contains(key, "original");
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -116,16 +116,16 @@ static void PrepareMechData(std::vector<PreparedData>* data,
|
||||
}
|
||||
}
|
||||
|
||||
std::tuple<units::second_t, units::second_t, units::second_t>
|
||||
std::tuple<wpi::units::second_t, wpi::units::second_t, wpi::units::second_t>
|
||||
sysid::TrimStepVoltageData(std::vector<PreparedData>* data,
|
||||
AnalysisManager::Settings* settings,
|
||||
units::second_t minStepTime,
|
||||
units::second_t maxStepTime) {
|
||||
wpi::units::second_t minStepTime,
|
||||
wpi::units::second_t maxStepTime) {
|
||||
auto voltageBegins =
|
||||
std::find_if(data->begin(), data->end(),
|
||||
[](auto& datum) { return std::abs(datum.voltage) > 0; });
|
||||
|
||||
units::second_t firstTimestamp = voltageBegins->timestamp;
|
||||
wpi::units::second_t firstTimestamp = voltageBegins->timestamp;
|
||||
double firstPosition = voltageBegins->position;
|
||||
|
||||
auto motionBegins = std::find_if(
|
||||
@@ -134,7 +134,7 @@ sysid::TrimStepVoltageData(std::vector<PreparedData>* data,
|
||||
(settings->velocityThreshold * datum.dt.value());
|
||||
});
|
||||
|
||||
units::second_t positionDelay;
|
||||
wpi::units::second_t positionDelay;
|
||||
if (motionBegins != data->end()) {
|
||||
positionDelay = motionBegins->timestamp - firstTimestamp;
|
||||
} else {
|
||||
@@ -146,8 +146,8 @@ sysid::TrimStepVoltageData(std::vector<PreparedData>* data,
|
||||
// Since we don't know if its a forward or backwards test here, we use
|
||||
// the sign of each point's velocity to determine how to compare their
|
||||
// accelerations.
|
||||
return wpi::sgn(a.velocity) * a.acceleration <
|
||||
wpi::sgn(b.velocity) * b.acceleration;
|
||||
return wpi::util::sgn(a.velocity) * a.acceleration <
|
||||
wpi::util::sgn(b.velocity) * b.acceleration;
|
||||
});
|
||||
|
||||
// Current limiting can delay onset of the peak acceleration, so we need to
|
||||
@@ -155,11 +155,11 @@ sysid::TrimStepVoltageData(std::vector<PreparedData>* data,
|
||||
// because this whole file is tech debt already
|
||||
auto accelBegins = std::find_if(
|
||||
data->begin(), data->end(), [&maxAccel](const auto& measurement) {
|
||||
return wpi::sgn(measurement.velocity) * measurement.acceleration >
|
||||
0.8 * wpi::sgn(maxAccel->velocity) * maxAccel->acceleration;
|
||||
return wpi::util::sgn(measurement.velocity) * measurement.acceleration >
|
||||
0.8 * wpi::util::sgn(maxAccel->velocity) * maxAccel->acceleration;
|
||||
});
|
||||
|
||||
units::second_t velocityDelay;
|
||||
wpi::units::second_t velocityDelay;
|
||||
if (accelBegins != data->end()) {
|
||||
velocityDelay = accelBegins->timestamp - firstTimestamp;
|
||||
|
||||
@@ -209,7 +209,7 @@ double sysid::GetNoiseFloor(
|
||||
std::function<double(const PreparedData&)> accessorFunction) {
|
||||
double sum = 0.0;
|
||||
size_t step = window / 2;
|
||||
auto averageFilter = frc::LinearFilter<double>::MovingAverage(window);
|
||||
auto averageFilter = wpi::math::LinearFilter<double>::MovingAverage(window);
|
||||
for (size_t i = 0; i < data.size(); i++) {
|
||||
double mean = averageFilter.Calculate(accessorFunction(data[i]));
|
||||
if (i >= step) {
|
||||
@@ -229,8 +229,8 @@ double sysid::GetMaxSpeed(
|
||||
return max;
|
||||
}
|
||||
|
||||
units::second_t sysid::GetMeanTimeDelta(const std::vector<PreparedData>& data) {
|
||||
std::vector<units::second_t> dts;
|
||||
wpi::units::second_t sysid::GetMeanTimeDelta(const std::vector<PreparedData>& data) {
|
||||
std::vector<wpi::units::second_t> dts;
|
||||
|
||||
for (const auto& pt : data) {
|
||||
if (pt.dt > 0_s && pt.dt < 500_ms) {
|
||||
@@ -241,8 +241,8 @@ units::second_t sysid::GetMeanTimeDelta(const std::vector<PreparedData>& data) {
|
||||
return std::accumulate(dts.begin(), dts.end(), 0_s) / dts.size();
|
||||
}
|
||||
|
||||
units::second_t sysid::GetMeanTimeDelta(const Storage& data) {
|
||||
std::vector<units::second_t> dts;
|
||||
wpi::units::second_t sysid::GetMeanTimeDelta(const Storage& data) {
|
||||
std::vector<wpi::units::second_t> dts;
|
||||
|
||||
for (const auto& pt : data.slowForward) {
|
||||
if (pt.dt > 0_s && pt.dt < 500_ms) {
|
||||
@@ -274,7 +274,7 @@ units::second_t sysid::GetMeanTimeDelta(const Storage& data) {
|
||||
void sysid::ApplyMedianFilter(std::vector<PreparedData>* data, int window) {
|
||||
CheckSize(*data, window, "Median Filter");
|
||||
|
||||
frc::MedianFilter<double> medianFilter(window);
|
||||
wpi::math::MedianFilter<double> medianFilter(window);
|
||||
|
||||
// Load the median filter with the first value for accurate initial behavior
|
||||
for (int i = 0; i < window; i++) {
|
||||
@@ -319,14 +319,14 @@ static std::string RemoveStr(std::string_view str, std::string_view removeStr) {
|
||||
*
|
||||
* @return The maximum duration of the Dynamic Tests
|
||||
*/
|
||||
static units::second_t GetMaxStepTime(
|
||||
wpi::StringMap<std::vector<PreparedData>>& data) {
|
||||
static wpi::units::second_t GetMaxStepTime(
|
||||
wpi::util::StringMap<std::vector<PreparedData>>& data) {
|
||||
auto maxStepTime = 0_s;
|
||||
for (auto& it : data) {
|
||||
auto& key = it.first;
|
||||
auto& dataset = it.second;
|
||||
|
||||
if (IsRaw(key) && wpi::contains(key, "dynamic")) {
|
||||
if (IsRaw(key) && wpi::util::contains(key, "dynamic")) {
|
||||
if (!dataset.empty()) {
|
||||
auto duration = dataset.back().timestamp - dataset.front().timestamp;
|
||||
if (duration > maxStepTime) {
|
||||
@@ -339,11 +339,11 @@ static units::second_t GetMaxStepTime(
|
||||
}
|
||||
|
||||
void sysid::InitialTrimAndFilter(
|
||||
wpi::StringMap<std::vector<PreparedData>>* data,
|
||||
wpi::util::StringMap<std::vector<PreparedData>>* data,
|
||||
AnalysisManager::Settings* settings,
|
||||
std::vector<units::second_t>& positionDelays,
|
||||
std::vector<units::second_t>& velocityDelays, units::second_t& minStepTime,
|
||||
units::second_t& maxStepTime, std::string_view unit) {
|
||||
std::vector<wpi::units::second_t>& positionDelays,
|
||||
std::vector<wpi::units::second_t>& velocityDelays, wpi::units::second_t& minStepTime,
|
||||
wpi::units::second_t& maxStepTime, std::string_view unit) {
|
||||
auto& preparedData = *data;
|
||||
|
||||
// Find the maximum Step Test Duration of the dynamic tests
|
||||
@@ -354,7 +354,7 @@ void sysid::InitialTrimAndFilter(
|
||||
for (auto& it : preparedData) {
|
||||
auto& key = it.first;
|
||||
auto& dataset = it.second;
|
||||
if (wpi::contains(key, "quasistatic")) {
|
||||
if (wpi::util::contains(key, "quasistatic")) {
|
||||
settings->velocityThreshold =
|
||||
std::min(settings->velocityThreshold,
|
||||
GetNoiseFloor(dataset, kNoiseMeanWindow,
|
||||
@@ -369,7 +369,7 @@ void sysid::InitialTrimAndFilter(
|
||||
|
||||
// Trim quasistatic test data to remove all points where voltage is zero or
|
||||
// velocity < velocity threshold.
|
||||
if (wpi::contains(key, "quasistatic")) {
|
||||
if (wpi::util::contains(key, "quasistatic")) {
|
||||
dataset.erase(std::remove_if(dataset.begin(), dataset.end(),
|
||||
[&](const auto& pt) {
|
||||
return std::abs(pt.voltage) <= 0 ||
|
||||
@@ -393,7 +393,7 @@ void sysid::InitialTrimAndFilter(
|
||||
PrepareMechData(&dataset, unit);
|
||||
|
||||
// Trims filtered Dynamic Test Data
|
||||
if (IsFiltered(key) && wpi::contains(key, "dynamic")) {
|
||||
if (IsFiltered(key) && wpi::util::contains(key, "dynamic")) {
|
||||
// Get the filtered dataset name
|
||||
auto filteredKey = RemoveStr(key, "raw-");
|
||||
|
||||
@@ -420,7 +420,7 @@ void sysid::InitialTrimAndFilter(
|
||||
}
|
||||
}
|
||||
|
||||
void sysid::AccelFilter(wpi::StringMap<std::vector<PreparedData>>* data) {
|
||||
void sysid::AccelFilter(wpi::util::StringMap<std::vector<PreparedData>>* data) {
|
||||
auto& preparedData = *data;
|
||||
|
||||
// Remove points with acceleration = 0
|
||||
|
||||
@@ -17,16 +17,16 @@ SimpleMotorSim::SimpleMotorSim(double Ks, double Kv, double Ka,
|
||||
Reset(initialPosition, initialVelocity);
|
||||
}
|
||||
|
||||
void SimpleMotorSim::Update(units::volt_t voltage, units::second_t dt) {
|
||||
void SimpleMotorSim::Update(wpi::units::volt_t voltage, wpi::units::second_t dt) {
|
||||
Eigen::Vector<double, 1> u{voltage.value()};
|
||||
|
||||
// Given dx/dt = Ax + Bu + c sgn(x),
|
||||
// x_k+1 = e^(AT) x_k + A^-1 (e^(AT) - 1) (Bu + c sgn(x))
|
||||
Eigen::Matrix<double, 2, 2> Ad;
|
||||
Eigen::Matrix<double, 2, 1> Bd;
|
||||
frc::DiscretizeAB<2, 1>(m_A, m_B, dt, &Ad, &Bd);
|
||||
wpi::math::DiscretizeAB<2, 1>(m_A, m_B, dt, &Ad, &Bd);
|
||||
m_x = Ad * m_x + Bd * u +
|
||||
Bd * m_B.householderQr().solve(m_c * wpi::sgn(GetVelocity()));
|
||||
Bd * m_B.householderQr().solve(m_c * wpi::util::sgn(GetVelocity()));
|
||||
}
|
||||
|
||||
double SimpleMotorSim::GetPosition() const {
|
||||
@@ -37,9 +37,9 @@ double SimpleMotorSim::GetVelocity() const {
|
||||
return m_x(1);
|
||||
}
|
||||
|
||||
double SimpleMotorSim::GetAcceleration(units::volt_t voltage) const {
|
||||
double SimpleMotorSim::GetAcceleration(wpi::units::volt_t voltage) const {
|
||||
Eigen::Vector<double, 1> u{voltage.value()};
|
||||
return (m_A * m_x + m_B * u + m_c * wpi::sgn(GetVelocity()))(1);
|
||||
return (m_A * m_x + m_B * u + m_c * wpi::util::sgn(GetVelocity()))(1);
|
||||
}
|
||||
|
||||
void SimpleMotorSim::Reset(double position, double velocity) {
|
||||
|
||||
@@ -29,9 +29,9 @@
|
||||
|
||||
using namespace sysid;
|
||||
|
||||
Analyzer::Analyzer(glass::Storage& storage, wpi::Logger& logger)
|
||||
Analyzer::Analyzer(wpi::glass::Storage& storage, wpi::util::Logger& logger)
|
||||
: m_logger(logger) {
|
||||
// Fill the StringMap with preset values.
|
||||
// Fill the wpi::util::StringMap with preset values.
|
||||
m_presets["Default"] = presets::kDefault;
|
||||
m_presets["WPILib"] = presets::kWPILib;
|
||||
m_presets["CTRE Phoenix 5"] = presets::kCTREv5;
|
||||
@@ -55,8 +55,8 @@ void Analyzer::UpdateFeedforwardGains() {
|
||||
m_settings.preset.measurementDelay =
|
||||
m_settings.type == FeedbackControllerLoopType::kPosition
|
||||
// Clamp feedback measurement delay to ≥ 0
|
||||
? units::math::max(0_s, m_manager->GetPositionDelay())
|
||||
: units::math::max(0_s, m_manager->GetVelocityDelay());
|
||||
? wpi::units::math::max(0_s, m_manager->GetPositionDelay())
|
||||
: wpi::units::math::max(0_s, m_manager->GetVelocityDelay());
|
||||
PrepareGraphs();
|
||||
} catch (const sysid::InvalidDataError& e) {
|
||||
m_state = AnalyzerState::kGeneralDataError;
|
||||
@@ -70,7 +70,7 @@ void Analyzer::UpdateFeedforwardGains() {
|
||||
} catch (const AnalysisManager::FileReadingError& e) {
|
||||
m_state = AnalyzerState::kFileError;
|
||||
HandleError(e.what());
|
||||
} catch (const wpi::json::exception& e) {
|
||||
} catch (const wpi::util::json::exception& e) {
|
||||
m_state = AnalyzerState::kFileError;
|
||||
HandleError(e.what());
|
||||
} catch (const std::exception& e) {
|
||||
@@ -86,7 +86,7 @@ void Analyzer::UpdateFeedbackGains() {
|
||||
const auto& Ka = m_feedforwardGains.Ka;
|
||||
if (Kv.isValidGain && Ka.isValidGain) {
|
||||
const auto& fb = m_manager->CalculateFeedback(Kv, Ka);
|
||||
m_timescale = units::second_t{Ka.gain / Kv.gain};
|
||||
m_timescale = wpi::units::second_t{Ka.gain / Kv.gain};
|
||||
m_timescaleValid = true;
|
||||
m_Kp = fb.Kp;
|
||||
m_Kd = fb.Kd;
|
||||
@@ -298,7 +298,7 @@ void Analyzer::PrepareData() {
|
||||
} catch (const AnalysisManager::FileReadingError& e) {
|
||||
m_state = AnalyzerState::kFileError;
|
||||
HandleError(e.what());
|
||||
} catch (const wpi::json::exception& e) {
|
||||
} catch (const wpi::util::json::exception& e) {
|
||||
m_state = AnalyzerState::kFileError;
|
||||
HandleError(e.what());
|
||||
} catch (const std::exception& e) {
|
||||
@@ -475,7 +475,7 @@ void Analyzer::DisplayFeedforwardParameters(float beginX, float beginY) {
|
||||
if (ImGui::SliderFloat("Test Duration", &m_stepTestDuration,
|
||||
m_manager->GetMinStepTime().value(),
|
||||
m_manager->GetMaxStepTime().value(), "%.2f")) {
|
||||
m_settings.stepTestDuration = units::second_t{m_stepTestDuration};
|
||||
m_settings.stepTestDuration = wpi::units::second_t{m_stepTestDuration};
|
||||
PrepareData();
|
||||
}
|
||||
}
|
||||
@@ -612,9 +612,9 @@ void Analyzer::DisplayFeedbackGains() {
|
||||
sysid::CreateTooltip(
|
||||
"Gain presets represent how feedback gains are calculated for your "
|
||||
"specific feedback controller:\n\n"
|
||||
"Default, WPILib (2020-): For use with the new WPILib PIDController "
|
||||
"Default, WPILib (2020-): For use with the new WPILib wpi::math::PIDController "
|
||||
"class.\n"
|
||||
"WPILib (Pre-2020): For use with the old WPILib PIDController class.\n"
|
||||
"WPILib (Pre-2020): For use with the old WPILib wpi::math::PIDController class.\n"
|
||||
"CTRE: For use with CTRE units. These are the default units that ship "
|
||||
"with CTRE motor controllers.\n"
|
||||
"REV (Brushless): For use with NEO and NEO 550 motors on a SPARK MAX.\n"
|
||||
|
||||
@@ -30,7 +30,7 @@ static ImPlotPoint Getter(int idx, void* data) {
|
||||
template <typename Model>
|
||||
static std::vector<std::vector<ImPlotPoint>> PopulateTimeDomainSim(
|
||||
const std::vector<PreparedData>& data,
|
||||
const std::array<units::second_t, 4>& startTimes, size_t step, Model model,
|
||||
const std::array<wpi::units::second_t, 4>& startTimes, size_t step, Model model,
|
||||
double* simSquaredErrorSum, double* squaredVariationSum,
|
||||
int* timeSeriesPoints) {
|
||||
// Create the vector of ImPlotPoints that will contain our simulated data.
|
||||
@@ -42,7 +42,7 @@ static std::vector<std::vector<ImPlotPoint>> PopulateTimeDomainSim(
|
||||
tmp.emplace_back(startTime.value(), data[0].velocity);
|
||||
|
||||
model.Reset(data[0].position, data[0].velocity);
|
||||
units::second_t t = 0_s;
|
||||
wpi::units::second_t t = 0_s;
|
||||
|
||||
for (size_t i = 1; i < data.size(); ++i) {
|
||||
const auto& now = data[i];
|
||||
@@ -60,7 +60,7 @@ static std::vector<std::vector<ImPlotPoint>> PopulateTimeDomainSim(
|
||||
continue;
|
||||
}
|
||||
|
||||
model.Update(units::volt_t{pre.voltage}, now.timestamp - pre.timestamp);
|
||||
model.Update(wpi::units::volt_t{pre.voltage}, now.timestamp - pre.timestamp);
|
||||
tmp.emplace_back((startTime + t).value(), model.GetVelocity());
|
||||
*simSquaredErrorSum += std::pow(now.velocity - model.GetVelocity(), 2);
|
||||
*squaredVariationSum += std::pow(now.velocity, 2);
|
||||
@@ -71,7 +71,7 @@ static std::vector<std::vector<ImPlotPoint>> PopulateTimeDomainSim(
|
||||
return pts;
|
||||
}
|
||||
|
||||
AnalyzerPlot::AnalyzerPlot(wpi::Logger& logger) : m_logger(logger) {}
|
||||
AnalyzerPlot::AnalyzerPlot(wpi::util::Logger& logger) : m_logger(logger) {}
|
||||
|
||||
void AnalyzerPlot::SetRawTimeData(const std::vector<PreparedData>& rawSlow,
|
||||
const std::vector<PreparedData>& rawFast,
|
||||
@@ -131,7 +131,7 @@ void AnalyzerPlot::SetRawData(const Storage& data, std::string_view unit,
|
||||
void AnalyzerPlot::SetData(const Storage& rawData, const Storage& filteredData,
|
||||
std::string_view unit,
|
||||
const AnalysisManager::FeedforwardGains& ffGains,
|
||||
const std::array<units::second_t, 4>& startTimes,
|
||||
const std::array<wpi::units::second_t, 4>& startTimes,
|
||||
AnalysisType type, std::atomic<bool>& abort) {
|
||||
double simSquaredErrorSum = 0;
|
||||
double squaredVariationSum = 0;
|
||||
@@ -163,7 +163,7 @@ void AnalyzerPlot::SetData(const Storage& rawData, const Storage& filteredData,
|
||||
auto slowStep = std::ceil(slow.size() * 1.0 / kMaxSize * 4);
|
||||
auto fastStep = std::ceil(fast.size() * 1.0 / kMaxSize * 4);
|
||||
|
||||
units::second_t dtMean = GetMeanTimeDelta(filteredData);
|
||||
wpi::units::second_t dtMean = GetMeanTimeDelta(filteredData);
|
||||
|
||||
// Velocity-vs-time plots
|
||||
{
|
||||
@@ -192,7 +192,7 @@ void AnalyzerPlot::SetData(const Storage& rawData, const Storage& filteredData,
|
||||
slow[i].timestamp) == startTimes.end()) {
|
||||
m_timestepData.data.emplace_back(
|
||||
(slow[i].timestamp).value(),
|
||||
units::millisecond_t{slow[i].dt}.value());
|
||||
wpi::units::millisecond_t{slow[i].dt}.value());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -217,7 +217,7 @@ void AnalyzerPlot::SetData(const Storage& rawData, const Storage& filteredData,
|
||||
fast[i].timestamp) == startTimes.end()) {
|
||||
m_timestepData.data.emplace_back(
|
||||
(fast[i].timestamp).value(),
|
||||
units::millisecond_t{fast[i].dt}.value());
|
||||
wpi::units::millisecond_t{fast[i].dt}.value());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -334,7 +334,7 @@ void AnalyzerPlot::SetData(const Storage& rawData, const Storage& filteredData,
|
||||
startTimes.end()) {
|
||||
m_timestepData.data.emplace_back(
|
||||
(slow[i].timestamp).value(),
|
||||
units::millisecond_t{slow[i].dt}.value());
|
||||
wpi::units::millisecond_t{slow[i].dt}.value());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -351,19 +351,19 @@ void AnalyzerPlot::SetData(const Storage& rawData, const Storage& filteredData,
|
||||
startTimes.end()) {
|
||||
m_timestepData.data.emplace_back(
|
||||
(fast[i].timestamp).value(),
|
||||
units::millisecond_t{fast[i].dt}.value());
|
||||
wpi::units::millisecond_t{fast[i].dt}.value());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
auto minTime =
|
||||
units::math::min(slow.front().timestamp, fast.front().timestamp);
|
||||
wpi::units::math::min(slow.front().timestamp, fast.front().timestamp);
|
||||
m_timestepData.fitLine[0] =
|
||||
ImPlotPoint{minTime.value(), units::millisecond_t{dtMean}.value()};
|
||||
ImPlotPoint{minTime.value(), wpi::units::millisecond_t{dtMean}.value()};
|
||||
|
||||
auto maxTime = units::math::max(slow.back().timestamp, fast.back().timestamp);
|
||||
auto maxTime = wpi::units::math::max(slow.back().timestamp, fast.back().timestamp);
|
||||
m_timestepData.fitLine[1] =
|
||||
ImPlotPoint{maxTime.value(), units::millisecond_t{dtMean}.value()};
|
||||
ImPlotPoint{maxTime.value(), wpi::units::millisecond_t{dtMean}.value()};
|
||||
|
||||
// RMSE = std::sqrt(sum((x_i - x^_i)^2) / N) where sum represents the sum of
|
||||
// all time series points, x_i represents the velocity at a timestep, x^_i
|
||||
|
||||
@@ -105,7 +105,7 @@ void DataSelector::Display() {
|
||||
continue;
|
||||
}
|
||||
for (auto it2 = it->second.begin(); it2 != it->second.end();) {
|
||||
auto direction = wpi::rsplit(it2->first, '-').second;
|
||||
auto direction = wpi::util::rsplit(it2->first, '-').second;
|
||||
if (direction != "forward" && direction != "reverse") {
|
||||
WPI_WARNING(m_logger, "Unrecognized direction {}, removing",
|
||||
direction);
|
||||
@@ -220,7 +220,7 @@ DataSelector::Tests DataSelector::LoadTests(
|
||||
continue;
|
||||
}
|
||||
|
||||
auto [testName, direction] = wpi::rsplit(testState, '-');
|
||||
auto [testName, direction] = wpi::util::rsplit(testState, '-');
|
||||
auto testIt = tests.find(testName);
|
||||
if (testIt == tests.end()) {
|
||||
testIt = tests.emplace(std::string{testName}, State{}).first;
|
||||
@@ -252,7 +252,7 @@ static void AddSamples(std::vector<MotorData::Run::Sample<T>>& samples,
|
||||
[](const auto& datapoint, double val) { return datapoint.first < val; });
|
||||
|
||||
for (auto it = begin; it != end; ++it) {
|
||||
samples.emplace_back(units::second_t{it->first * 1.0e-6}, T{it->second});
|
||||
samples.emplace_back(wpi::units::second_t{it->first * 1.0e-6}, T{it->second});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
|
||||
using namespace sysid;
|
||||
|
||||
LogLoader::LogLoader(glass::Storage& storage, wpi::Logger& logger) {}
|
||||
LogLoader::LogLoader(wpi::glass::Storage& storage, wpi::util::Logger& logger) {}
|
||||
|
||||
LogLoader::~LogLoader() = default;
|
||||
|
||||
@@ -40,7 +40,7 @@ void LogLoader::Display() {
|
||||
if (!m_opener->result().empty()) {
|
||||
m_filename = m_opener->result()[0];
|
||||
|
||||
auto fileBuffer = wpi::MemoryBuffer::GetFile(m_filename);
|
||||
auto fileBuffer = wpi::util::MemoryBuffer::GetFile(m_filename);
|
||||
if (!fileBuffer) {
|
||||
ImGui::OpenPopup("Error");
|
||||
m_error = fmt::format("Could not open file: {}",
|
||||
@@ -108,7 +108,7 @@ void LogLoader::Display() {
|
||||
|
||||
void LogLoader::RebuildEntryTree() {
|
||||
m_entryTree.clear();
|
||||
wpi::SmallVector<std::string_view, 16> parts;
|
||||
wpi::util::SmallVector<std::string_view, 16> parts;
|
||||
m_reader->ForEachEntryName([&](const wpi::log::DataLogReaderEntry& entry) {
|
||||
// only show double/float/string entries (TODO: support struct/protobuf)
|
||||
if (entry.type != "double" && entry.type != "float" &&
|
||||
@@ -117,19 +117,19 @@ void LogLoader::RebuildEntryTree() {
|
||||
}
|
||||
|
||||
// filter on name
|
||||
if (!m_filter.empty() && !wpi::contains_lower(entry.name, m_filter)) {
|
||||
if (!m_filter.empty() && !wpi::util::contains_lower(entry.name, m_filter)) {
|
||||
return;
|
||||
}
|
||||
|
||||
parts.clear();
|
||||
// split on first : if one is present
|
||||
auto [prefix, mainpart] = wpi::split(entry.name, ':');
|
||||
if (mainpart.empty() || wpi::contains(prefix, '/')) {
|
||||
auto [prefix, mainpart] = wpi::util::split(entry.name, ':');
|
||||
if (mainpart.empty() || wpi::util::contains(prefix, '/')) {
|
||||
mainpart = entry.name;
|
||||
} else {
|
||||
parts.emplace_back(prefix);
|
||||
}
|
||||
wpi::split(mainpart, '/', -1, false,
|
||||
wpi::util::split(mainpart, '/', -1, false,
|
||||
[&](auto part) { parts.emplace_back(part); });
|
||||
|
||||
// ignore a raw "/" key
|
||||
@@ -139,7 +139,7 @@ void LogLoader::RebuildEntryTree() {
|
||||
|
||||
// get to leaf
|
||||
auto nodes = &m_entryTree;
|
||||
for (auto part : wpi::drop_back(std::span{parts.begin(), parts.end()})) {
|
||||
for (auto part : wpi::util::drop_back(std::span{parts.begin(), parts.end()})) {
|
||||
auto it =
|
||||
std::find_if(nodes->begin(), nodes->end(),
|
||||
[&](const auto& node) { return node.name == part; });
|
||||
|
||||
@@ -70,7 +70,7 @@ class AnalysisManager {
|
||||
* The duration of the dynamic test that should be considered. A value of
|
||||
* zero indicates it needs to be set to the default.
|
||||
*/
|
||||
units::second_t stepTestDuration = 0_s;
|
||||
wpi::units::second_t stepTestDuration = 0_s;
|
||||
};
|
||||
|
||||
struct FeedforwardGain {
|
||||
@@ -189,7 +189,7 @@ class AnalysisManager {
|
||||
* @param settings The settings for this instance of the analysis manager.
|
||||
* @param logger The logger instance to use for log data.
|
||||
*/
|
||||
AnalysisManager(Settings& settings, wpi::Logger& logger);
|
||||
AnalysisManager(Settings& settings, wpi::util::Logger& logger);
|
||||
|
||||
/**
|
||||
* Constructs an instance of the analysis manager with the given path (to the
|
||||
@@ -199,7 +199,7 @@ class AnalysisManager {
|
||||
* @param settings The settings for this instance of the analysis manager.
|
||||
* @param logger The logger instance to use for log data.
|
||||
*/
|
||||
AnalysisManager(TestData data, Settings& settings, wpi::Logger& logger);
|
||||
AnalysisManager(TestData data, Settings& settings, wpi::util::Logger& logger);
|
||||
|
||||
/**
|
||||
* Prepares data from the JSON and stores the output in Storage member
|
||||
@@ -281,7 +281,7 @@ class AnalysisManager {
|
||||
*
|
||||
* @return The minimum step test duration.
|
||||
*/
|
||||
units::second_t GetMinStepTime() const { return m_minStepTime; }
|
||||
wpi::units::second_t GetMinStepTime() const { return m_minStepTime; }
|
||||
|
||||
/**
|
||||
* Returns the maximum duration of the Step Voltage Test of the currently
|
||||
@@ -289,7 +289,7 @@ class AnalysisManager {
|
||||
*
|
||||
* @return Maximum step test duration
|
||||
*/
|
||||
units::second_t GetMaxStepTime() const { return m_maxStepTime; }
|
||||
wpi::units::second_t GetMaxStepTime() const { return m_maxStepTime; }
|
||||
|
||||
/**
|
||||
* Returns the estimated time delay of the measured position, including
|
||||
@@ -297,7 +297,7 @@ class AnalysisManager {
|
||||
*
|
||||
* @return Position delay in milliseconds
|
||||
*/
|
||||
units::millisecond_t GetPositionDelay() const {
|
||||
wpi::units::millisecond_t GetPositionDelay() const {
|
||||
return std::accumulate(m_positionDelays.begin(), m_positionDelays.end(),
|
||||
0_s) /
|
||||
m_positionDelays.size();
|
||||
@@ -309,7 +309,7 @@ class AnalysisManager {
|
||||
*
|
||||
* @return Velocity delay in milliseconds
|
||||
*/
|
||||
units::millisecond_t GetVelocityDelay() const {
|
||||
wpi::units::millisecond_t GetVelocityDelay() const {
|
||||
return std::accumulate(m_velocityDelays.begin(), m_velocityDelays.end(),
|
||||
0_s) /
|
||||
m_positionDelays.size();
|
||||
@@ -320,30 +320,30 @@ class AnalysisManager {
|
||||
*
|
||||
* @return The start times for each test
|
||||
*/
|
||||
const std::array<units::second_t, 4>& GetStartTimes() const {
|
||||
const std::array<wpi::units::second_t, 4>& GetStartTimes() const {
|
||||
return m_startTimes;
|
||||
}
|
||||
|
||||
bool HasData() const { return !m_originalDataset.empty(); }
|
||||
|
||||
private:
|
||||
wpi::Logger& m_logger;
|
||||
wpi::util::Logger& m_logger;
|
||||
|
||||
Storage m_originalDataset;
|
||||
Storage m_rawDataset;
|
||||
Storage m_filteredDataset;
|
||||
|
||||
// Stores the various start times of the different tests.
|
||||
std::array<units::second_t, 4> m_startTimes;
|
||||
std::array<wpi::units::second_t, 4> m_startTimes;
|
||||
|
||||
// The settings for this instance. This contains pointers to the feedback
|
||||
// controller preset, LQR parameters, acceleration window size, etc.
|
||||
Settings& m_settings;
|
||||
|
||||
units::second_t m_minStepTime{0};
|
||||
units::second_t m_maxStepTime{std::numeric_limits<double>::infinity()};
|
||||
std::vector<units::second_t> m_positionDelays;
|
||||
std::vector<units::second_t> m_velocityDelays;
|
||||
wpi::units::second_t m_minStepTime{0};
|
||||
wpi::units::second_t m_maxStepTime{std::numeric_limits<double>::infinity()};
|
||||
std::vector<wpi::units::second_t> m_positionDelays;
|
||||
std::vector<wpi::units::second_t> m_velocityDelays;
|
||||
|
||||
void PrepareGeneralData();
|
||||
};
|
||||
|
||||
@@ -36,7 +36,7 @@ class ArmSim {
|
||||
* @param voltage Voltage to apply over the timestep.
|
||||
* @param dt Sample period.
|
||||
*/
|
||||
void Update(units::volt_t voltage, units::second_t dt);
|
||||
void Update(wpi::units::volt_t voltage, wpi::units::second_t dt);
|
||||
|
||||
/**
|
||||
* Returns the position.
|
||||
@@ -58,7 +58,7 @@ class ArmSim {
|
||||
* @param voltage The voltage that is being applied to the mechanism / input
|
||||
* @return The acceleration given the state and input
|
||||
*/
|
||||
double GetAcceleration(units::volt_t voltage) const;
|
||||
double GetAcceleration(wpi::units::volt_t voltage) const;
|
||||
|
||||
/**
|
||||
* Resets model position and velocity.
|
||||
|
||||
@@ -34,7 +34,7 @@ class ElevatorSim {
|
||||
* @param voltage Voltage to apply over the timestep.
|
||||
* @param dt Sample period.
|
||||
*/
|
||||
void Update(units::volt_t voltage, units::second_t dt);
|
||||
void Update(wpi::units::volt_t voltage, wpi::units::second_t dt);
|
||||
|
||||
/**
|
||||
* Returns the position.
|
||||
@@ -56,7 +56,7 @@ class ElevatorSim {
|
||||
* @param voltage The voltage that is being applied to the mechanism / input
|
||||
* @return The acceleration given the state and input
|
||||
*/
|
||||
double GetAcceleration(units::volt_t voltage) const;
|
||||
double GetAcceleration(wpi::units::volt_t voltage) const;
|
||||
|
||||
/**
|
||||
* Resets model position and velocity.
|
||||
|
||||
@@ -29,7 +29,7 @@ struct FeedbackControllerPreset {
|
||||
/**
|
||||
* The period at which the controller runs.
|
||||
*/
|
||||
units::millisecond_t period;
|
||||
wpi::units::millisecond_t period;
|
||||
|
||||
/**
|
||||
* Whether the controller gains are time-normalized.
|
||||
@@ -39,7 +39,7 @@ struct FeedbackControllerPreset {
|
||||
/**
|
||||
* The measurement delay in the encoder measurements.
|
||||
*/
|
||||
units::millisecond_t measurementDelay;
|
||||
wpi::units::millisecond_t measurementDelay;
|
||||
|
||||
/**
|
||||
* Checks equality between two feedback controller presets.
|
||||
|
||||
@@ -145,10 +145,10 @@ void ApplyMedianFilter(std::vector<PreparedData>* data, int window);
|
||||
* @param maxStepTime The maximum step test duration.
|
||||
* @return The updated minimum step test duration.
|
||||
*/
|
||||
std::tuple<units::second_t, units::second_t, units::second_t>
|
||||
std::tuple<wpi::units::second_t, wpi::units::second_t, wpi::units::second_t>
|
||||
TrimStepVoltageData(std::vector<PreparedData>* data,
|
||||
AnalysisManager::Settings* settings,
|
||||
units::second_t minStepTime, units::second_t maxStepTime);
|
||||
wpi::units::second_t minStepTime, wpi::units::second_t maxStepTime);
|
||||
|
||||
/**
|
||||
* Compute the mean time delta of the given data.
|
||||
@@ -156,7 +156,7 @@ TrimStepVoltageData(std::vector<PreparedData>* data,
|
||||
* @param data A reference to all of the collected PreparedData
|
||||
* @return The mean time delta for all the data points
|
||||
*/
|
||||
units::second_t GetMeanTimeDelta(const std::vector<PreparedData>& data);
|
||||
wpi::units::second_t GetMeanTimeDelta(const std::vector<PreparedData>& data);
|
||||
|
||||
/**
|
||||
* Compute the mean time delta of the given data.
|
||||
@@ -164,7 +164,7 @@ units::second_t GetMeanTimeDelta(const std::vector<PreparedData>& data);
|
||||
* @param data A reference to all of the collected PreparedData
|
||||
* @return The mean time delta for all the data points
|
||||
*/
|
||||
units::second_t GetMeanTimeDelta(const Storage& data);
|
||||
wpi::units::second_t GetMeanTimeDelta(const Storage& data);
|
||||
|
||||
/**
|
||||
* Creates a central finite difference filter that computes the nth
|
||||
@@ -187,16 +187,16 @@ units::second_t GetMeanTimeDelta(const Storage& data);
|
||||
* @param period The period in seconds between samples taken by the user.
|
||||
*/
|
||||
template <int Derivative, int Samples>
|
||||
frc::LinearFilter<double> CentralFiniteDifference(units::second_t period) {
|
||||
wpi::math::LinearFilter<double> CentralFiniteDifference(wpi::units::second_t period) {
|
||||
static_assert(Samples % 2 != 0, "Number of samples must be odd.");
|
||||
|
||||
// Generate stencil points from -(samples - 1)/2 to (samples - 1)/2
|
||||
wpi::array<int, Samples> stencil{wpi::empty_array};
|
||||
wpi::util::array<int, Samples> stencil{wpi::util::empty_array};
|
||||
for (int i = 0; i < Samples; ++i) {
|
||||
stencil[i] = -(Samples - 1) / 2 + i;
|
||||
}
|
||||
|
||||
return frc::LinearFilter<double>::FiniteDifference<Derivative, Samples>(
|
||||
return wpi::math::LinearFilter<double>::FiniteDifference<Derivative, Samples>(
|
||||
stencil, period);
|
||||
}
|
||||
|
||||
@@ -219,12 +219,12 @@ frc::LinearFilter<double> CentralFiniteDifference(units::second_t period) {
|
||||
* @param unit The angular unit that the arm test is in (only for calculating
|
||||
* cosine data)
|
||||
*/
|
||||
void InitialTrimAndFilter(wpi::StringMap<std::vector<PreparedData>>* data,
|
||||
void InitialTrimAndFilter(wpi::util::StringMap<std::vector<PreparedData>>* data,
|
||||
AnalysisManager::Settings* settings,
|
||||
std::vector<units::second_t>& positionDelays,
|
||||
std::vector<units::second_t>& velocityDelays,
|
||||
units::second_t& minStepTime,
|
||||
units::second_t& maxStepTime,
|
||||
std::vector<wpi::units::second_t>& positionDelays,
|
||||
std::vector<wpi::units::second_t>& velocityDelays,
|
||||
wpi::units::second_t& minStepTime,
|
||||
wpi::units::second_t& maxStepTime,
|
||||
std::string_view unit = "");
|
||||
|
||||
/**
|
||||
@@ -232,6 +232,6 @@ void InitialTrimAndFilter(wpi::StringMap<std::vector<PreparedData>>* data,
|
||||
*
|
||||
* @param data A pointer to a PreparedData vector
|
||||
*/
|
||||
void AccelFilter(wpi::StringMap<std::vector<PreparedData>>* data);
|
||||
void AccelFilter(wpi::util::StringMap<std::vector<PreparedData>>* data);
|
||||
|
||||
} // namespace sysid
|
||||
|
||||
@@ -34,7 +34,7 @@ class SimpleMotorSim {
|
||||
* @param voltage Voltage to apply over the timestep.
|
||||
* @param dt Sample period.
|
||||
*/
|
||||
void Update(units::volt_t voltage, units::second_t dt);
|
||||
void Update(wpi::units::volt_t voltage, wpi::units::second_t dt);
|
||||
|
||||
/**
|
||||
* Returns the position.
|
||||
@@ -56,7 +56,7 @@ class SimpleMotorSim {
|
||||
* @param voltage The voltage that is being applied to the mechanism / input
|
||||
* @return The acceleration given the state and input
|
||||
*/
|
||||
double GetAcceleration(units::volt_t voltage) const;
|
||||
double GetAcceleration(wpi::units::volt_t voltage) const;
|
||||
|
||||
/**
|
||||
* Resets model position and velocity.
|
||||
|
||||
@@ -22,14 +22,14 @@ struct MotorData {
|
||||
// Timestamps are not necessarily aligned!
|
||||
struct Run {
|
||||
template <typename T>
|
||||
requires std::is_arithmetic_v<T> || units::traits::is_unit_t_v<T>
|
||||
requires std::is_arithmetic_v<T> || wpi::units::traits::is_unit_t_v<T>
|
||||
struct Sample {
|
||||
Sample(units::second_t time, T measurement)
|
||||
Sample(wpi::units::second_t time, T measurement)
|
||||
: time{time}, measurement{measurement} {}
|
||||
units::second_t time;
|
||||
wpi::units::second_t time;
|
||||
T measurement;
|
||||
};
|
||||
std::vector<Sample<units::volt_t>> voltage;
|
||||
std::vector<Sample<wpi::units::volt_t>> voltage;
|
||||
std::vector<Sample<double>> position;
|
||||
std::vector<Sample<double>> velocity;
|
||||
};
|
||||
@@ -40,7 +40,7 @@ struct MotorData {
|
||||
struct TestData {
|
||||
std::string distanceUnit;
|
||||
AnalysisType mechanismType;
|
||||
wpi::StringMap<MotorData> motorData;
|
||||
wpi::util::StringMap<MotorData> motorData;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -51,7 +51,7 @@ struct PreparedData {
|
||||
/**
|
||||
* The timestamp of the data point.
|
||||
*/
|
||||
units::second_t timestamp;
|
||||
wpi::units::second_t timestamp;
|
||||
|
||||
/**
|
||||
* The voltage of the data point.
|
||||
@@ -71,7 +71,7 @@ struct PreparedData {
|
||||
/**
|
||||
* The difference in timestamps between this point and the next point.
|
||||
*/
|
||||
units::second_t dt = 0_s;
|
||||
wpi::units::second_t dt = 0_s;
|
||||
|
||||
/**
|
||||
* The acceleration of the data point
|
||||
|
||||
@@ -19,7 +19,7 @@ namespace sysid {
|
||||
* @param accum The accumulated gyro angle.
|
||||
*/
|
||||
constexpr double CalculateTrackwidth(double l, double r,
|
||||
units::radian_t accum) {
|
||||
wpi::units::radian_t accum) {
|
||||
// The below comes from solving ω = (vr − vl) / 2r for 2r.
|
||||
return (gcem::abs(r) + gcem::abs(l)) / gcem::abs(accum.value());
|
||||
}
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
|
||||
struct ImPlotPoint;
|
||||
|
||||
namespace glass {
|
||||
namespace wpi::glass {
|
||||
class Storage;
|
||||
} // namespace glass
|
||||
|
||||
@@ -35,7 +35,7 @@ namespace sysid {
|
||||
* load their data, visualize the data, adjust certain variables, and then view
|
||||
* the calculated gains.
|
||||
*/
|
||||
class Analyzer : public glass::View {
|
||||
class Analyzer : public wpi::glass::View {
|
||||
public:
|
||||
TestData m_data;
|
||||
/**
|
||||
@@ -78,7 +78,7 @@ class Analyzer : public glass::View {
|
||||
* @param storage Glass Storage
|
||||
* @param logger The program logger
|
||||
*/
|
||||
Analyzer(glass::Storage& storage, wpi::Logger& logger);
|
||||
Analyzer(wpi::glass::Storage& storage, wpi::util::Logger& logger);
|
||||
|
||||
/**
|
||||
* Displays the analyzer widget
|
||||
@@ -212,7 +212,7 @@ class Analyzer : public glass::View {
|
||||
|
||||
// Everything related to feedback controller calculations.
|
||||
AnalysisManager::Settings m_settings;
|
||||
wpi::StringMap<FeedbackControllerPreset> m_presets;
|
||||
wpi::util::StringMap<FeedbackControllerPreset> m_presets;
|
||||
|
||||
int m_selectedLoopType = 1;
|
||||
int m_selectedPreset = 0;
|
||||
@@ -223,7 +223,7 @@ class Analyzer : public glass::View {
|
||||
double m_accelRMSE;
|
||||
double m_Kp;
|
||||
double m_Kd;
|
||||
units::millisecond_t m_timescale;
|
||||
wpi::units::millisecond_t m_timescale;
|
||||
bool m_timescaleValid = false;
|
||||
|
||||
// Units
|
||||
@@ -235,7 +235,7 @@ class Analyzer : public glass::View {
|
||||
float m_stepTestDuration = 0;
|
||||
|
||||
// Logger
|
||||
wpi::Logger& m_logger;
|
||||
wpi::util::Logger& m_logger;
|
||||
|
||||
// Plot
|
||||
AnalyzerPlot m_plot{m_logger};
|
||||
|
||||
@@ -37,7 +37,7 @@ class AnalyzerPlot {
|
||||
*
|
||||
* @param logger The program logger
|
||||
*/
|
||||
explicit AnalyzerPlot(wpi::Logger& logger);
|
||||
explicit AnalyzerPlot(wpi::util::Logger& logger);
|
||||
|
||||
/**
|
||||
* Sets the data to be displayed on the plots.
|
||||
@@ -55,7 +55,7 @@ class AnalyzerPlot {
|
||||
void SetData(const Storage& rawData, const Storage& filteredData,
|
||||
std::string_view unit,
|
||||
const AnalysisManager::FeedforwardGains& ff,
|
||||
const std::array<units::second_t, 4>& startTimes,
|
||||
const std::array<wpi::units::second_t, 4>& startTimes,
|
||||
AnalysisType type, std::atomic<bool>& abort);
|
||||
|
||||
/**
|
||||
@@ -189,10 +189,10 @@ class AnalyzerPlot {
|
||||
std::string m_velPortionAccelLabel;
|
||||
|
||||
// Thread safety
|
||||
wpi::spinlock m_mutex;
|
||||
wpi::util::spinlock m_mutex;
|
||||
|
||||
// Logger
|
||||
wpi::Logger& m_logger;
|
||||
wpi::util::Logger& m_logger;
|
||||
|
||||
FilteredDataVsTimePlot m_quasistaticData;
|
||||
FilteredDataVsTimePlot m_dynamicData;
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
#include "wpi/sysid/analysis/Storage.hpp"
|
||||
#include "wpi/util/StringMap.hpp"
|
||||
|
||||
namespace glass {
|
||||
namespace wpi::glass {
|
||||
class Storage;
|
||||
} // namespace glass
|
||||
|
||||
@@ -25,21 +25,21 @@ namespace wpi {
|
||||
namespace log {
|
||||
class DataLogReaderEntry;
|
||||
} // namespace log
|
||||
class Logger;
|
||||
class wpi::util::Logger;
|
||||
} // namespace wpi
|
||||
|
||||
namespace sysid {
|
||||
/**
|
||||
* Helps with loading datalog files.
|
||||
*/
|
||||
class DataSelector : public glass::View {
|
||||
class DataSelector : public wpi::glass::View {
|
||||
public:
|
||||
/**
|
||||
* Creates a data selector widget
|
||||
*
|
||||
* @param logger The program logger
|
||||
*/
|
||||
explicit DataSelector(glass::Storage& storage, wpi::Logger& logger)
|
||||
explicit DataSelector(wpi::glass::Storage& storage, wpi::util::Logger& logger)
|
||||
: m_logger{logger} {}
|
||||
|
||||
/**
|
||||
@@ -60,7 +60,7 @@ class DataSelector : public glass::View {
|
||||
std::vector<std::string> m_missingTests;
|
||||
|
||||
private:
|
||||
wpi::Logger& m_logger;
|
||||
wpi::util::Logger& m_logger;
|
||||
using Runs = std::vector<std::pair<int64_t, int64_t>>;
|
||||
using State = std::map<std::string, Runs, std::less<>>; // full name
|
||||
using Tests = std::map<std::string, State, std::less<>>; // e.g. "dynamic"
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
#include "wpi/glass/View.hpp"
|
||||
#include "wpi/util/Signal.h"
|
||||
|
||||
namespace glass {
|
||||
namespace wpi::glass {
|
||||
class Storage;
|
||||
} // namespace glass
|
||||
|
||||
@@ -25,21 +25,21 @@ namespace log {
|
||||
class DataLogReaderEntry;
|
||||
class DataLogReaderThread;
|
||||
} // namespace log
|
||||
class Logger;
|
||||
class wpi::util::Logger;
|
||||
} // namespace wpi
|
||||
|
||||
namespace sysid {
|
||||
/**
|
||||
* Helps with loading datalog files.
|
||||
*/
|
||||
class LogLoader : public glass::View {
|
||||
class LogLoader : public wpi::glass::View {
|
||||
public:
|
||||
/**
|
||||
* Creates a log loader widget
|
||||
*
|
||||
* @param logger The program logger
|
||||
*/
|
||||
explicit LogLoader(glass::Storage& storage, wpi::Logger& logger);
|
||||
explicit LogLoader(wpi::glass::Storage& storage, wpi::util::Logger& logger);
|
||||
|
||||
~LogLoader() override;
|
||||
|
||||
@@ -52,10 +52,10 @@ class LogLoader : public glass::View {
|
||||
* Signal called when the current file is unloaded (invalidates any
|
||||
* LogEntry*).
|
||||
*/
|
||||
wpi::sig::Signal<> unload;
|
||||
wpi::util::sig::Signal<> unload;
|
||||
|
||||
private:
|
||||
// wpi::Logger& m_logger;
|
||||
// Logger& m_logger;
|
||||
|
||||
std::string m_filename;
|
||||
std::unique_ptr<pfd::open_file> m_opener;
|
||||
|
||||
@@ -40,9 +40,9 @@ inline constexpr int kMovementCombinations = 16;
|
||||
template <typename Model>
|
||||
sysid::Storage CollectData(Model& model, std::bitset<4> movements) {
|
||||
constexpr auto kUstep = 0.25_V / 1_s;
|
||||
constexpr units::volt_t kUmax = 7_V;
|
||||
constexpr units::second_t T = 5_ms;
|
||||
constexpr units::second_t kTestDuration = 5_s;
|
||||
constexpr wpi::units::volt_t kUmax = 7_V;
|
||||
constexpr wpi::units::second_t T = 5_ms;
|
||||
constexpr wpi::units::second_t kTestDuration = 5_s;
|
||||
|
||||
sysid::Storage storage;
|
||||
auto& [slowForward, slowBackward, fastForward, fastBackward] = storage;
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
#include "wpi/sysid/analysis/FilteringUtils.hpp"
|
||||
#include "wpi/sysid/analysis/Storage.hpp"
|
||||
|
||||
TEST(FilterTest, MedianFilter) {
|
||||
TEST(FilterTest, wpi::math::MedianFilter) {
|
||||
std::vector<sysid::PreparedData> testData{
|
||||
sysid::PreparedData{0_s, 0, 0, 0}, sysid::PreparedData{0_s, 0, 0, 1},
|
||||
sysid::PreparedData{0_s, 0, 0, 10}, sysid::PreparedData{0_s, 0, 0, 5},
|
||||
@@ -49,7 +49,7 @@ void FillStepVoltageData(std::vector<sysid::PreparedData>& data) {
|
||||
auto& datum = data.at(i);
|
||||
datum.timestamp = previousDatum.timestamp + previousDatum.dt;
|
||||
datum.position = 0.5 * previousDatum.acceleration *
|
||||
units::math::pow<2>(previousDatum.dt).value() +
|
||||
wpi::units::math::pow<2>(previousDatum.dt).value() +
|
||||
previousDatum.velocity * previousDatum.dt.value() +
|
||||
previousDatum.position;
|
||||
datum.velocity = previousDatum.velocity +
|
||||
@@ -136,7 +136,7 @@ TEST(FilterTest, StepTrim) {
|
||||
}
|
||||
|
||||
template <int Derivative, int Samples, typename F, typename DfDx>
|
||||
void AssertCentralResults(F&& f, DfDx&& dfdx, units::second_t h, double min,
|
||||
void AssertCentralResults(F&& f, DfDx&& dfdx, wpi::units::second_t h, double min,
|
||||
double max) {
|
||||
static_assert(Samples % 2 != 0, "Number of samples must be odd.");
|
||||
|
||||
|
||||
@@ -148,7 +148,7 @@ static bool EmitEntryTarget(int tag_id, std::string& file) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
void saveCalibration(wpi::json& field, std::string& output_directory,
|
||||
void saveCalibration(wpi::util::json& field, std::string& output_directory,
|
||||
std::string output_name, bool& isCalibrating) {
|
||||
if (!field.empty() && !output_directory.empty()) {
|
||||
std::cout << "Saving calibration to " << output_directory << std::endl;
|
||||
@@ -198,8 +198,8 @@ static void DisplayGui() {
|
||||
field_calibration_directory_selector;
|
||||
static std::unique_ptr<pfd::select_folder> download_directory_selector;
|
||||
|
||||
static wpi::json field_calibration_json;
|
||||
static wpi::json field_combination_json;
|
||||
static wpi::util::json field_calibration_json;
|
||||
static wpi::util::json field_combination_json;
|
||||
|
||||
static std::string selected_camera_intrinsics;
|
||||
static std::string selected_field_map;
|
||||
@@ -534,8 +534,8 @@ static void DisplayGui() {
|
||||
std::ifstream calJson(output_calibration_json_path);
|
||||
std::ifstream refJson(selected_field_map);
|
||||
|
||||
currentCalibrationMap = Fieldmap(wpi::json::parse(calJson));
|
||||
currentReferenceMap = Fieldmap(wpi::json::parse(refJson));
|
||||
currentCalibrationMap = Fieldmap(wpi::util::json::parse(calJson));
|
||||
currentReferenceMap = Fieldmap(wpi::util::json::parse(refJson));
|
||||
|
||||
if (currentCalibrationMap.getNumTags() !=
|
||||
currentReferenceMap.getNumTags()) {
|
||||
@@ -616,7 +616,7 @@ static void DisplayGui() {
|
||||
if (!selected_field_map.empty()) {
|
||||
drawCheck();
|
||||
std::ifstream json(selected_field_map);
|
||||
currentReferenceMap = Fieldmap(wpi::json::parse(json));
|
||||
currentReferenceMap = Fieldmap(wpi::util::json::parse(json));
|
||||
currentCombinerMap = currentReferenceMap;
|
||||
}
|
||||
openFilesButton("Select Field Calibrations",
|
||||
@@ -660,7 +660,7 @@ static void DisplayGui() {
|
||||
if (ImGui::Button("Download", ImVec2(0, 0))) {
|
||||
for (auto& [key, val] : combiner_map) {
|
||||
std::ifstream json(val);
|
||||
Fieldmap map(wpi::json::parse(json));
|
||||
Fieldmap map(wpi::util::json::parse(json));
|
||||
currentCombinerMap.replaceTag(key, map.getTag(key));
|
||||
}
|
||||
field_combination_json = currentCombinerMap.toJson();
|
||||
|
||||
@@ -96,11 +96,11 @@ inline cameracalibration::CameraModel load_camera_model(std::string path) {
|
||||
|
||||
std::ifstream file(path);
|
||||
|
||||
wpi::json json_data;
|
||||
wpi::util::json json_data;
|
||||
|
||||
try {
|
||||
json_data = wpi::json::parse(file);
|
||||
} catch (const wpi::json::parse_error& e) {
|
||||
json_data = wpi::util::json::parse(file);
|
||||
} catch (const wpi::util::json::parse_error& e) {
|
||||
std::cout << e.what() << std::endl;
|
||||
}
|
||||
|
||||
@@ -150,7 +150,7 @@ inline cameracalibration::CameraModel load_camera_model(std::string path) {
|
||||
return camera_model;
|
||||
}
|
||||
|
||||
inline cameracalibration::CameraModel load_camera_model(wpi::json json_data) {
|
||||
inline cameracalibration::CameraModel load_camera_model(wpi::util::json json_data) {
|
||||
// Camera matrix
|
||||
Eigen::Matrix<double, 3, 3> camera_matrix;
|
||||
|
||||
@@ -176,10 +176,10 @@ inline cameracalibration::CameraModel load_camera_model(wpi::json json_data) {
|
||||
return camera_model;
|
||||
}
|
||||
|
||||
inline std::map<int, wpi::json> load_ideal_map(std::string path) {
|
||||
inline std::map<int, wpi::util::json> load_ideal_map(std::string path) {
|
||||
std::ifstream file(path);
|
||||
wpi::json json_data = wpi::json::parse(file);
|
||||
std::map<int, wpi::json> ideal_map;
|
||||
wpi::util::json json_data = wpi::util::json::parse(file);
|
||||
std::map<int, wpi::util::json> ideal_map;
|
||||
|
||||
for (const auto& element : json_data["tags"]) {
|
||||
ideal_map[element["ID"]] = element;
|
||||
@@ -189,7 +189,7 @@ inline std::map<int, wpi::json> load_ideal_map(std::string path) {
|
||||
}
|
||||
|
||||
Eigen::Matrix<double, 4, 4> get_tag_transform(
|
||||
std::map<int, wpi::json>& ideal_map, int tag_id) {
|
||||
std::map<int, wpi::util::json>& ideal_map, int tag_id) {
|
||||
Eigen::Matrix<double, 4, 4> transform =
|
||||
Eigen::Matrix<double, 4, 4>::Identity();
|
||||
|
||||
@@ -432,7 +432,7 @@ inline bool process_video_file(
|
||||
}
|
||||
|
||||
int fieldcalibration::calibrate(std::string input_dir_path,
|
||||
wpi::json& output_json,
|
||||
wpi::util::json& output_json,
|
||||
std::string camera_model_path,
|
||||
std::string ideal_map_path, int pinned_tag_id,
|
||||
bool show_debug_window) {
|
||||
@@ -452,13 +452,13 @@ int fieldcalibration::calibrate(std::string input_dir_path,
|
||||
return 1;
|
||||
}
|
||||
|
||||
wpi::json json = wpi::json::parse(std::ifstream(ideal_map_path));
|
||||
wpi::util::json json = wpi::util::json::parse(std::ifstream(ideal_map_path));
|
||||
if (!json.contains("tags")) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Load ideal field map
|
||||
std::map<int, wpi::json> ideal_map;
|
||||
std::map<int, wpi::util::json> ideal_map;
|
||||
try {
|
||||
ideal_map = load_ideal_map(ideal_map_path);
|
||||
} catch (...) {
|
||||
@@ -552,7 +552,7 @@ int fieldcalibration::calibrate(std::string input_dir_path,
|
||||
std::cout << summary.BriefReport() << std::endl;
|
||||
|
||||
// Output
|
||||
std::map<int, wpi::json> observed_map = ideal_map;
|
||||
std::map<int, wpi::util::json> observed_map = ideal_map;
|
||||
|
||||
Eigen::Matrix<double, 4, 4> correction_a;
|
||||
correction_a << 0, 0, -1, 0, 1, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 1;
|
||||
@@ -594,7 +594,7 @@ int fieldcalibration::calibrate(std::string input_dir_path,
|
||||
corrected_transform_q.w();
|
||||
}
|
||||
|
||||
wpi::json observed_map_json;
|
||||
wpi::util::json observed_map_json;
|
||||
|
||||
for (const auto& [tag_id, tag_json] : observed_map) {
|
||||
observed_map_json["tags"].push_back(tag_json);
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
wpi::json fmap::singleTag(int tag, const tag::Pose& tagpose) {
|
||||
wpi::util::json fmap::singleTag(int tag, const tag::Pose& tagpose) {
|
||||
std::vector<double> transform = {};
|
||||
for (int i = 0; i < 4; i++) {
|
||||
for (int j = 0; j < 4; j++) {
|
||||
@@ -22,7 +22,7 @@ wpi::json fmap::singleTag(int tag, const tag::Pose& tagpose) {
|
||||
{"unique", true}};
|
||||
}
|
||||
|
||||
wpi::json fmap::convertfmap(const wpi::json& json) {
|
||||
wpi::util::json fmap::convertfmap(const wpi::util::json& json) {
|
||||
std::string fmapstart = "{\"fiducials\":[";
|
||||
|
||||
std::string fmapend = "],\"type\":\"frc\"}";
|
||||
@@ -36,5 +36,5 @@ wpi::json fmap::convertfmap(const wpi::json& json) {
|
||||
}
|
||||
}
|
||||
|
||||
return wpi::json::parse(fmapstart.append(fmapend));
|
||||
return wpi::util::json::parse(fmapstart.append(fmapend));
|
||||
}
|
||||
|
||||
@@ -32,7 +32,7 @@ Pose::Pose(int tag_id, double xpos, double ypos, double zpos, double w,
|
||||
yawRot = eulerAngles[2];
|
||||
}
|
||||
|
||||
wpi::json Pose::toJson() {
|
||||
wpi::util::json Pose::toJson() {
|
||||
return {{"ID", tagId},
|
||||
{"pose",
|
||||
{{"translation", {{"x", xPos}, {"y", yPos}, {"z", zPos}}},
|
||||
|
||||
@@ -40,7 +40,7 @@ static void dumpJson(CameraModel& camera_model,
|
||||
camera_model.distortion_coefficients.data() +
|
||||
camera_model.distortion_coefficients.size());
|
||||
|
||||
wpi::json result = {
|
||||
wpi::util::json result = {
|
||||
{"camera_matrix", camera_matrix},
|
||||
{"distortion_coefficients", distortion_coefficients},
|
||||
{"avg_reprojection_error", camera_model.avg_reprojection_error}};
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
#include "wpi/util/json.hpp"
|
||||
|
||||
namespace fieldcalibration {
|
||||
int calibrate(std::string input_dir_path, wpi::json& output_json,
|
||||
int calibrate(std::string input_dir_path, wpi::util::json& output_json,
|
||||
std::string camera_model_path, std::string ideal_map_path,
|
||||
int pinned_tag_id, bool show_debug_window);
|
||||
} // namespace fieldcalibration
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
class Fieldmap {
|
||||
public:
|
||||
Fieldmap() = default;
|
||||
explicit Fieldmap(const wpi::json& json) {
|
||||
explicit Fieldmap(const wpi::util::json& json) {
|
||||
double field_length_meters =
|
||||
static_cast<double>(json.at("field").at("length"));
|
||||
double field_width_meters =
|
||||
@@ -50,8 +50,8 @@ class Fieldmap {
|
||||
|
||||
bool hasTag(int tag) { return tagMap.find(tag) != tagMap.end(); }
|
||||
|
||||
wpi::json toJson() {
|
||||
wpi::json json;
|
||||
wpi::util::json toJson() {
|
||||
wpi::util::json json;
|
||||
for (auto& [key, val] : tagMap) {
|
||||
json["tags"].push_back(val.toJson());
|
||||
}
|
||||
|
||||
@@ -9,6 +9,6 @@
|
||||
#include "wpi/util/json.hpp"
|
||||
|
||||
namespace fmap {
|
||||
wpi::json singleTag(int tag, const tag::Pose& tagpose);
|
||||
wpi::json convertfmap(const wpi::json& json);
|
||||
wpi::util::json singleTag(int tag, const tag::Pose& tagpose);
|
||||
wpi::util::json convertfmap(const wpi::util::json& json);
|
||||
} // namespace fmap
|
||||
|
||||
@@ -20,6 +20,6 @@ class Pose {
|
||||
Eigen::Quaterniond quaternion;
|
||||
Eigen::Matrix3d rotationMatrix;
|
||||
Eigen::Matrix4d transformMatrixFmap;
|
||||
wpi::json toJson();
|
||||
wpi::util::json toJson();
|
||||
};
|
||||
} // namespace tag
|
||||
|
||||
@@ -288,7 +288,7 @@ compose_r_core(// output
|
||||
|
||||
Described here:
|
||||
|
||||
Altmann, Simon L. "Hamilton, Rodrigues, and the Quaternion Scandal."
|
||||
Altmann, Simon L. "Hamilton, Rodrigues, and the wpi::math::Quaternion Scandal."
|
||||
Mathematics Magazine, vol. 62, no. 5, 1989, pp. 291–308
|
||||
|
||||
Available here:
|
||||
|
||||
@@ -26,7 +26,7 @@ cameracalibration::CameraModel cameraModel = {
|
||||
.distortion_coefficients = Eigen::Matrix<double, 8, 1>::Zero(),
|
||||
.avg_reprojection_error = 0.0};
|
||||
|
||||
wpi::json output_json;
|
||||
wpi::util::json output_json;
|
||||
|
||||
#ifdef __linux__
|
||||
const std::string fileSuffix = ".avi";
|
||||
|
||||
Reference in New Issue
Block a user