Files
allwpilib/simulation/halsim_gui/src/main/native/cpp/PCMSimGui.cpp

229 lines
6.5 KiB
C++
Raw Normal View History

// 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.
2025-11-07 19:56:21 -05:00
#include "PCMSimGui.hpp"
#include <cstdio>
#include <memory>
#include <vector>
2025-11-07 19:56:21 -05:00
#include "wpi/glass/hardware/Pneumatic.hpp"
#include "wpi/glass/other/DeviceTree.hpp"
#include "wpi/hal/Ports.h"
#include "wpi/hal/Value.h"
#include "wpi/hal/simulation/CTREPCMData.h"
#include "wpi/halsim/gui/HALDataSource.hpp"
#include "wpi/halsim/gui/HALSimGui.hpp"
#include "wpi/halsim/gui/SimDeviceGui.hpp"
using namespace halsimgui;
namespace {
2021-06-05 22:36:39 -07:00
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,
"Compressor Current");
2021-06-05 22:36:39 -07:00
HALSIMGUI_DATASOURCE_BOOLEAN_INDEXED2(CTREPCMSolenoidOutput, "Solenoid");
2025-11-07 20:00:05 -05:00
class CompressorSimModel : public wpi::glass::CompressorModel {
public:
explicit CompressorSimModel(int32_t index)
: m_index{index},
m_running{index},
m_enabled{index},
m_pressureSwitch{index},
m_current{index} {}
void Update() override {}
2021-06-05 22:36:39 -07:00
bool Exists() override { return HALSIM_GetCTREPCMInitialized(m_index); }
2025-11-07 20:00:05 -05:00
wpi::glass::BooleanSource* GetRunningData() override { return &m_running; }
wpi::glass::BooleanSource* GetEnabledData() override { return &m_enabled; }
wpi::glass::BooleanSource* GetPressureSwitchData() override {
return &m_pressureSwitch;
}
2025-11-07 20:00:05 -05:00
wpi::glass::DoubleSource* GetCurrentData() override { return &m_current; }
void SetRunning(bool val) override {
2021-06-05 22:36:39 -07:00
HALSIM_SetCTREPCMCompressorOn(m_index, val);
}
void SetEnabled(bool val) override {
2021-06-05 22:36:39 -07:00
HALSIM_SetCTREPCMClosedLoopEnabled(m_index, val);
}
void SetPressureSwitch(bool val) override {
2021-06-05 22:36:39 -07:00
HALSIM_SetCTREPCMPressureSwitch(m_index, val);
}
void SetCurrent(double val) override {
2021-06-05 22:36:39 -07:00
HALSIM_SetCTREPCMCompressorCurrent(m_index, val);
}
private:
int32_t m_index;
2021-06-05 22:36:39 -07:00
CTREPCMCompressorOnSource m_running;
CTREPCMClosedLoopEnabledSource m_enabled;
CTREPCMPressureSwitchSource m_pressureSwitch;
CTREPCMCompressorCurrentSource m_current;
};
2025-11-07 20:00:05 -05:00
class SolenoidSimModel : public wpi::glass::SolenoidModel {
public:
SolenoidSimModel(int32_t index, int32_t channel)
: m_index{index}, m_channel{channel}, m_output{index, channel} {}
void Update() override {}
2021-06-05 22:36:39 -07:00
bool Exists() override { return HALSIM_GetCTREPCMInitialized(m_index); }
2025-11-07 20:00:05 -05:00
wpi::glass::BooleanSource* GetOutputData() override { return &m_output; }
void SetOutput(bool val) override {
2021-06-05 22:36:39 -07:00
HALSIM_SetCTREPCMSolenoidOutput(m_index, m_channel, val);
}
private:
int32_t m_index;
int32_t m_channel;
2021-06-05 22:36:39 -07:00
CTREPCMSolenoidOutputSource m_output;
};
2025-11-07 20:00:05 -05:00
class PCMSimModel : public wpi::glass::PneumaticControlModel {
public:
explicit PCMSimModel(int32_t index)
: m_index{index},
m_compressor{index},
m_solenoids(HAL_GetNumCTRESolenoidChannels()) {}
void Update() override;
bool Exists() override { return true; }
CompressorSimModel* GetCompressor() override { return &m_compressor; }
void ForEachSolenoid(
2025-11-07 20:00:05 -05:00
wpi::util::function_ref<void(wpi::glass::SolenoidModel& model, int index)> func)
override;
std::string_view GetName() override { return "PCM"; }
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;
};
2025-11-07 20:00:05 -05:00
class PCMsSimModel : public wpi::glass::PneumaticControlsModel {
public:
2021-06-05 22:36:39 -07:00
PCMsSimModel() : m_models(HAL_GetNumCTREPCMModules()) {}
void Update() override;
bool Exists() override { return true; }
void ForEachPneumaticControl(
2025-11-07 20:00:05 -05:00
wpi::util::function_ref<void(wpi::glass::PneumaticControlModel& model, int index)>
func) override;
private:
std::vector<std::unique_ptr<PCMSimModel>> m_models;
};
} // namespace
void PCMSimModel::Update() {
int32_t numChannels = m_solenoids.size();
m_solenoidInitCount = 0;
for (int32_t i = 0; i < numChannels; ++i) {
auto& model = m_solenoids[i];
2021-06-05 22:36:39 -07:00
if (HALSIM_GetCTREPCMInitialized(m_index)) {
if (!model) {
model = std::make_unique<SolenoidSimModel>(m_index, i);
}
++m_solenoidInitCount;
} else {
model.reset();
}
}
}
void PCMSimModel::ForEachSolenoid(
2025-11-07 20:00:05 -05:00
wpi::util::function_ref<void(wpi::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 PCMsSimModel::Update() {
for (int32_t i = 0, iend = static_cast<int32_t>(m_models.size()); i < iend;
++i) {
auto& model = m_models[i];
2021-06-05 22:36:39 -07:00
if (HALSIM_GetCTREPCMInitialized(i)) {
if (!model) {
model = std::make_unique<PCMSimModel>(i);
}
model->Update();
} else {
model.reset();
}
}
}
void PCMsSimModel::ForEachPneumaticControl(
2025-11-07 20:00:05 -05:00
wpi::util::function_ref<void(wpi::glass::PneumaticControlModel& model, int index)>
func) {
2021-06-05 22:36:39 -07:00
int32_t numCTREPCMs = m_models.size();
for (int32_t i = 0; i < numCTREPCMs; ++i) {
if (auto model = m_models[i].get()) {
func(*model, i);
}
}
}
bool PCMSimGui::PCMsAnyInitialized() {
2021-06-05 22:36:39 -07:00
static const int32_t num = HAL_GetNumCTREPCMModules();
for (int32_t i = 0; i < num; ++i) {
2021-06-05 22:36:39 -07:00
if (HALSIM_GetCTREPCMInitialized(i)) {
return true;
}
}
return false;
}
2025-11-07 20:00:05 -05:00
bool PCMSimGui::PCMsAnySolenoids(wpi::glass::PneumaticControlsModel* model) {
bool any = false;
static_cast<PCMsSimModel*>(model)->ForEachPneumaticControl(
2025-11-07 20:00:05 -05:00
[&](wpi::glass::PneumaticControlModel& CTREPCM, int) {
if (static_cast<PCMSimModel*>(&CTREPCM)->GetNumSolenoids() > 0) {
any = true;
}
});
return any;
}
2025-11-07 20:00:05 -05:00
std::unique_ptr<wpi::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(
2025-11-07 20:00:05 -05:00
HALSimGui::halProvider->GetModel("CTREPCMs"), [](wpi::glass::Model* model) {
wpi::glass::DisplayCompressorsDevice(
static_cast<PCMsSimModel*>(model),
HALSimGui::halProvider->AreOutputsEnabled());
});
}