mirror of
https://github.com/wpilibsuite/allwpilib
synced 2026-06-19 00:41:43 +00:00
[sim] Add GUI support for the REV PH (#6704)
This commit is contained in:
@@ -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) {
|
||||
|
||||
@@ -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
|
||||
|
||||
225
simulation/halsim_gui/src/main/native/cpp/PHSimGui.cpp
Normal file
225
simulation/halsim_gui/src/main/native/cpp/PHSimGui.cpp
Normal 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());
|
||||
});
|
||||
}
|
||||
20
simulation/halsim_gui/src/main/native/cpp/PHSimGui.h
Normal file
20
simulation/halsim_gui/src/main/native/cpp/PHSimGui.h
Normal 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
|
||||
@@ -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();
|
||||
|
||||
Reference in New Issue
Block a user