[sim] Add GUI support for the REV PH (#6704)

This commit is contained in:
Wispy
2024-07-15 19:28:05 -05:00
committed by GitHub
parent cd6b70af0e
commit 7d64d4e24c
7 changed files with 375 additions and 68 deletions

View File

@@ -4,7 +4,7 @@
#include "PCMSimGui.h"
#include <glass/hardware/PCM.h>
#include <glass/hardware/Pneumatic.h>
#include <glass/other/DeviceTree.h>
#include <cstdio>
@@ -25,7 +25,8 @@ namespace {
HALSIMGUI_DATASOURCE_BOOLEAN_INDEXED(CTREPCMCompressorOn, "Compressor On");
HALSIMGUI_DATASOURCE_BOOLEAN_INDEXED(CTREPCMClosedLoopEnabled, "Closed Loop");
HALSIMGUI_DATASOURCE_BOOLEAN_INDEXED(CTREPCMPressureSwitch, "Pressure Switch");
HALSIMGUI_DATASOURCE_DOUBLE_INDEXED(CTREPCMCompressorCurrent, "Comp Current");
HALSIMGUI_DATASOURCE_DOUBLE_INDEXED(CTREPCMCompressorCurrent,
"Compressor Current");
HALSIMGUI_DATASOURCE_BOOLEAN_INDEXED2(CTREPCMSolenoidOutput, "Solenoid");
class CompressorSimModel : public glass::CompressorModel {
@@ -90,7 +91,7 @@ class SolenoidSimModel : public glass::SolenoidModel {
CTREPCMSolenoidOutputSource m_output;
};
class PCMSimModel : public glass::PCMModel {
class PCMSimModel : public glass::PneumaticControlModel {
public:
explicit PCMSimModel(int32_t index)
: m_index{index},
@@ -107,6 +108,8 @@ class PCMSimModel : public glass::PCMModel {
wpi::function_ref<void(glass::SolenoidModel& model, int index)> func)
override;
std::string_view GetName() override { return "PCM"; }
int GetNumSolenoids() const { return m_solenoidInitCount; }
private:
@@ -116,7 +119,7 @@ class PCMSimModel : public glass::PCMModel {
int m_solenoidInitCount = 0;
};
class PCMsSimModel : public glass::PCMsModel {
class PCMsSimModel : public glass::PneumaticControlsModel {
public:
PCMsSimModel() : m_models(HAL_GetNumCTREPCMModules()) {}
@@ -124,8 +127,9 @@ class PCMsSimModel : public glass::PCMsModel {
bool Exists() override { return true; }
void ForEachPCM(
wpi::function_ref<void(glass::PCMModel& model, int index)> func) override;
void ForEachPneumaticControl(
wpi::function_ref<void(glass::PneumaticControlModel& model, int index)>
func) override;
private:
std::vector<std::unique_ptr<PCMSimModel>> m_models;
@@ -176,8 +180,9 @@ void PCMsSimModel::Update() {
}
}
void PCMsSimModel::ForEachPCM(
wpi::function_ref<void(glass::PCMModel& model, int index)> func) {
void PCMsSimModel::ForEachPneumaticControl(
wpi::function_ref<void(glass::PneumaticControlModel& model, int index)>
func) {
int32_t numCTREPCMs = m_models.size();
for (int32_t i = 0; i < numCTREPCMs; ++i) {
if (auto model = m_models[i].get()) {
@@ -186,7 +191,7 @@ void PCMsSimModel::ForEachPCM(
}
}
static bool PCMsAnyInitialized() {
bool PCMSimGui::PCMsAnyInitialized() {
static const int32_t num = HAL_GetNumCTREPCMModules();
for (int32_t i = 0; i < num; ++i) {
if (HALSIM_GetCTREPCMInitialized(i)) {
@@ -196,31 +201,25 @@ static bool PCMsAnyInitialized() {
return false;
}
void PCMSimGui::Initialize() {
HALSimGui::halProvider->RegisterModel("CTREPCMs", PCMsAnyInitialized, [] {
return std::make_unique<PCMsSimModel>();
});
HALSimGui::halProvider->RegisterView(
"Solenoids", "CTREPCMs",
[](glass::Model* model) {
bool any = false;
static_cast<PCMsSimModel*>(model)->ForEachPCM(
[&](glass::PCMModel& CTREPCM, int) {
if (static_cast<PCMSimModel*>(&CTREPCM)->GetNumSolenoids() > 0) {
any = true;
}
});
return any;
},
[](glass::Window* win, glass::Model* model) {
win->SetFlags(ImGuiWindowFlags_AlwaysAutoResize);
win->SetDefaultPos(290, 20);
return glass::MakeFunctionView([=] {
glass::DisplayPCMsSolenoids(
static_cast<PCMsSimModel*>(model),
HALSimGui::halProvider->AreOutputsEnabled());
});
bool PCMSimGui::PCMsAnySolenoids(glass::PneumaticControlsModel* model) {
bool any = false;
static_cast<PCMsSimModel*>(model)->ForEachPneumaticControl(
[&](glass::PneumaticControlModel& CTREPCM, int) {
if (static_cast<PCMSimModel*>(&CTREPCM)->GetNumSolenoids() > 0) {
any = true;
}
});
return any;
}
std::unique_ptr<glass::PneumaticControlsModel> PCMSimGui::GetPCMsModel() {
return std::make_unique<PCMsSimModel>();
}
void PCMSimGui::Initialize() {
HALSimGui::halProvider->RegisterModel(
"CTREPCMs", PCMSimGui::PCMsAnyInitialized,
[] { return std::make_unique<PCMsSimModel>(); });
SimDeviceGui::GetDeviceTree().Add(
HALSimGui::halProvider->GetModel("CTREPCMs"), [](glass::Model* model) {

View File

@@ -3,12 +3,18 @@
// the WPILib BSD license file in the root directory of this project.
#pragma once
#include <glass/hardware/Pneumatic.h>
#include <memory>
namespace halsimgui {
class PCMSimGui {
public:
static void Initialize();
static bool PCMsAnyInitialized();
static bool PCMsAnySolenoids(glass::PneumaticControlsModel* model);
static std::unique_ptr<glass::PneumaticControlsModel> GetPCMsModel();
};
} // namespace halsimgui

View File

@@ -0,0 +1,225 @@
// Copyright (c) FIRST and other WPILib contributors.
// Open Source Software; you can modify and/or share it under the terms of
// the WPILib BSD license file in the root directory of this project.
#include "PHSimGui.h"
#include <glass/hardware/Pneumatic.h>
#include <glass/other/DeviceTree.h>
#include <cstdio>
#include <memory>
#include <vector>
#include <hal/Ports.h>
#include <hal/Value.h>
#include <hal/simulation/REVPHData.h>
#include "HALDataSource.h"
#include "HALSimGui.h"
#include "SimDeviceGui.h"
using namespace halsimgui;
namespace {
HALSIMGUI_DATASOURCE_BOOLEAN_INDEXED(REVPHCompressorOn, "Compressor On");
HALSIMGUI_DATASOURCE_BOOLEAN_INDEXED(REVPHPressureSwitch, "Pressure Switch");
HALSIMGUI_DATASOURCE_DOUBLE_INDEXED(REVPHCompressorCurrent,
"Compressor Current");
HALSIMGUI_DATASOURCE_BOOLEAN_INDEXED2(REVPHSolenoidOutput, "Solenoid");
class CompressorSimModel : public glass::CompressorModel {
public:
explicit CompressorSimModel(int32_t index)
: m_index{index},
m_running{index},
m_pressureSwitch{index},
m_current{index} {}
void Update() override {}
bool Exists() override { return HALSIM_GetREVPHInitialized(m_index); }
glass::DataSource* GetRunningData() override { return &m_running; }
glass::DataSource* GetEnabledData() override { return nullptr; }
glass::DataSource* GetPressureSwitchData() override {
return &m_pressureSwitch;
}
glass::DataSource* GetCurrentData() override { return &m_current; }
void SetRunning(bool val) override {
HALSIM_SetREVPHCompressorOn(m_index, val);
}
void SetEnabled(bool val) override {}
void SetPressureSwitch(bool val) override {
HALSIM_SetREVPHPressureSwitch(m_index, val);
}
void SetCurrent(double val) override {
HALSIM_SetREVPHCompressorCurrent(m_index, val);
}
private:
int32_t m_index;
REVPHCompressorOnSource m_running;
REVPHPressureSwitchSource m_pressureSwitch;
REVPHCompressorCurrentSource m_current;
};
class SolenoidSimModel : public glass::SolenoidModel {
public:
SolenoidSimModel(int32_t index, int32_t channel)
: m_index{index}, m_channel{channel}, m_output{index, channel} {}
void Update() override {}
bool Exists() override { return HALSIM_GetREVPHInitialized(m_index); }
glass::DataSource* GetOutputData() override { return &m_output; }
void SetOutput(bool val) override {
HALSIM_SetREVPHSolenoidOutput(m_index, m_channel, val);
}
private:
int32_t m_index;
int32_t m_channel;
REVPHSolenoidOutputSource m_output;
};
class PHSimModel : public glass::PneumaticControlModel {
public:
explicit PHSimModel(int32_t index)
: m_index{index},
m_compressor{index},
m_solenoids(HAL_GetNumREVPHChannels()) {}
void Update() override;
bool Exists() override { return true; }
CompressorSimModel* GetCompressor() override { return &m_compressor; }
void ForEachSolenoid(
wpi::function_ref<void(glass::SolenoidModel& model, int index)> func)
override;
std::string_view GetName() override { return "PH"; }
int GetNumSolenoids() const { return m_solenoidInitCount; }
private:
int32_t m_index;
CompressorSimModel m_compressor;
std::vector<std::unique_ptr<SolenoidSimModel>> m_solenoids;
int m_solenoidInitCount = 0;
};
class PHsSimModel : public glass::PneumaticControlsModel {
public:
PHsSimModel() : m_models(HAL_GetNumREVPHModules()) {}
void Update() override;
bool Exists() override { return true; }
void ForEachPneumaticControl(
wpi::function_ref<void(glass::PneumaticControlModel& model, int index)>
func) override;
private:
std::vector<std::unique_ptr<PHSimModel>> m_models;
};
} // namespace
void PHSimModel::Update() {
int32_t numChannels = m_solenoids.size();
m_solenoidInitCount = 0;
for (int32_t i = 0; i < numChannels; ++i) {
auto& model = m_solenoids[i];
if (HALSIM_GetREVPHInitialized(m_index)) {
if (!model) {
model = std::make_unique<SolenoidSimModel>(m_index, i);
}
++m_solenoidInitCount;
} else {
model.reset();
}
}
}
void PHSimModel::ForEachSolenoid(
wpi::function_ref<void(glass::SolenoidModel& model, int index)> func) {
if (m_solenoidInitCount == 0) {
return;
}
int32_t numSolenoids = m_solenoids.size();
for (int32_t i = 0; i < numSolenoids; ++i) {
if (auto model = m_solenoids[i].get()) {
func(*model, i);
}
}
}
void PHsSimModel::Update() {
for (int32_t i = 0, iend = static_cast<int32_t>(m_models.size()); i < iend;
++i) {
auto& model = m_models[i];
if (HALSIM_GetREVPHInitialized(i)) {
if (!model) {
model = std::make_unique<PHSimModel>(i);
}
model->Update();
} else {
model.reset();
}
}
}
void PHsSimModel::ForEachPneumaticControl(
wpi::function_ref<void(glass::PneumaticControlModel& model, int index)>
func) {
int32_t numREVPHs = m_models.size();
for (int32_t i = 0; i < numREVPHs; ++i) {
if (auto model = m_models[i].get()) {
func(*model, i);
}
}
}
bool PHSimGui::PHsAnyInitialized() {
static const int32_t num = HAL_GetNumREVPHModules();
for (int32_t i = 0; i < num; ++i) {
if (HALSIM_GetREVPHInitialized(i)) {
return true;
}
}
return false;
}
bool PHSimGui::PHsAnySolenoids(glass::PneumaticControlsModel* model) {
bool any = false;
static_cast<PHsSimModel*>(model)->ForEachPneumaticControl(
[&](glass::PneumaticControlModel& REVPH, int) {
if (static_cast<PHSimModel*>(&REVPH)->GetNumSolenoids() > 0) {
any = true;
}
});
return any;
}
std::unique_ptr<glass::PneumaticControlsModel> PHSimGui::GetPHsModel() {
return std::make_unique<PHsSimModel>();
}
void PHSimGui::Initialize() {
HALSimGui::halProvider->RegisterModel(
"REVPHs", PHSimGui::PHsAnyInitialized,
[] { return std::make_unique<PHsSimModel>(); });
SimDeviceGui::GetDeviceTree().Add(
HALSimGui::halProvider->GetModel("REVPHs"), [](glass::Model* model) {
glass::DisplayCompressorsDevice(
static_cast<PHsSimModel*>(model),
HALSimGui::halProvider->AreOutputsEnabled());
});
}

View File

@@ -0,0 +1,20 @@
// Copyright (c) FIRST and other WPILib contributors.
// Open Source Software; you can modify and/or share it under the terms of
// the WPILib BSD license file in the root directory of this project.
#pragma once
#include <glass/hardware/Pneumatic.h>
#include <memory>
namespace halsimgui {
class PHSimGui {
public:
static void Initialize();
static bool PHsAnyInitialized();
static bool PHsAnySolenoids(glass::PneumaticControlsModel* model);
static std::unique_ptr<glass::PneumaticControlsModel> GetPHsModel();
};
} // namespace halsimgui

View File

@@ -4,6 +4,7 @@
#include <glass/Context.h>
#include <glass/Storage.h>
#include <glass/hardware/Pneumatic.h>
#include <glass/other/Plot.h>
#include <cstdio>
@@ -26,6 +27,7 @@
#include "HALSimGuiExt.h"
#include "NetworkTablesSimGui.h"
#include "PCMSimGui.h"
#include "PHSimGui.h"
#include "PWMSimGui.h"
#include "PowerDistributionSimGui.h"
#include "RelaySimGui.h"
@@ -85,9 +87,43 @@ __declspec(dllexport)
PowerDistributionSimGui::Initialize();
PWMSimGui::Initialize();
RelaySimGui::Initialize();
PHSimGui::Initialize();
RoboRioSimGui::Initialize();
TimingGui::Initialize();
HALSimGui::halProvider->RegisterModel(
"AllPneumaticControls",
[] {
return PCMSimGui::PCMsAnyInitialized() || PHSimGui::PHsAnyInitialized();
},
[] {
return std::make_unique<glass::AllPneumaticControlsModel>(
PCMSimGui::GetPCMsModel(), PHSimGui::GetPHsModel());
});
HALSimGui::halProvider->RegisterView(
"Solenoids", "AllPneumaticControls",
[](glass::Model* model) {
auto pneumaticModel =
static_cast<glass::AllPneumaticControlsModel*>(model);
return PCMSimGui::PCMsAnySolenoids(pneumaticModel->pcms.get()) ||
PHSimGui::PHsAnySolenoids(pneumaticModel->phs.get());
},
[](glass::Window* win, glass::Model* model) {
win->SetFlags(ImGuiWindowFlags_AlwaysAutoResize);
win->SetDefaultPos(290, 20);
return glass::MakeFunctionView([=] {
auto pneumaticModel =
static_cast<glass::AllPneumaticControlsModel*>(model);
glass::DisplayPneumaticControlsSolenoids(
pneumaticModel->pcms.get(),
HALSimGui::halProvider->AreOutputsEnabled());
glass::DisplayPneumaticControlsSolenoids(
pneumaticModel->phs.get(),
HALSimGui::halProvider->AreOutputsEnabled());
});
});
HALSimGui::mainMenu.AddMainMenu([] {
if (ImGui::BeginMenu("Hardware")) {
HALSimGui::halProvider->DisplayMenu();