diff --git a/glass/src/lib/native/cpp/hardware/Gyro.cpp b/glass/src/lib/native/cpp/hardware/Gyro.cpp new file mode 100644 index 0000000000..3ee8fc2d89 --- /dev/null +++ b/glass/src/lib/native/cpp/hardware/Gyro.cpp @@ -0,0 +1,84 @@ +/*----------------------------------------------------------------------------*/ +/* Copyright (c) 2020 FIRST. All Rights Reserved. */ +/* Open Source Software - may be modified and shared by FRC teams. The code */ +/* must be accompanied by the FIRST BSD license file in the root directory of */ +/* the project. */ +/*----------------------------------------------------------------------------*/ + +#include "glass/hardware/Gyro.h" + +#include + +#define IMGUI_DEFINE_MATH_OPERATORS + +#include +#include +#include + +#include "glass/Context.h" +#include "glass/DataSource.h" + +using namespace glass; + +void glass::DisplayGyro(GyroModel* m) { + static const auto kColorWhite = IM_COL32(255, 255, 255, 255); + static const auto kColorGray = IM_COL32(200, 200, 200, 255); + static const auto kColorPurple = IM_COL32(200, 200, 255, 255); + + auto angle = m->GetAngleData(); + if (!angle || !m->Exists()) { + ImGui::PushStyleColor(ImGuiCol_Text, IM_COL32(96, 96, 96, 255)); + ImGui::Text("Unknown Gyro"); + ImGui::PopStyleColor(); + return; + } + + // Display the numeric angle value. This can be editable in some cases (i.e. + // running from HALSIM). + auto flags = + m->IsReadOnly() ? ImGuiInputTextFlags_ReadOnly : ImGuiInputTextFlags_None; + auto value = angle->GetValue(); + ImGui::SetNextItemWidth(ImGui::GetFontSize() * 8); + if (ImGui::InputDouble("Gyro Angle (Deg)", &value, 0.0, 0.0, "%.4f", flags)) + m->SetAngle(value); + + // Draw the gyro indicator. + ImDrawList* draw = ImGui::GetWindowDrawList(); + ImVec2 window = ImGui::GetWindowPos(); + float w = ImGui::GetWindowWidth(); + float h = ImGui::GetWindowHeight(); + + float radius = (w < h) ? w * 0.3 : h * 0.3; + ImVec2 center = window + ImVec2(w / 2, h / 2 + ImGui::GetFontSize()); + + // Add the primary circle. + draw->AddCircle(center, radius, kColorWhite, 100, 1.5); + + // Draw the spokes at every 5 degrees and a "major" spoke every 45 degrees. + for (int i = -175; i <= 180; i += 5) { + double radians = i * 2 * wpi::math::pi / 360.0; + ImVec2 direction(std::sin(radians), -std::cos(radians)); + + bool major = i % 45 == 0; + auto color = major ? kColorWhite : kColorGray; + + draw->AddLine(center + (direction * radius), + center + (direction * radius * (major ? 1.07f : 1.03f)), + color, 1.2f); + if (major) { + char txt[16]; + std::snprintf(txt, sizeof(txt), "%d°", i); + draw->AddText( + center + (direction * radius * 1.25) - ImGui::CalcTextSize(txt) * 0.5, + kColorWhite, txt, nullptr); + } + } + + draw->AddCircleFilled(center, radius * 0.075, kColorPurple, 50); + + double radians = value * 2 * wpi::math::pi / 360.0; + draw->AddLine( + center - ImVec2(1, 0), + center + ImVec2(std::sin(radians), -std::cos(radians)) * radius * 0.95f, + kColorPurple, 3); +} diff --git a/glass/src/lib/native/cpp/hardware/SpeedController.cpp b/glass/src/lib/native/cpp/hardware/SpeedController.cpp new file mode 100644 index 0000000000..52dc242507 --- /dev/null +++ b/glass/src/lib/native/cpp/hardware/SpeedController.cpp @@ -0,0 +1,36 @@ +/*----------------------------------------------------------------------------*/ +/* Copyright (c) 2020 FIRST. All Rights Reserved. */ +/* Open Source Software - may be modified and shared by FRC teams. The code */ +/* must be accompanied by the FIRST BSD license file in the root directory of */ +/* the project. */ +/*----------------------------------------------------------------------------*/ + +#include "glass/hardware/SpeedController.h" + +#include + +#include "glass/Context.h" +#include "glass/DataSource.h" + +using namespace glass; + +void glass::DisplaySpeedController(SpeedControllerModel* m) { + // Get duty cycle data from the model and do not display anything if the data + // is null. + auto dc = m->GetPercentData(); + if (!dc || !m->Exists()) { + ImGui::PushStyleColor(ImGuiCol_Text, IM_COL32(96, 96, 96, 255)); + ImGui::Text("Unknown SpeedController"); + ImGui::PopStyleColor(); + return; + } + + // Add button to zero output. + if (ImGui::Button("Zero")) m->SetPercent(0.0); + ImGui::SameLine(); + + // Display a slider for the data. + float value = dc->GetValue(); + ImGui::SetNextItemWidth(ImGui::GetFontSize() * 8); + if (dc->SliderFloat("% Output", &value, -1.0f, 1.0f)) m->SetPercent(value); +} diff --git a/glass/src/lib/native/cpp/other/CommandScheduler.cpp b/glass/src/lib/native/cpp/other/CommandScheduler.cpp new file mode 100644 index 0000000000..a08422e458 --- /dev/null +++ b/glass/src/lib/native/cpp/other/CommandScheduler.cpp @@ -0,0 +1,41 @@ +/*----------------------------------------------------------------------------*/ +/* Copyright (c) 2020 FIRST. All Rights Reserved. */ +/* Open Source Software - may be modified and shared by FRC teams. The code */ +/* must be accompanied by the FIRST BSD license file in the root directory of */ +/* the project. */ +/*----------------------------------------------------------------------------*/ + +#include "glass/other/CommandScheduler.h" + +#include + +#include "glass/Context.h" +#include "glass/DataSource.h" + +using namespace glass; + +void glass::DisplayCommandScheduler(CommandSchedulerModel* m) { + ImGui::SetNextItemWidth(ImGui::GetFontSize() * 20); + ImGui::Text("Scheduled Commands: "); + ImGui::Separator(); + ImGui::Spacing(); + + if (m->Exists()) { + float pos = ImGui::GetContentRegionAvail().x * 0.97f - + ImGui::CalcTextSize("Cancel").x; + + const auto& commands = m->GetCurrentCommands(); + for (size_t i = 0; i < commands.size(); ++i) { + ImGui::Text("%s", commands[i].c_str()); + ImGui::SameLine(pos); + + ImGui::PushID(i); + if (ImGui::Button("Cancel")) m->CancelCommand(i); + ImGui::PopID(); + } + } else { + ImGui::PushStyleColor(ImGuiCol_Text, IM_COL32(96, 96, 96, 255)); + ImGui::Text("Unknown Scheduler"); + ImGui::PopStyleColor(); + } +} diff --git a/glass/src/lib/native/cpp/other/CommandSelector.cpp b/glass/src/lib/native/cpp/other/CommandSelector.cpp new file mode 100644 index 0000000000..57fa83402e --- /dev/null +++ b/glass/src/lib/native/cpp/other/CommandSelector.cpp @@ -0,0 +1,34 @@ +/*----------------------------------------------------------------------------*/ +/* Copyright (c) 2020 FIRST. All Rights Reserved. */ +/* Open Source Software - may be modified and shared by FRC teams. The code */ +/* must be accompanied by the FIRST BSD license file in the root directory of */ +/* the project. */ +/*----------------------------------------------------------------------------*/ + +#include "glass/other/CommandSelector.h" + +#include + +#include "glass/Context.h" +#include "glass/DataSource.h" + +using namespace glass; + +void glass::DisplayCommandSelector(CommandSelectorModel* m) { + if (auto name = m->GetName()) ImGui::Text("%s", name); + if (m->Exists()) { + if (auto run = m->GetRunningData()) { + bool running = run->GetValue(); + if (ImGui::Button(running ? "Cancel" : "Run")) { + running = !running; + m->SetRunning(running); + } + ImGui::SameLine(); + if (running) ImGui::Text("Running..."); + } + } else { + ImGui::PushStyleColor(ImGuiCol_Text, IM_COL32(96, 96, 96, 255)); + ImGui::Text("Unknown Command"); + ImGui::PopStyleColor(); + } +} diff --git a/glass/src/lib/native/cpp/other/PIDController.cpp b/glass/src/lib/native/cpp/other/PIDController.cpp new file mode 100644 index 0000000000..6fb615f6f5 --- /dev/null +++ b/glass/src/lib/native/cpp/other/PIDController.cpp @@ -0,0 +1,54 @@ +/*----------------------------------------------------------------------------*/ +/* Copyright (c) 2020 FIRST. All Rights Reserved. */ +/* Open Source Software - may be modified and shared by FRC teams. The code */ +/* must be accompanied by the FIRST BSD license file in the root directory of */ +/* the project. */ +/*----------------------------------------------------------------------------*/ + +#include "glass/other/PIDController.h" + +#include + +#include + +#include "glass/Context.h" +#include "glass/DataSource.h" + +using namespace glass; + +void glass::DisplayPIDController(PIDControllerModel* m) { + if (auto name = m->GetName()) { + ImGui::Text("%s", name); + ImGui::Separator(); + } + + if (m->Exists()) { + auto createTuningParameter = [](const char* name, double* v, + std::function callback) { + ImGui::SetNextItemWidth(ImGui::GetFontSize() * 4); + if (ImGui::InputDouble(name, v, 0.0, 0.0, "%.3f")) callback(*v); + }; + + if (auto p = m->GetPData()) { + double value = p->GetValue(); + createTuningParameter("P", &value, [=](auto v) { m->SetP(v); }); + } + if (auto i = m->GetIData()) { + double value = i->GetValue(); + createTuningParameter("I", &value, [=](auto v) { m->SetI(v); }); + } + if (auto d = m->GetDData()) { + double value = d->GetValue(); + createTuningParameter("D", &value, [=](auto v) { m->SetD(v); }); + } + if (auto s = m->GetSetpointData()) { + double value = s->GetValue(); + createTuningParameter("Setpoint", &value, + [=](auto v) { m->SetSetpoint(v); }); + } + } else { + ImGui::PushStyleColor(ImGuiCol_Text, IM_COL32(96, 96, 96, 255)); + ImGui::Text("Unknown PID Controller"); + ImGui::PopStyleColor(); + } +} diff --git a/glass/src/lib/native/cpp/other/Subsystem.cpp b/glass/src/lib/native/cpp/other/Subsystem.cpp new file mode 100644 index 0000000000..6ac54c0df7 --- /dev/null +++ b/glass/src/lib/native/cpp/other/Subsystem.cpp @@ -0,0 +1,32 @@ +/*----------------------------------------------------------------------------*/ +/* Copyright (c) 2020 FIRST. All Rights Reserved. */ +/* Open Source Software - may be modified and shared by FRC teams. The code */ +/* must be accompanied by the FIRST BSD license file in the root directory of */ +/* the project. */ +/*----------------------------------------------------------------------------*/ + +#include "glass/other/Subsystem.h" + +#include + +#include "glass/Context.h" +#include "glass/DataSource.h" + +using namespace glass; + +void glass::DisplaySubsystem(SubsystemModel* m) { + if (auto name = m->GetName()) { + ImGui::Text("%s", name); + ImGui::Separator(); + } + if (m->Exists()) { + std::string defaultCommand = m->GetDefaultCommand(); + std::string currentCommand = m->GetCurrentCommand(); + ImGui::Text("%s", ("Default Command: " + defaultCommand).c_str()); + ImGui::Text("%s", ("Current Command: " + currentCommand).c_str()); + } else { + ImGui::PushStyleColor(ImGuiCol_Text, IM_COL32(96, 96, 96, 255)); + ImGui::Text("Unknown Subsystem"); + ImGui::PopStyleColor(); + } +} diff --git a/glass/src/lib/native/include/glass/hardware/Gyro.h b/glass/src/lib/native/include/glass/hardware/Gyro.h new file mode 100644 index 0000000000..a94e7bb0f5 --- /dev/null +++ b/glass/src/lib/native/include/glass/hardware/Gyro.h @@ -0,0 +1,26 @@ +/*----------------------------------------------------------------------------*/ +/* Copyright (c) 2020 FIRST. All Rights Reserved. */ +/* Open Source Software - may be modified and shared by FRC teams. The code */ +/* must be accompanied by the FIRST BSD license file in the root directory of */ +/* the project. */ +/*----------------------------------------------------------------------------*/ + +#pragma once + +#include +#include + +#include "glass/Model.h" + +namespace glass { +class DataSource; +class GyroModel : public Model { + public: + virtual const char* GetName() const = 0; + virtual const char* GetSimDevice() const = 0; + + virtual DataSource* GetAngleData() = 0; + virtual void SetAngle(double angle) = 0; +}; +void DisplayGyro(GyroModel* m); +} // namespace glass diff --git a/glass/src/lib/native/include/glass/hardware/SpeedController.h b/glass/src/lib/native/include/glass/hardware/SpeedController.h new file mode 100644 index 0000000000..5a9323eb5a --- /dev/null +++ b/glass/src/lib/native/include/glass/hardware/SpeedController.h @@ -0,0 +1,25 @@ +/*----------------------------------------------------------------------------*/ +/* Copyright (c) 2020 FIRST. All Rights Reserved. */ +/* Open Source Software - may be modified and shared by FRC teams. The code */ +/* must be accompanied by the FIRST BSD license file in the root directory of */ +/* the project. */ +/*----------------------------------------------------------------------------*/ + +#pragma once + +#include +#include + +#include "glass/Model.h" + +namespace glass { +class DataSource; +class SpeedControllerModel : public Model { + public: + virtual const char* GetName() const = 0; + virtual const char* GetSimDevice() const = 0; + virtual DataSource* GetPercentData() = 0; + virtual void SetPercent(double value) = 0; +}; +void DisplaySpeedController(SpeedControllerModel* m); +} // namespace glass diff --git a/glass/src/lib/native/include/glass/other/CommandScheduler.h b/glass/src/lib/native/include/glass/other/CommandScheduler.h new file mode 100644 index 0000000000..6a50a043d1 --- /dev/null +++ b/glass/src/lib/native/include/glass/other/CommandScheduler.h @@ -0,0 +1,27 @@ +/*----------------------------------------------------------------------------*/ +/* Copyright (c) 2020 FIRST. All Rights Reserved. */ +/* Open Source Software - may be modified and shared by FRC teams. The code */ +/* must be accompanied by the FIRST BSD license file in the root directory of */ +/* the project. */ +/*----------------------------------------------------------------------------*/ + +#pragma once + +#include +#include + +#include +#include + +#include "glass/Model.h" + +namespace glass { +class DataSource; +class CommandSchedulerModel : public Model { + public: + virtual const char* GetName() const = 0; + virtual const std::vector& GetCurrentCommands() = 0; + virtual void CancelCommand(size_t index) = 0; +}; +void DisplayCommandScheduler(CommandSchedulerModel* m); +} // namespace glass diff --git a/glass/src/lib/native/include/glass/other/CommandSelector.h b/glass/src/lib/native/include/glass/other/CommandSelector.h new file mode 100644 index 0000000000..3b7b321d2d --- /dev/null +++ b/glass/src/lib/native/include/glass/other/CommandSelector.h @@ -0,0 +1,24 @@ +/*----------------------------------------------------------------------------*/ +/* Copyright (c) 2020 FIRST. All Rights Reserved. */ +/* Open Source Software - may be modified and shared by FRC teams. The code */ +/* must be accompanied by the FIRST BSD license file in the root directory of */ +/* the project. */ +/*----------------------------------------------------------------------------*/ + +#pragma once + +#include +#include + +#include "glass/Model.h" + +namespace glass { +class DataSource; +class CommandSelectorModel : public Model { + public: + virtual const char* GetName() const = 0; + virtual DataSource* GetRunningData() = 0; + virtual void SetRunning(bool run) = 0; +}; +void DisplayCommandSelector(CommandSelectorModel* m); +} // namespace glass diff --git a/glass/src/lib/native/include/glass/other/PIDController.h b/glass/src/lib/native/include/glass/other/PIDController.h new file mode 100644 index 0000000000..942795adcf --- /dev/null +++ b/glass/src/lib/native/include/glass/other/PIDController.h @@ -0,0 +1,29 @@ +/*----------------------------------------------------------------------------*/ +/* Copyright (c) 2020 FIRST. All Rights Reserved. */ +/* Open Source Software - may be modified and shared by FRC teams. The code */ +/* must be accompanied by the FIRST BSD license file in the root directory of */ +/* the project. */ +/*----------------------------------------------------------------------------*/ + +#pragma once + +#include "glass/Model.h" + +namespace glass { +class DataSource; +class PIDControllerModel : public Model { + public: + virtual const char* GetName() const = 0; + + virtual DataSource* GetPData() = 0; + virtual DataSource* GetIData() = 0; + virtual DataSource* GetDData() = 0; + virtual DataSource* GetSetpointData() = 0; + + virtual void SetP(double value) = 0; + virtual void SetI(double value) = 0; + virtual void SetD(double value) = 0; + virtual void SetSetpoint(double value) = 0; +}; +void DisplayPIDController(PIDControllerModel* m); +} // namespace glass diff --git a/glass/src/lib/native/include/glass/other/Subsystem.h b/glass/src/lib/native/include/glass/other/Subsystem.h new file mode 100644 index 0000000000..a28bad4d78 --- /dev/null +++ b/glass/src/lib/native/include/glass/other/Subsystem.h @@ -0,0 +1,24 @@ +/*----------------------------------------------------------------------------*/ +/* Copyright (c) 2020 FIRST. All Rights Reserved. */ +/* Open Source Software - may be modified and shared by FRC teams. The code */ +/* must be accompanied by the FIRST BSD license file in the root directory of */ +/* the project. */ +/*----------------------------------------------------------------------------*/ + +#pragma once + +#include +#include + +#include "glass/Model.h" + +namespace glass { +class DataSource; +class SubsystemModel : public Model { + public: + virtual const char* GetName() const = 0; + virtual const char* GetDefaultCommand() const = 0; + virtual const char* GetCurrentCommand() const = 0; +}; +void DisplaySubsystem(SubsystemModel* m); +} // namespace glass diff --git a/glass/src/libnt/native/cpp/NTCommandScheduler.cpp b/glass/src/libnt/native/cpp/NTCommandScheduler.cpp new file mode 100644 index 0000000000..f30fa5035d --- /dev/null +++ b/glass/src/libnt/native/cpp/NTCommandScheduler.cpp @@ -0,0 +1,55 @@ +/*----------------------------------------------------------------------------*/ +/* Copyright (c) 2020 FIRST. All Rights Reserved. */ +/* Open Source Software - may be modified and shared by FRC teams. The code */ +/* must be accompanied by the FIRST BSD license file in the root directory of */ +/* the project. */ +/*----------------------------------------------------------------------------*/ + +#include "glass/networktables/NTCommandScheduler.h" + +#include + +using namespace glass; + +NTCommandSchedulerModel::NTCommandSchedulerModel(wpi::StringRef path) + : NTCommandSchedulerModel(nt::GetDefaultInstance(), path) {} + +NTCommandSchedulerModel::NTCommandSchedulerModel(NT_Inst instance, + wpi::StringRef path) + : m_nt(instance), + m_name(m_nt.GetEntry(path + "/.name")), + m_commands(m_nt.GetEntry(path + "/Names")), + m_ids(m_nt.GetEntry(path + "/Ids")), + m_cancel(m_nt.GetEntry(path + "/Cancel")), + m_nameValue(path.rsplit('/').second) { + m_nt.AddListener(m_name); + m_nt.AddListener(m_commands); + m_nt.AddListener(m_ids); + m_nt.AddListener(m_cancel); + Update(); +} + +void NTCommandSchedulerModel::CancelCommand(size_t index) { + if (index < m_idsValue.size()) + nt::SetEntryValue( + m_cancel, nt::NetworkTableValue::MakeDoubleArray({m_idsValue[index]})); +} + +void NTCommandSchedulerModel::Update() { + for (auto&& event : m_nt.PollListener()) { + if (event.entry == m_name) { + if (event.value && event.value->IsString()) + m_nameValue = event.value->GetString(); + } else if (event.entry == m_commands) { + if (event.value && event.value->IsStringArray()) + m_commandsValue = event.value->GetStringArray(); + } else if (event.entry == m_ids) { + if (event.value && event.value->IsDoubleArray()) + m_idsValue = event.value->GetDoubleArray(); + } + } +} + +bool NTCommandSchedulerModel::Exists() { + return m_nt.IsConnected() && nt::GetEntryType(m_commands) != NT_UNASSIGNED; +} diff --git a/glass/src/libnt/native/cpp/NTCommandSelector.cpp b/glass/src/libnt/native/cpp/NTCommandSelector.cpp new file mode 100644 index 0000000000..a1e98ac5d9 --- /dev/null +++ b/glass/src/libnt/native/cpp/NTCommandSelector.cpp @@ -0,0 +1,46 @@ +/*----------------------------------------------------------------------------*/ +/* Copyright (c) 2020 FIRST. All Rights Reserved. */ +/* Open Source Software - may be modified and shared by FRC teams. The code */ +/* must be accompanied by the FIRST BSD license file in the root directory of */ +/* the project. */ +/*----------------------------------------------------------------------------*/ + +#include "glass/networktables/NTCommandSelector.h" + +using namespace glass; + +NTCommandSelectorModel::NTCommandSelectorModel(wpi::StringRef path) + : NTCommandSelectorModel(nt::GetDefaultInstance(), path) {} + +NTCommandSelectorModel::NTCommandSelectorModel(NT_Inst instance, + wpi::StringRef path) + : m_nt(instance), + m_running(m_nt.GetEntry(path + "/running")), + m_name(m_nt.GetEntry(path + "/.name")), + m_runningData("NTCmd:" + path), + m_nameValue(path.rsplit('/').second) { + m_runningData.SetDigital(true); + m_nt.AddListener(m_running); + m_nt.AddListener(m_name); + Update(); +} + +void NTCommandSelectorModel::SetRunning(bool run) { + nt::SetEntryValue(m_running, nt::NetworkTableValue::MakeBoolean(run)); +} + +void NTCommandSelectorModel::Update() { + for (auto&& event : m_nt.PollListener()) { + if (event.entry == m_running) { + if (event.value && event.value->IsBoolean()) + m_runningData.SetValue(event.value->GetBoolean()); + } else if (event.entry == m_name) { + if (event.value && event.value->IsString()) + m_nameValue = event.value->GetString(); + } + } +} + +bool NTCommandSelectorModel::Exists() { + return m_nt.IsConnected() && nt::GetEntryType(m_running) != NT_UNASSIGNED; +} diff --git a/glass/src/libnt/native/cpp/NTGyro.cpp b/glass/src/libnt/native/cpp/NTGyro.cpp new file mode 100644 index 0000000000..04944fc06d --- /dev/null +++ b/glass/src/libnt/native/cpp/NTGyro.cpp @@ -0,0 +1,40 @@ +/*----------------------------------------------------------------------------*/ +/* Copyright (c) 2020 FIRST. All Rights Reserved. */ +/* Open Source Software - may be modified and shared by FRC teams. The code */ +/* must be accompanied by the FIRST BSD license file in the root directory of */ +/* the project. */ +/*----------------------------------------------------------------------------*/ + +#include "glass/networktables/NTGyro.h" + +using namespace glass; + +NTGyroModel::NTGyroModel(wpi::StringRef path) + : NTGyroModel(nt::GetDefaultInstance(), path) {} + +NTGyroModel::NTGyroModel(NT_Inst instance, wpi::StringRef path) + : m_nt(instance), + m_angle(m_nt.GetEntry(path + "/Value")), + m_name(m_nt.GetEntry(path + "/.name")), + m_angleData("NT_Gyro:" + path), + m_nameValue(path.rsplit('/').second) { + m_nt.AddListener(m_angle); + m_nt.AddListener(m_name); + Update(); +} + +void NTGyroModel::Update() { + for (auto&& event : m_nt.PollListener()) { + if (event.entry == m_angle) { + if (event.value && event.value->IsDouble()) + m_angleData.SetValue(event.value->GetDouble()); + } else if (event.entry == m_name) { + if (event.value && event.value->IsString()) + m_nameValue = event.value->GetString(); + } + } +} + +bool NTGyroModel::Exists() { + return m_nt.IsConnected() && nt::GetEntryType(m_angle) != NT_UNASSIGNED; +} diff --git a/glass/src/libnt/native/cpp/NTPIDController.cpp b/glass/src/libnt/native/cpp/NTPIDController.cpp new file mode 100644 index 0000000000..9b734d929b --- /dev/null +++ b/glass/src/libnt/native/cpp/NTPIDController.cpp @@ -0,0 +1,75 @@ +/*----------------------------------------------------------------------------*/ +/* Copyright (c) 2020 FIRST. All Rights Reserved. */ +/* Open Source Software - may be modified and shared by FRC teams. The code */ +/* must be accompanied by the FIRST BSD license file in the root directory of */ +/* the project. */ +/*----------------------------------------------------------------------------*/ + +#include "glass/networktables/NTPIDController.h" + +using namespace glass; + +NTPIDControllerModel::NTPIDControllerModel(wpi::StringRef path) + : NTPIDControllerModel(nt::GetDefaultInstance(), path) {} + +NTPIDControllerModel::NTPIDControllerModel(NT_Inst instance, + wpi::StringRef path) + : m_nt(instance), + m_name(m_nt.GetEntry(path + "/.name")), + m_p(m_nt.GetEntry(path + "/p")), + m_i(m_nt.GetEntry(path + "/i")), + m_d(m_nt.GetEntry(path + "/d")), + m_setpoint(m_nt.GetEntry(path + "/setpoint")), + m_pData("NTPIDCtrlP:" + path), + m_iData("NTPIDCtrlI:" + path), + m_dData("NTPIDCtrlD:" + path), + m_setpointData("NTPIDCtrlStpt:" + path), + m_nameValue(path.rsplit('/').second) { + m_nt.AddListener(m_name); + m_nt.AddListener(m_p); + m_nt.AddListener(m_i); + m_nt.AddListener(m_d); + m_nt.AddListener(m_setpoint); + Update(); +} + +void NTPIDControllerModel::SetP(double value) { + nt::SetEntryValue(m_p, nt::NetworkTableValue::MakeDouble(value)); +} + +void NTPIDControllerModel::SetI(double value) { + nt::SetEntryValue(m_i, nt::NetworkTableValue::MakeDouble(value)); +} + +void NTPIDControllerModel::SetD(double value) { + nt::SetEntryValue(m_d, nt::NetworkTableValue::MakeDouble(value)); +} + +void NTPIDControllerModel::SetSetpoint(double value) { + nt::SetEntryValue(m_setpoint, nt::NetworkTableValue::MakeDouble(value)); +} + +void NTPIDControllerModel::Update() { + for (auto&& event : m_nt.PollListener()) { + if (event.entry == m_name) { + if (event.value && event.value->IsString()) + m_nameValue = event.value->GetString(); + } else if (event.entry == m_p) { + if (event.value && event.value->IsDouble()) + m_pData.SetValue(event.value->GetDouble()); + } else if (event.entry == m_i) { + if (event.value && event.value->IsDouble()) + m_iData.SetValue(event.value->GetDouble()); + } else if (event.entry == m_d) { + if (event.value && event.value->IsDouble()) + m_dData.SetValue(event.value->GetDouble()); + } else if (event.entry == m_setpoint) { + if (event.value && event.value->IsDouble()) + m_setpointData.SetValue(event.value->GetDouble()); + } + } +} + +bool NTPIDControllerModel::Exists() { + return m_nt.IsConnected() && nt::GetEntryType(m_setpoint) != NT_UNASSIGNED; +} diff --git a/glass/src/libnt/native/cpp/NTSpeedController.cpp b/glass/src/libnt/native/cpp/NTSpeedController.cpp new file mode 100644 index 0000000000..eb3d670219 --- /dev/null +++ b/glass/src/libnt/native/cpp/NTSpeedController.cpp @@ -0,0 +1,45 @@ +/*----------------------------------------------------------------------------*/ +/* Copyright (c) 2020 FIRST. All Rights Reserved. */ +/* Open Source Software - may be modified and shared by FRC teams. The code */ +/* must be accompanied by the FIRST BSD license file in the root directory of */ +/* the project. */ +/*----------------------------------------------------------------------------*/ + +#include "glass/networktables/NTSpeedController.h" + +using namespace glass; + +NTSpeedControllerModel::NTSpeedControllerModel(wpi::StringRef path) + : NTSpeedControllerModel(nt::GetDefaultInstance(), path) {} + +NTSpeedControllerModel::NTSpeedControllerModel(NT_Inst instance, + wpi::StringRef path) + : m_nt(instance), + m_value(m_nt.GetEntry(path + "/Value")), + m_name(m_nt.GetEntry(path + "/.name")), + m_valueData("NT_SpdCtrl:" + path), + m_nameValue(path.rsplit('/').second) { + m_nt.AddListener(m_value); + m_nt.AddListener(m_name); + Update(); +} + +void NTSpeedControllerModel::SetPercent(double value) { + nt::SetEntryValue(m_value, nt::NetworkTableValue::MakeDouble(value)); +} + +void NTSpeedControllerModel::Update() { + for (auto&& event : m_nt.PollListener()) { + if (event.entry == m_value) { + if (event.value && event.value->IsDouble()) + m_valueData.SetValue(event.value->GetDouble()); + } else if (event.entry == m_name) { + if (event.value && event.value->IsString()) + m_nameValue = event.value->GetString(); + } + } +} + +bool NTSpeedControllerModel::Exists() { + return m_nt.IsConnected() && nt::GetEntryType(m_value) != NT_UNASSIGNED; +} diff --git a/glass/src/libnt/native/cpp/NTSubsystem.cpp b/glass/src/libnt/native/cpp/NTSubsystem.cpp new file mode 100644 index 0000000000..0cd57e2cdc --- /dev/null +++ b/glass/src/libnt/native/cpp/NTSubsystem.cpp @@ -0,0 +1,45 @@ +/*----------------------------------------------------------------------------*/ +/* Copyright (c) 2020 FIRST. All Rights Reserved. */ +/* Open Source Software - may be modified and shared by FRC teams. The code */ +/* must be accompanied by the FIRST BSD license file in the root directory of */ +/* the project. */ +/*----------------------------------------------------------------------------*/ + +#include "glass/networktables/NTSubsystem.h" + +using namespace glass; + +NTSubsystemModel::NTSubsystemModel(wpi::StringRef path) + : NTSubsystemModel(nt::GetDefaultInstance(), path) {} + +NTSubsystemModel::NTSubsystemModel(NT_Inst instance, wpi::StringRef path) + : m_nt(instance), + m_name(m_nt.GetEntry(path + "/.name")), + m_defaultCommand(m_nt.GetEntry(path + "/.default")), + m_currentCommand(m_nt.GetEntry(path + "/.command")) { + m_nt.AddListener(m_name); + m_nt.AddListener(m_defaultCommand); + m_nt.AddListener(m_currentCommand); + Update(); +} + +void NTSubsystemModel::Update() { + for (auto&& event : m_nt.PollListener()) { + if (event.entry == m_name) { + if (event.value && event.value->IsString()) + m_nameValue = event.value->GetString(); + } else if (event.entry == m_defaultCommand) { + if (event.value && event.value->IsString()) + m_defaultCommandValue = event.value->GetString(); + } else if (event.entry == m_currentCommand) { + if (event.value && event.value->IsString()) { + m_currentCommandValue = event.value->GetString(); + } + } + } +} + +bool NTSubsystemModel::Exists() { + return m_nt.IsConnected() && + nt::GetEntryType(m_defaultCommand) != NT_UNASSIGNED; +} diff --git a/glass/src/libnt/native/cpp/StandardNetworkTables.cpp b/glass/src/libnt/native/cpp/StandardNetworkTables.cpp index 55f937d759..d808beeca9 100644 --- a/glass/src/libnt/native/cpp/StandardNetworkTables.cpp +++ b/glass/src/libnt/native/cpp/StandardNetworkTables.cpp @@ -5,16 +5,44 @@ /* the project. */ /*----------------------------------------------------------------------------*/ +#include "glass/networktables/NTCommandScheduler.h" +#include "glass/networktables/NTCommandSelector.h" #include "glass/networktables/NTDigitalInput.h" #include "glass/networktables/NTDigitalOutput.h" #include "glass/networktables/NTFMS.h" #include "glass/networktables/NTField2D.h" +#include "glass/networktables/NTGyro.h" +#include "glass/networktables/NTPIDController.h" +#include "glass/networktables/NTSpeedController.h" #include "glass/networktables/NTStringChooser.h" +#include "glass/networktables/NTSubsystem.h" #include "glass/networktables/NetworkTablesProvider.h" using namespace glass; void glass::AddStandardNetworkTablesViews(NetworkTablesProvider& provider) { + provider.Register( + NTCommandSchedulerModel::kType, + [](NT_Inst inst, const char* path) { + return std::make_unique(inst, path); + }, + [](Window* win, Model* model, const char*) { + win->SetDefaultSize(400, 200); + return MakeFunctionView([=] { + DisplayCommandScheduler(static_cast(model)); + }); + }); + provider.Register( + NTCommandSelectorModel::kType, + [](NT_Inst inst, const char* path) { + return std::make_unique(inst, path); + }, + [](Window* win, Model* model, const char*) { + win->SetFlags(ImGuiWindowFlags_AlwaysAutoResize); + return MakeFunctionView([=] { + DisplayCommandSelector(static_cast(model)); + }); + }); provider.Register( NTFMSModel::kType, [](NT_Inst inst, const char* path) { @@ -59,6 +87,38 @@ void glass::AddStandardNetworkTablesViews(NetworkTablesProvider& provider) { return std::make_unique( static_cast(model)); }); + provider.Register( + NTGyroModel::kType, + [](NT_Inst inst, const char* path) { + return std::make_unique(inst, path); + }, + [](Window* win, Model* model, const char* path) { + win->SetDefaultSize(320, 380); + return MakeFunctionView( + [=] { DisplayGyro(static_cast(model)); }); + }); + provider.Register( + NTPIDControllerModel::kType, + [](NT_Inst inst, const char* path) { + return std::make_unique(inst, path); + }, + [](Window* win, Model* model, const char* path) { + win->SetFlags(ImGuiWindowFlags_AlwaysAutoResize); + return MakeFunctionView([=] { + DisplayPIDController(static_cast(model)); + }); + }); + provider.Register( + NTSpeedControllerModel::kType, + [](NT_Inst inst, const char* path) { + return std::make_unique(inst, path); + }, + [](Window* win, Model* model, const char* path) { + win->SetFlags(ImGuiWindowFlags_AlwaysAutoResize); + return MakeFunctionView([=] { + DisplaySpeedController(static_cast(model)); + }); + }); provider.Register( NTStringChooserModel::kType, [](NT_Inst inst, const char* path) { @@ -70,4 +130,14 @@ void glass::AddStandardNetworkTablesViews(NetworkTablesProvider& provider) { DisplayStringChooser(static_cast(model)); }); }); + provider.Register( + NTSubsystemModel::kType, + [](NT_Inst inst, const char* path) { + return std::make_unique(inst, path); + }, + [](Window* win, Model* model, const char*) { + win->SetFlags(ImGuiWindowFlags_AlwaysAutoResize); + return MakeFunctionView( + [=] { DisplaySubsystem(static_cast(model)); }); + }); } diff --git a/glass/src/libnt/native/include/glass/networktables/NTCommandScheduler.h b/glass/src/libnt/native/include/glass/networktables/NTCommandScheduler.h new file mode 100644 index 0000000000..b8204b721a --- /dev/null +++ b/glass/src/libnt/native/include/glass/networktables/NTCommandScheduler.h @@ -0,0 +1,50 @@ +/*----------------------------------------------------------------------------*/ +/* Copyright (c) 2020 FIRST. All Rights Reserved. */ +/* Open Source Software - may be modified and shared by FRC teams. The code */ +/* must be accompanied by the FIRST BSD license file in the root directory of */ +/* the project. */ +/*----------------------------------------------------------------------------*/ + +#pragma once + +#include +#include + +#include +#include + +#include "glass/DataSource.h" +#include "glass/networktables/NetworkTablesHelper.h" +#include "glass/other/CommandScheduler.h" + +namespace glass { +class NTCommandSchedulerModel : public CommandSchedulerModel { + public: + static constexpr const char* kType = "Scheduler"; + + explicit NTCommandSchedulerModel(wpi::StringRef path); + NTCommandSchedulerModel(NT_Inst instance, wpi::StringRef path); + + const char* GetName() const override { return m_nameValue.c_str(); } + const std::vector& GetCurrentCommands() override { + return m_commandsValue; + } + + void CancelCommand(size_t index) override; + + void Update() override; + bool Exists() override; + bool IsReadOnly() override { return false; } + + private: + NetworkTablesHelper m_nt; + NT_Entry m_name; + NT_Entry m_commands; + NT_Entry m_ids; + NT_Entry m_cancel; + + std::string m_nameValue; + std::vector m_commandsValue; + std::vector m_idsValue; +}; +} // namespace glass diff --git a/glass/src/libnt/native/include/glass/networktables/NTCommandSelector.h b/glass/src/libnt/native/include/glass/networktables/NTCommandSelector.h new file mode 100644 index 0000000000..eb0c4b3b92 --- /dev/null +++ b/glass/src/libnt/native/include/glass/networktables/NTCommandSelector.h @@ -0,0 +1,43 @@ +/*----------------------------------------------------------------------------*/ +/* Copyright (c) 2020 FIRST. All Rights Reserved. */ +/* Open Source Software - may be modified and shared by FRC teams. The code */ +/* must be accompanied by the FIRST BSD license file in the root directory of */ +/* the project. */ +/*----------------------------------------------------------------------------*/ + +#pragma once + +#include + +#include +#include + +#include "glass/DataSource.h" +#include "glass/networktables/NetworkTablesHelper.h" +#include "glass/other/CommandSelector.h" + +namespace glass { +class NTCommandSelectorModel : public CommandSelectorModel { + public: + static constexpr const char* kType = "Command"; + + explicit NTCommandSelectorModel(wpi::StringRef path); + NTCommandSelectorModel(NT_Inst instance, wpi::StringRef path); + + const char* GetName() const override { return m_nameValue.c_str(); } + DataSource* GetRunningData() override { return &m_runningData; } + void SetRunning(bool run) override; + + void Update() override; + bool Exists() override; + bool IsReadOnly() override { return false; } + + private: + NetworkTablesHelper m_nt; + NT_Entry m_running; + NT_Entry m_name; + + DataSource m_runningData; + std::string m_nameValue; +}; +} // namespace glass diff --git a/glass/src/libnt/native/include/glass/networktables/NTGyro.h b/glass/src/libnt/native/include/glass/networktables/NTGyro.h new file mode 100644 index 0000000000..e16075f6e7 --- /dev/null +++ b/glass/src/libnt/native/include/glass/networktables/NTGyro.h @@ -0,0 +1,44 @@ +/*----------------------------------------------------------------------------*/ +/* Copyright (c) 2020 FIRST. All Rights Reserved. */ +/* Open Source Software - may be modified and shared by FRC teams. The code */ +/* must be accompanied by the FIRST BSD license file in the root directory of */ +/* the project. */ +/*----------------------------------------------------------------------------*/ + +#pragma once +#include + +#include +#include + +#include "glass/DataSource.h" +#include "glass/hardware/Gyro.h" +#include "glass/networktables/NetworkTablesHelper.h" + +namespace glass { +class NTGyroModel : public GyroModel { + public: + static constexpr const char* kType = "Gyro"; + + explicit NTGyroModel(wpi::StringRef path); + NTGyroModel(NT_Inst instance, wpi::StringRef path); + + const char* GetName() const override { return m_nameValue.c_str(); } + const char* GetSimDevice() const override { return nullptr; } + + DataSource* GetAngleData() override { return &m_angleData; } + void SetAngle(double value) override {} + + void Update() override; + bool Exists() override; + bool IsReadOnly() override { return true; } + + private: + NetworkTablesHelper m_nt; + NT_Entry m_angle; + NT_Entry m_name; + + DataSource m_angleData; + std::string m_nameValue; +}; +} // namespace glass diff --git a/glass/src/libnt/native/include/glass/networktables/NTPIDController.h b/glass/src/libnt/native/include/glass/networktables/NTPIDController.h new file mode 100644 index 0000000000..2b3401e626 --- /dev/null +++ b/glass/src/libnt/native/include/glass/networktables/NTPIDController.h @@ -0,0 +1,58 @@ +/*----------------------------------------------------------------------------*/ +/* Copyright (c) 2020 FIRST. All Rights Reserved. */ +/* Open Source Software - may be modified and shared by FRC teams. The code */ +/* must be accompanied by the FIRST BSD license file in the root directory of */ +/* the project. */ +/*----------------------------------------------------------------------------*/ + +#pragma once + +#include + +#include +#include + +#include "glass/DataSource.h" +#include "glass/networktables/NetworkTablesHelper.h" +#include "glass/other/PIDController.h" + +namespace glass { +class NTPIDControllerModel : public PIDControllerModel { + public: + static constexpr const char* kType = "PIDController"; + + explicit NTPIDControllerModel(wpi::StringRef path); + NTPIDControllerModel(NT_Inst instance, wpi::StringRef path); + + const char* GetName() const override { return m_nameValue.c_str(); } + + DataSource* GetPData() override { return &m_pData; } + DataSource* GetIData() override { return &m_iData; } + DataSource* GetDData() override { return &m_dData; } + DataSource* GetSetpointData() override { return &m_setpointData; } + + void SetP(double value) override; + void SetI(double value) override; + void SetD(double value) override; + void SetSetpoint(double value) override; + + void Update() override; + bool Exists() override; + bool IsReadOnly() override { return false; } + + private: + NetworkTablesHelper m_nt; + NT_Entry m_name; + NT_Entry m_p; + NT_Entry m_i; + NT_Entry m_d; + NT_Entry m_setpoint; + + DataSource m_pData; + DataSource m_iData; + DataSource m_dData; + DataSource m_setpointData; + + std::string m_nameValue; +}; +} // namespace glass diff --git a/glass/src/libnt/native/include/glass/networktables/NTSpeedController.h b/glass/src/libnt/native/include/glass/networktables/NTSpeedController.h new file mode 100644 index 0000000000..2792d9e8fe --- /dev/null +++ b/glass/src/libnt/native/include/glass/networktables/NTSpeedController.h @@ -0,0 +1,45 @@ +/*----------------------------------------------------------------------------*/ +/* Copyright (c) 2020 FIRST. All Rights Reserved. */ +/* Open Source Software - may be modified and shared by FRC teams. The code */ +/* must be accompanied by the FIRST BSD license file in the root directory of */ +/* the project. */ +/*----------------------------------------------------------------------------*/ + +#pragma once + +#include + +#include +#include + +#include "glass/DataSource.h" +#include "glass/hardware/SpeedController.h" +#include "glass/networktables/NetworkTablesHelper.h" + +namespace glass { +class NTSpeedControllerModel : public SpeedControllerModel { + public: + static constexpr const char* kType = "Speed Controller"; + + explicit NTSpeedControllerModel(wpi::StringRef path); + NTSpeedControllerModel(NT_Inst instance, wpi::StringRef path); + + const char* GetName() const override { return m_nameValue.c_str(); } + const char* GetSimDevice() const override { return nullptr; } + + DataSource* GetPercentData() override { return &m_valueData; } + void SetPercent(double value) override; + + void Update() override; + bool Exists() override; + bool IsReadOnly() override { return false; } + + private: + NetworkTablesHelper m_nt; + NT_Entry m_value; + NT_Entry m_name; + + DataSource m_valueData; + std::string m_nameValue; +}; +} // namespace glass diff --git a/glass/src/libnt/native/include/glass/networktables/NTSubsystem.h b/glass/src/libnt/native/include/glass/networktables/NTSubsystem.h new file mode 100644 index 0000000000..2922dc5de1 --- /dev/null +++ b/glass/src/libnt/native/include/glass/networktables/NTSubsystem.h @@ -0,0 +1,49 @@ +/*----------------------------------------------------------------------------*/ +/* Copyright (c) 2020 FIRST. All Rights Reserved. */ +/* Open Source Software - may be modified and shared by FRC teams. The code */ +/* must be accompanied by the FIRST BSD license file in the root directory of */ +/* the project. */ +/*----------------------------------------------------------------------------*/ + +#pragma once + +#include + +#include +#include + +#include "glass/DataSource.h" +#include "glass/networktables/NetworkTablesHelper.h" +#include "glass/other/Subsystem.h" + +namespace glass { +class NTSubsystemModel : public SubsystemModel { + public: + static constexpr const char* kType = "Subsystem"; + + explicit NTSubsystemModel(wpi::StringRef path); + NTSubsystemModel(NT_Inst instance, wpi::StringRef path); + + const char* GetName() const override { return m_nameValue.c_str(); } + const char* GetDefaultCommand() const override { + return m_defaultCommandValue.c_str(); + } + const char* GetCurrentCommand() const override { + return m_currentCommandValue.c_str(); + } + + void Update() override; + bool Exists() override; + bool IsReadOnly() override { return true; } + + private: + NetworkTablesHelper m_nt; + NT_Entry m_name; + NT_Entry m_defaultCommand; + NT_Entry m_currentCommand; + + std::string m_nameValue; + std::string m_defaultCommandValue; + std::string m_currentCommandValue; +}; +} // namespace glass