mirror of
https://github.com/wpilibsuite/allwpilib
synced 2026-06-20 00:51:42 +00:00
Update LiveWindow to provide continuous telemetry. (#771)
LiveWindow.updateValues() is now called from IterativeRobotBase on every loop iteration. Telemetry for all WPILib classes is enabled by default; it can be disabled for specific classes using LiveWindow.disableTelemetry(), or all telemetry can be disabled using LiveWindow.disableAllTelemetry(). This necessitated changing the hook methodology into other classes to be more property-based rather than each class providing multiple functions. This had the benefit of reducing boilerplate and increasing consistency. - Remove NamedSendable, add name to Sendable. - Provide SendableBase abstract class. - Deprecate LiveWindow addSensor/addActuator interfaces. - Add LiveWindow support to drive classes. - Add addChild() helper functions to Subsystem. - Fix inheritance hierarchy. Now only sensors inherit from SensorBase. Other devices inherit from some combination of SendableBase, ErrorBase, or nothing.
This commit is contained in:
@@ -9,8 +9,7 @@
|
||||
|
||||
#include <HAL/HAL.h>
|
||||
|
||||
#include "I2C.h"
|
||||
#include "LiveWindow/LiveWindow.h"
|
||||
#include "SmartDashboard/SendableBuilder.h"
|
||||
|
||||
using namespace frc;
|
||||
|
||||
@@ -30,7 +29,7 @@ ADXL345_I2C::ADXL345_I2C(I2C::Port port, Range range, int deviceAddress)
|
||||
|
||||
HAL_Report(HALUsageReporting::kResourceType_ADXL345,
|
||||
HALUsageReporting::kADXL345_I2C, 0);
|
||||
LiveWindow::GetInstance()->AddSensor("ADXL345_I2C", port, this);
|
||||
SetName("ADXL345_I2C", port);
|
||||
}
|
||||
|
||||
void ADXL345_I2C::SetRange(Range range) {
|
||||
@@ -75,25 +74,15 @@ ADXL345_I2C::AllAxes ADXL345_I2C::GetAccelerations() {
|
||||
return data;
|
||||
}
|
||||
|
||||
std::string ADXL345_I2C::GetSmartDashboardType() const {
|
||||
return "3AxisAccelerometer";
|
||||
}
|
||||
|
||||
void ADXL345_I2C::InitTable(std::shared_ptr<nt::NetworkTable> subtable) {
|
||||
if (subtable) {
|
||||
m_xEntry = subtable->GetEntry("X");
|
||||
m_yEntry = subtable->GetEntry("Y");
|
||||
m_zEntry = subtable->GetEntry("Z");
|
||||
UpdateTable();
|
||||
} else {
|
||||
m_xEntry = nt::NetworkTableEntry();
|
||||
m_yEntry = nt::NetworkTableEntry();
|
||||
m_zEntry = nt::NetworkTableEntry();
|
||||
}
|
||||
}
|
||||
|
||||
void ADXL345_I2C::UpdateTable() {
|
||||
if (m_xEntry) m_xEntry.SetDouble(GetX());
|
||||
if (m_yEntry) m_yEntry.SetDouble(GetY());
|
||||
if (m_zEntry) m_zEntry.SetDouble(GetZ());
|
||||
void ADXL345_I2C::InitSendable(SendableBuilder& builder) {
|
||||
builder.SetSmartDashboardType("3AxisAccelerometer");
|
||||
auto x = builder.GetEntry("X").GetHandle();
|
||||
auto y = builder.GetEntry("Y").GetHandle();
|
||||
auto z = builder.GetEntry("Z").GetHandle();
|
||||
builder.SetUpdateTable([=]() {
|
||||
auto data = GetAccelerations();
|
||||
nt::NetworkTableEntry(x).SetDouble(data.XAxis);
|
||||
nt::NetworkTableEntry(y).SetDouble(data.YAxis);
|
||||
nt::NetworkTableEntry(z).SetDouble(data.ZAxis);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -9,9 +9,7 @@
|
||||
|
||||
#include <HAL/HAL.h>
|
||||
|
||||
#include "DigitalInput.h"
|
||||
#include "DigitalOutput.h"
|
||||
#include "LiveWindow/LiveWindow.h"
|
||||
#include "SmartDashboard/SendableBuilder.h"
|
||||
|
||||
using namespace frc;
|
||||
|
||||
@@ -40,7 +38,7 @@ ADXL345_SPI::ADXL345_SPI(SPI::Port port, ADXL345_SPI::Range range)
|
||||
HAL_Report(HALUsageReporting::kResourceType_ADXL345,
|
||||
HALUsageReporting::kADXL345_SPI);
|
||||
|
||||
LiveWindow::GetInstance()->AddSensor("ADXL345_SPI", port, this);
|
||||
SetName("ADXL345_SPI", port);
|
||||
}
|
||||
|
||||
void ADXL345_SPI::SetRange(Range range) {
|
||||
@@ -103,25 +101,15 @@ ADXL345_SPI::AllAxes ADXL345_SPI::GetAccelerations() {
|
||||
return data;
|
||||
}
|
||||
|
||||
std::string ADXL345_SPI::GetSmartDashboardType() const {
|
||||
return "3AxisAccelerometer";
|
||||
}
|
||||
|
||||
void ADXL345_SPI::InitTable(std::shared_ptr<nt::NetworkTable> subtable) {
|
||||
if (subtable) {
|
||||
m_xEntry = subtable->GetEntry("X");
|
||||
m_yEntry = subtable->GetEntry("Y");
|
||||
m_zEntry = subtable->GetEntry("Z");
|
||||
UpdateTable();
|
||||
} else {
|
||||
m_xEntry = nt::NetworkTableEntry();
|
||||
m_yEntry = nt::NetworkTableEntry();
|
||||
m_zEntry = nt::NetworkTableEntry();
|
||||
}
|
||||
}
|
||||
|
||||
void ADXL345_SPI::UpdateTable() {
|
||||
if (m_xEntry) m_xEntry.SetDouble(GetX());
|
||||
if (m_yEntry) m_yEntry.SetDouble(GetY());
|
||||
if (m_zEntry) m_zEntry.SetDouble(GetZ());
|
||||
void ADXL345_SPI::InitSendable(SendableBuilder& builder) {
|
||||
builder.SetSmartDashboardType("3AxisAccelerometer");
|
||||
auto x = builder.GetEntry("X").GetHandle();
|
||||
auto y = builder.GetEntry("Y").GetHandle();
|
||||
auto z = builder.GetEntry("Z").GetHandle();
|
||||
builder.SetUpdateTable([=]() {
|
||||
auto data = GetAccelerations();
|
||||
nt::NetworkTableEntry(x).SetDouble(data.XAxis);
|
||||
nt::NetworkTableEntry(y).SetDouble(data.YAxis);
|
||||
nt::NetworkTableEntry(z).SetDouble(data.ZAxis);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -9,29 +9,27 @@
|
||||
|
||||
#include <HAL/HAL.h>
|
||||
|
||||
#include "DigitalInput.h"
|
||||
#include "DigitalOutput.h"
|
||||
#include "DriverStation.h"
|
||||
#include "LiveWindow/LiveWindow.h"
|
||||
#include "SmartDashboard/SendableBuilder.h"
|
||||
|
||||
using namespace frc;
|
||||
|
||||
static int kRegWrite = 0x0A;
|
||||
static int kRegRead = 0x0B;
|
||||
static constexpr int kRegWrite = 0x0A;
|
||||
static constexpr int kRegRead = 0x0B;
|
||||
|
||||
static int kPartIdRegister = 0x02;
|
||||
static int kDataRegister = 0x0E;
|
||||
static int kFilterCtlRegister = 0x2C;
|
||||
static int kPowerCtlRegister = 0x2D;
|
||||
static constexpr int kPartIdRegister = 0x02;
|
||||
static constexpr int kDataRegister = 0x0E;
|
||||
static constexpr int kFilterCtlRegister = 0x2C;
|
||||
static constexpr int kPowerCtlRegister = 0x2D;
|
||||
|
||||
// static int kFilterCtl_Range2G = 0x00;
|
||||
// static int kFilterCtl_Range4G = 0x40;
|
||||
// static int kFilterCtl_Range8G = 0x80;
|
||||
static int kFilterCtl_ODR_100Hz = 0x03;
|
||||
// static constexpr int kFilterCtl_Range2G = 0x00;
|
||||
// static constexpr int kFilterCtl_Range4G = 0x40;
|
||||
// static constexpr int kFilterCtl_Range8G = 0x80;
|
||||
static constexpr int kFilterCtl_ODR_100Hz = 0x03;
|
||||
|
||||
static int kPowerCtl_UltraLowNoise = 0x20;
|
||||
// static int kPowerCtl_AutoSleep = 0x04;
|
||||
static int kPowerCtl_Measure = 0x02;
|
||||
static constexpr int kPowerCtl_UltraLowNoise = 0x20;
|
||||
// static constexpr int kPowerCtl_AutoSleep = 0x04;
|
||||
static constexpr int kPowerCtl_Measure = 0x02;
|
||||
|
||||
/**
|
||||
* Constructor. Uses the onboard CS1.
|
||||
@@ -75,7 +73,7 @@ ADXL362::ADXL362(SPI::Port port, Range range) : m_spi(port) {
|
||||
|
||||
HAL_Report(HALUsageReporting::kResourceType_ADXL362, port);
|
||||
|
||||
LiveWindow::GetInstance()->AddSensor("ADXL362", port, this);
|
||||
SetName("ADXL362", port);
|
||||
}
|
||||
|
||||
void ADXL362::SetRange(Range range) {
|
||||
@@ -163,25 +161,15 @@ ADXL362::AllAxes ADXL362::GetAccelerations() {
|
||||
return data;
|
||||
}
|
||||
|
||||
std::string ADXL362::GetSmartDashboardType() const {
|
||||
return "3AxisAccelerometer";
|
||||
}
|
||||
|
||||
void ADXL362::InitTable(std::shared_ptr<nt::NetworkTable> subtable) {
|
||||
if (subtable) {
|
||||
m_xEntry = subtable->GetEntry("X");
|
||||
m_yEntry = subtable->GetEntry("Y");
|
||||
m_zEntry = subtable->GetEntry("Z");
|
||||
UpdateTable();
|
||||
} else {
|
||||
m_xEntry = nt::NetworkTableEntry();
|
||||
m_yEntry = nt::NetworkTableEntry();
|
||||
m_zEntry = nt::NetworkTableEntry();
|
||||
}
|
||||
}
|
||||
|
||||
void ADXL362::UpdateTable() {
|
||||
if (m_xEntry) m_xEntry.SetDouble(GetX());
|
||||
if (m_yEntry) m_yEntry.SetDouble(GetY());
|
||||
if (m_zEntry) m_zEntry.SetDouble(GetZ());
|
||||
void ADXL362::InitSendable(SendableBuilder& builder) {
|
||||
builder.SetSmartDashboardType("3AxisAccelerometer");
|
||||
auto x = builder.GetEntry("X").GetHandle();
|
||||
auto y = builder.GetEntry("Y").GetHandle();
|
||||
auto z = builder.GetEntry("Z").GetHandle();
|
||||
builder.SetUpdateTable([=]() {
|
||||
auto data = GetAccelerations();
|
||||
nt::NetworkTableEntry(x).SetDouble(data.XAxis);
|
||||
nt::NetworkTableEntry(y).SetDouble(data.YAxis);
|
||||
nt::NetworkTableEntry(z).SetDouble(data.ZAxis);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -10,7 +10,6 @@
|
||||
#include <HAL/HAL.h>
|
||||
|
||||
#include "DriverStation.h"
|
||||
#include "LiveWindow/LiveWindow.h"
|
||||
#include "Timer.h"
|
||||
|
||||
using namespace frc;
|
||||
@@ -81,7 +80,7 @@ ADXRS450_Gyro::ADXRS450_Gyro(SPI::Port port) : m_spi(port) {
|
||||
Calibrate();
|
||||
|
||||
HAL_Report(HALUsageReporting::kResourceType_ADXRS450, port);
|
||||
LiveWindow::GetInstance()->AddSensor("ADXRS450_Gyro", port, this);
|
||||
SetName("ADXRS450_Gyro", port);
|
||||
}
|
||||
|
||||
static bool CalcParity(int v) {
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
|
||||
#include <HAL/HAL.h>
|
||||
|
||||
#include "LiveWindow/LiveWindow.h"
|
||||
#include "SmartDashboard/SendableBuilder.h"
|
||||
#include "WPIErrors.h"
|
||||
|
||||
using namespace frc;
|
||||
@@ -20,8 +20,7 @@ using namespace frc;
|
||||
void AnalogAccelerometer::InitAccelerometer() {
|
||||
HAL_Report(HALUsageReporting::kResourceType_Accelerometer,
|
||||
m_analogInput->GetChannel());
|
||||
LiveWindow::GetInstance()->AddSensor("Accelerometer",
|
||||
m_analogInput->GetChannel(), this);
|
||||
SetName("Accelerometer", m_analogInput->GetChannel());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -32,9 +31,9 @@ void AnalogAccelerometer::InitAccelerometer() {
|
||||
* @param channel The channel number for the analog input the accelerometer is
|
||||
* connected to
|
||||
*/
|
||||
AnalogAccelerometer::AnalogAccelerometer(int channel) {
|
||||
m_analogInput = std::make_shared<AnalogInput>(channel);
|
||||
InitAccelerometer();
|
||||
AnalogAccelerometer::AnalogAccelerometer(int channel)
|
||||
: AnalogAccelerometer(std::make_shared<AnalogInput>(channel)) {
|
||||
AddChild(m_analogInput);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -116,24 +115,8 @@ void AnalogAccelerometer::SetZero(double zero) { m_zeroGVoltage = zero; }
|
||||
*/
|
||||
double AnalogAccelerometer::PIDGet() { return GetAcceleration(); }
|
||||
|
||||
void AnalogAccelerometer::UpdateTable() {
|
||||
if (m_valueEntry) m_valueEntry.SetDouble(GetAcceleration());
|
||||
}
|
||||
|
||||
void AnalogAccelerometer::StartLiveWindowMode() {}
|
||||
|
||||
void AnalogAccelerometer::StopLiveWindowMode() {}
|
||||
|
||||
std::string AnalogAccelerometer::GetSmartDashboardType() const {
|
||||
return "Accelerometer";
|
||||
}
|
||||
|
||||
void AnalogAccelerometer::InitTable(
|
||||
std::shared_ptr<nt::NetworkTable> subTable) {
|
||||
if (subTable) {
|
||||
m_valueEntry = subTable->GetEntry("Value");
|
||||
UpdateTable();
|
||||
} else {
|
||||
m_valueEntry = nt::NetworkTableEntry();
|
||||
}
|
||||
void AnalogAccelerometer::InitSendable(SendableBuilder& builder) {
|
||||
builder.SetSmartDashboardType("Accelerometer");
|
||||
builder.AddDoubleProperty("Value", [=]() { return GetAcceleration(); },
|
||||
nullptr);
|
||||
}
|
||||
|
||||
@@ -14,7 +14,6 @@
|
||||
#include <HAL/HAL.h>
|
||||
|
||||
#include "AnalogInput.h"
|
||||
#include "LiveWindow/LiveWindow.h"
|
||||
#include "Timer.h"
|
||||
#include "WPIErrors.h"
|
||||
|
||||
@@ -27,7 +26,9 @@ using namespace frc;
|
||||
* be used on on-board Analog Inputs 0-1.
|
||||
*/
|
||||
AnalogGyro::AnalogGyro(int channel)
|
||||
: AnalogGyro(std::make_shared<AnalogInput>(channel)) {}
|
||||
: AnalogGyro(std::make_shared<AnalogInput>(channel)) {
|
||||
AddChild(m_analog);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gyro constructor with a precreated AnalogInput object.
|
||||
@@ -75,18 +76,9 @@ AnalogGyro::AnalogGyro(std::shared_ptr<AnalogInput> channel)
|
||||
* value.
|
||||
* @param offset Preset uncalibrated value to use as the gyro offset.
|
||||
*/
|
||||
AnalogGyro::AnalogGyro(int channel, int center, double offset) {
|
||||
m_analog = std::make_shared<AnalogInput>(channel);
|
||||
InitGyro();
|
||||
int32_t status = 0;
|
||||
HAL_SetAnalogGyroParameters(m_gyroHandle, kDefaultVoltsPerDegreePerSecond,
|
||||
offset, center, &status);
|
||||
if (status != 0) {
|
||||
wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
|
||||
m_gyroHandle = HAL_kInvalidHandle;
|
||||
return;
|
||||
}
|
||||
Reset();
|
||||
AnalogGyro::AnalogGyro(int channel, int center, double offset)
|
||||
: AnalogGyro(std::make_shared<AnalogInput>(channel), center, offset) {
|
||||
AddChild(m_analog);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -172,8 +164,7 @@ void AnalogGyro::InitGyro() {
|
||||
}
|
||||
|
||||
HAL_Report(HALUsageReporting::kResourceType_Gyro, m_analog->GetChannel());
|
||||
LiveWindow::GetInstance()->AddSensor("AnalogGyro", m_analog->GetChannel(),
|
||||
this);
|
||||
SetName("AnalogGyro", m_analog->GetChannel());
|
||||
}
|
||||
|
||||
void AnalogGyro::Calibrate() {
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
#include <llvm/SmallString.h>
|
||||
#include <llvm/raw_ostream.h>
|
||||
|
||||
#include "LiveWindow/LiveWindow.h"
|
||||
#include "SmartDashboard/SendableBuilder.h"
|
||||
#include "Timer.h"
|
||||
#include "WPIErrors.h"
|
||||
|
||||
@@ -49,8 +49,8 @@ AnalogInput::AnalogInput(int channel) {
|
||||
return;
|
||||
}
|
||||
|
||||
LiveWindow::GetInstance()->AddSensor("AnalogInput", channel, this);
|
||||
HAL_Report(HALUsageReporting::kResourceType_AnalogChannel, channel);
|
||||
SetName("AnalogInput", channel);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -414,23 +414,8 @@ double AnalogInput::PIDGet() {
|
||||
return GetAverageVoltage();
|
||||
}
|
||||
|
||||
void AnalogInput::UpdateTable() {
|
||||
if (m_valueEntry) m_valueEntry.SetDouble(GetAverageVoltage());
|
||||
}
|
||||
|
||||
void AnalogInput::StartLiveWindowMode() {}
|
||||
|
||||
void AnalogInput::StopLiveWindowMode() {}
|
||||
|
||||
std::string AnalogInput::GetSmartDashboardType() const {
|
||||
return "Analog Input";
|
||||
}
|
||||
|
||||
void AnalogInput::InitTable(std::shared_ptr<nt::NetworkTable> subTable) {
|
||||
if (subTable) {
|
||||
m_valueEntry = subTable->GetEntry("Value");
|
||||
UpdateTable();
|
||||
} else {
|
||||
m_valueEntry = nt::NetworkTableEntry();
|
||||
}
|
||||
void AnalogInput::InitSendable(SendableBuilder& builder) {
|
||||
builder.SetSmartDashboardType("Analog Input");
|
||||
builder.AddDoubleProperty("Value", [=]() { return GetAverageVoltage(); },
|
||||
nullptr);
|
||||
}
|
||||
|
||||
@@ -14,7 +14,8 @@
|
||||
#include <llvm/SmallString.h>
|
||||
#include <llvm/raw_ostream.h>
|
||||
|
||||
#include "LiveWindow/LiveWindow.h"
|
||||
#include "SensorBase.h"
|
||||
#include "SmartDashboard/SendableBuilder.h"
|
||||
#include "WPIErrors.h"
|
||||
|
||||
using namespace frc;
|
||||
@@ -51,8 +52,8 @@ AnalogOutput::AnalogOutput(int channel) {
|
||||
return;
|
||||
}
|
||||
|
||||
LiveWindow::GetInstance()->AddActuator("AnalogOutput", m_channel, this);
|
||||
HAL_Report(HALUsageReporting::kResourceType_AnalogOutput, m_channel);
|
||||
SetName("AnalogOutput", m_channel);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -93,23 +94,8 @@ double AnalogOutput::GetVoltage() const {
|
||||
return voltage;
|
||||
}
|
||||
|
||||
void AnalogOutput::UpdateTable() {
|
||||
if (m_valueEntry) m_valueEntry.SetDouble(GetVoltage());
|
||||
}
|
||||
|
||||
void AnalogOutput::StartLiveWindowMode() {}
|
||||
|
||||
void AnalogOutput::StopLiveWindowMode() {}
|
||||
|
||||
std::string AnalogOutput::GetSmartDashboardType() const {
|
||||
return "Analog Output";
|
||||
}
|
||||
|
||||
void AnalogOutput::InitTable(std::shared_ptr<nt::NetworkTable> subTable) {
|
||||
if (subTable) {
|
||||
m_valueEntry = subTable->GetEntry("Value");
|
||||
UpdateTable();
|
||||
} else {
|
||||
m_valueEntry = nt::NetworkTableEntry();
|
||||
}
|
||||
void AnalogOutput::InitSendable(SendableBuilder& builder) {
|
||||
builder.SetSmartDashboardType("Analog Output");
|
||||
builder.AddDoubleProperty("Value", [=]() { return GetVoltage(); },
|
||||
[=](double value) { SetVoltage(value); });
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
#include "AnalogPotentiometer.h"
|
||||
|
||||
#include "ControllerPower.h"
|
||||
#include "SmartDashboard/SendableBuilder.h"
|
||||
|
||||
using namespace frc;
|
||||
|
||||
@@ -23,9 +24,11 @@ using namespace frc;
|
||||
*/
|
||||
AnalogPotentiometer::AnalogPotentiometer(int channel, double fullRange,
|
||||
double offset)
|
||||
: m_analog_input(std::make_unique<AnalogInput>(channel)),
|
||||
: m_analog_input(std::make_shared<AnalogInput>(channel)),
|
||||
m_fullRange(fullRange),
|
||||
m_offset(offset) {}
|
||||
m_offset(offset) {
|
||||
AddChild(m_analog_input);
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct an Analog Potentiometer object from an existing Analog Input
|
||||
@@ -76,26 +79,9 @@ double AnalogPotentiometer::Get() const {
|
||||
*/
|
||||
double AnalogPotentiometer::PIDGet() { return Get(); }
|
||||
|
||||
/**
|
||||
* @return the Smart Dashboard Type
|
||||
*/
|
||||
std::string AnalogPotentiometer::GetSmartDashboardType() const {
|
||||
return "Analog Input";
|
||||
}
|
||||
|
||||
/**
|
||||
* Live Window code, only does anything if live window is activated.
|
||||
*/
|
||||
void AnalogPotentiometer::InitTable(
|
||||
std::shared_ptr<nt::NetworkTable> subtable) {
|
||||
if (subtable) {
|
||||
m_valueEntry = subtable->GetEntry("Value");
|
||||
UpdateTable();
|
||||
} else {
|
||||
m_valueEntry = nt::NetworkTableEntry();
|
||||
}
|
||||
}
|
||||
|
||||
void AnalogPotentiometer::UpdateTable() {
|
||||
if (m_valueEntry) m_valueEntry.SetDouble(Get());
|
||||
void AnalogPotentiometer::InitSendable(SendableBuilder& builder) {
|
||||
m_analog_input->InitSendable(builder);
|
||||
}
|
||||
|
||||
@@ -25,6 +25,7 @@ using namespace frc;
|
||||
AnalogTrigger::AnalogTrigger(int channel)
|
||||
: AnalogTrigger(new AnalogInput(channel)) {
|
||||
m_ownsAnalog = true;
|
||||
AddChild(m_analogInput);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -49,6 +50,7 @@ AnalogTrigger::AnalogTrigger(AnalogInput* input) {
|
||||
m_index = index;
|
||||
|
||||
HAL_Report(HALUsageReporting::kResourceType_AnalogTrigger, input->m_channel);
|
||||
SetName("AnalogTrigger", input->GetChannel());
|
||||
}
|
||||
|
||||
AnalogTrigger::~AnalogTrigger() {
|
||||
@@ -184,3 +186,7 @@ std::shared_ptr<AnalogTriggerOutput> AnalogTrigger::CreateOutput(
|
||||
return std::shared_ptr<AnalogTriggerOutput>(
|
||||
new AnalogTriggerOutput(*this, type), NullDeleter<AnalogTriggerOutput>());
|
||||
}
|
||||
|
||||
void AnalogTrigger::InitSendable(SendableBuilder& builder) {
|
||||
if (m_ownsAnalog) m_analogInput->InitSendable(builder);
|
||||
}
|
||||
|
||||
@@ -78,3 +78,5 @@ AnalogTriggerType AnalogTriggerOutput::GetAnalogTriggerTypeForRouting() const {
|
||||
* @return The channel of the source.
|
||||
*/
|
||||
int AnalogTriggerOutput::GetChannel() const { return m_trigger.m_index; }
|
||||
|
||||
void AnalogTriggerOutput::InitSendable(SendableBuilder&) {}
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
#include <HAL/Accelerometer.h>
|
||||
#include <HAL/HAL.h>
|
||||
|
||||
#include "LiveWindow/LiveWindow.h"
|
||||
#include "SmartDashboard/SendableBuilder.h"
|
||||
#include "WPIErrors.h"
|
||||
|
||||
using namespace frc;
|
||||
@@ -25,7 +25,7 @@ BuiltInAccelerometer::BuiltInAccelerometer(Range range) {
|
||||
|
||||
HAL_Report(HALUsageReporting::kResourceType_Accelerometer, 0, 0,
|
||||
"Built-in accelerometer");
|
||||
LiveWindow::GetInstance()->AddSensor((std::string) "BuiltInAccel", 0, this);
|
||||
SetName("BuiltInAccel", 0);
|
||||
}
|
||||
|
||||
void BuiltInAccelerometer::SetRange(Range range) {
|
||||
@@ -54,26 +54,9 @@ double BuiltInAccelerometer::GetY() { return HAL_GetAccelerometerY(); }
|
||||
*/
|
||||
double BuiltInAccelerometer::GetZ() { return HAL_GetAccelerometerZ(); }
|
||||
|
||||
std::string BuiltInAccelerometer::GetSmartDashboardType() const {
|
||||
return "3AxisAccelerometer";
|
||||
}
|
||||
|
||||
void BuiltInAccelerometer::InitTable(
|
||||
std::shared_ptr<nt::NetworkTable> subtable) {
|
||||
if (subtable != nullptr) {
|
||||
m_xEntry = subtable->GetEntry("X");
|
||||
m_yEntry = subtable->GetEntry("Y");
|
||||
m_zEntry = subtable->GetEntry("Z");
|
||||
UpdateTable();
|
||||
} else {
|
||||
m_xEntry = nt::NetworkTableEntry();
|
||||
m_yEntry = nt::NetworkTableEntry();
|
||||
m_zEntry = nt::NetworkTableEntry();
|
||||
}
|
||||
}
|
||||
|
||||
void BuiltInAccelerometer::UpdateTable() {
|
||||
if (m_xEntry) m_xEntry.SetDouble(GetX());
|
||||
if (m_yEntry) m_yEntry.SetDouble(GetY());
|
||||
if (m_zEntry) m_zEntry.SetDouble(GetZ());
|
||||
void BuiltInAccelerometer::InitSendable(SendableBuilder& builder) {
|
||||
builder.SetSmartDashboardType("3AxisAccelerometer");
|
||||
builder.AddDoubleProperty("X", [=]() { return GetX(); }, nullptr);
|
||||
builder.AddDoubleProperty("Y", [=]() { return GetY(); }, nullptr);
|
||||
builder.AddDoubleProperty("Z", [=]() { return GetZ(); }, nullptr);
|
||||
}
|
||||
|
||||
@@ -11,12 +11,11 @@
|
||||
#include "Buttons/PressedButtonScheduler.h"
|
||||
#include "Buttons/ReleasedButtonScheduler.h"
|
||||
#include "Buttons/ToggleButtonScheduler.h"
|
||||
#include "SmartDashboard/SendableBuilder.h"
|
||||
|
||||
using namespace frc;
|
||||
|
||||
bool Trigger::Grab() {
|
||||
return Get() || (m_pressedEntry && m_pressedEntry.GetBoolean(false));
|
||||
}
|
||||
bool Trigger::Grab() { return Get() || m_sendablePressed; }
|
||||
|
||||
void Trigger::WhenActive(Command* command) {
|
||||
auto pbs = new PressedButtonScheduler(Grab(), this, command);
|
||||
@@ -43,13 +42,9 @@ void Trigger::ToggleWhenActive(Command* command) {
|
||||
tbs->Start();
|
||||
}
|
||||
|
||||
std::string Trigger::GetSmartDashboardType() const { return "Button"; }
|
||||
|
||||
void Trigger::InitTable(std::shared_ptr<nt::NetworkTable> subtable) {
|
||||
if (subtable) {
|
||||
m_pressedEntry = subtable->GetEntry("pressed");
|
||||
m_pressedEntry.SetBoolean(Get());
|
||||
} else {
|
||||
m_pressedEntry = nt::NetworkTableEntry();
|
||||
}
|
||||
void Trigger::InitSendable(SendableBuilder& builder) {
|
||||
builder.SetSmartDashboardType("Button");
|
||||
builder.SetSafeState([=]() { m_sendablePressed = false; });
|
||||
builder.AddBooleanProperty("pressed", [=]() { return Grab(); },
|
||||
[=](bool value) { m_sendablePressed = value; });
|
||||
}
|
||||
|
||||
@@ -11,16 +11,14 @@
|
||||
|
||||
#include "Commands/CommandGroup.h"
|
||||
#include "Commands/Scheduler.h"
|
||||
#include "LiveWindow/LiveWindow.h"
|
||||
#include "RobotState.h"
|
||||
#include "SmartDashboard/SendableBuilder.h"
|
||||
#include "Timer.h"
|
||||
#include "WPIErrors.h"
|
||||
|
||||
using namespace frc;
|
||||
|
||||
static const std::string kName = ".name";
|
||||
static const std::string kRunning = "running";
|
||||
static const std::string kIsParented = ".isParented";
|
||||
|
||||
int Command::m_commandCounter = 0;
|
||||
|
||||
/**
|
||||
@@ -35,7 +33,7 @@ Command::Command() : Command("", -1.0) {}
|
||||
*
|
||||
* @param name the name for this command
|
||||
*/
|
||||
Command::Command(const std::string& name) : Command(name, -1.0) {}
|
||||
Command::Command(const llvm::Twine& name) : Command(name, -1.0) {}
|
||||
|
||||
/**
|
||||
* Creates a new command with the given timeout and a default name.
|
||||
@@ -52,7 +50,8 @@ Command::Command(double timeout) : Command("", timeout) {}
|
||||
* @param timeout the time (in seconds) before this command "times out"
|
||||
* @see IsTimedOut()
|
||||
*/
|
||||
Command::Command(const std::string& name, double timeout) {
|
||||
Command::Command(const llvm::Twine& name, double timeout)
|
||||
: SendableBase(false) {
|
||||
// We use -1.0 to indicate no timeout.
|
||||
if (timeout < 0.0 && timeout != -1.0)
|
||||
wpi_setWPIErrorWithContext(ParameterOutOfRange, "timeout < 0.0");
|
||||
@@ -60,17 +59,14 @@ Command::Command(const std::string& name, double timeout) {
|
||||
m_timeout = timeout;
|
||||
|
||||
// If name contains an empty string
|
||||
if (name.length() == 0) {
|
||||
m_name = std::string("Command_") + std::string(typeid(*this).name());
|
||||
if (name.isTriviallyEmpty() ||
|
||||
(name.isSingleStringRef() && name.getSingleStringRef().empty())) {
|
||||
SetName("Command_" + llvm::Twine(typeid(*this).name()));
|
||||
} else {
|
||||
m_name = name;
|
||||
SetName(name);
|
||||
}
|
||||
}
|
||||
|
||||
Command::~Command() {
|
||||
if (m_runningListener != 0) m_runningEntry.RemoveListener(m_runningListener);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the ID (sequence number) for this command.
|
||||
*
|
||||
@@ -144,7 +140,6 @@ void Command::Removed() {
|
||||
m_initialized = false;
|
||||
m_canceled = false;
|
||||
m_running = false;
|
||||
if (m_runningEntry) m_runningEntry.SetBoolean(false);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -291,10 +286,16 @@ void Command::SetParent(CommandGroup* parent) {
|
||||
} else {
|
||||
LockChanges();
|
||||
m_parent = parent;
|
||||
if (m_isParentedEntry) m_isParentedEntry.SetBoolean(true);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the command has a parent.
|
||||
*
|
||||
* @param True if the command has a parent.
|
||||
*/
|
||||
bool Command::IsParented() const { return m_parent != nullptr; }
|
||||
|
||||
/**
|
||||
* Clears list of subsystem requirements.
|
||||
*
|
||||
@@ -317,7 +318,6 @@ void Command::ClearRequirements() { m_requirements.clear(); }
|
||||
void Command::StartRunning() {
|
||||
m_running = true;
|
||||
m_startTime = -1;
|
||||
if (m_runningEntry) m_runningEntry.SetBoolean(true);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -422,28 +422,17 @@ void Command::SetRunWhenDisabled(bool run) { m_runWhenDisabled = run; }
|
||||
*/
|
||||
bool Command::WillRunWhenDisabled() const { return m_runWhenDisabled; }
|
||||
|
||||
std::string Command::GetName() const { return m_name; }
|
||||
|
||||
std::string Command::GetSmartDashboardType() const { return "Command"; }
|
||||
|
||||
void Command::InitTable(std::shared_ptr<nt::NetworkTable> subtable) {
|
||||
if (m_runningListener != 0) m_runningEntry.RemoveListener(m_runningListener);
|
||||
if (subtable) {
|
||||
subtable->GetEntry(kName).SetString(GetName());
|
||||
m_runningEntry = subtable->GetEntry(kRunning);
|
||||
m_runningEntry.SetBoolean(IsRunning());
|
||||
m_isParentedEntry = subtable->GetEntry(kIsParented);
|
||||
m_isParentedEntry.SetBoolean(m_parent != nullptr);
|
||||
|
||||
m_runningListener = m_runningEntry.AddListener(
|
||||
[=](const nt::EntryNotification& event) {
|
||||
if (!event.value->IsBoolean()) return;
|
||||
if (event.value->GetBoolean()) {
|
||||
if (!IsRunning()) Start();
|
||||
} else {
|
||||
if (IsRunning()) Cancel();
|
||||
}
|
||||
},
|
||||
NT_NOTIFY_NEW | NT_NOTIFY_UPDATE);
|
||||
}
|
||||
void Command::InitSendable(SendableBuilder& builder) {
|
||||
builder.SetSmartDashboardType("Command");
|
||||
builder.AddStringProperty(".name", [=]() { return GetName(); }, nullptr);
|
||||
builder.AddBooleanProperty("running", [=]() { return IsRunning(); },
|
||||
[=](bool value) {
|
||||
if (value) {
|
||||
if (!IsRunning()) Start();
|
||||
} else {
|
||||
if (IsRunning()) Cancel();
|
||||
}
|
||||
});
|
||||
builder.AddBooleanProperty(".isParented", [=]() { return IsParented(); },
|
||||
nullptr);
|
||||
}
|
||||
|
||||
@@ -7,6 +7,8 @@
|
||||
|
||||
#include "Commands/PIDCommand.h"
|
||||
|
||||
#include "SmartDashboard/SendableBuilder.h"
|
||||
|
||||
using namespace frc;
|
||||
|
||||
PIDCommand::PIDCommand(const std::string& name, double p, double i, double d,
|
||||
@@ -65,9 +67,8 @@ double PIDCommand::GetSetpoint() const { return m_controller->GetSetpoint(); }
|
||||
|
||||
double PIDCommand::GetPosition() { return ReturnPIDInput(); }
|
||||
|
||||
std::string PIDCommand::GetSmartDashboardType() const { return "PIDCommand"; }
|
||||
|
||||
void PIDCommand::InitTable(std::shared_ptr<nt::NetworkTable> subtable) {
|
||||
m_controller->InitTable(subtable);
|
||||
Command::InitTable(subtable);
|
||||
void PIDCommand::InitSendable(SendableBuilder& builder) {
|
||||
m_controller->InitSendable(builder);
|
||||
Command::InitSendable(builder);
|
||||
builder.SetSmartDashboardType("PIDCommand");
|
||||
}
|
||||
|
||||
@@ -23,6 +23,7 @@ PIDSubsystem::PIDSubsystem(const std::string& name, double p, double i,
|
||||
double d)
|
||||
: Subsystem(name) {
|
||||
m_controller = std::make_shared<PIDController>(p, i, d, this, this);
|
||||
AddChild("PIDController", m_controller);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -38,6 +39,7 @@ PIDSubsystem::PIDSubsystem(const std::string& name, double p, double i,
|
||||
double d, double f)
|
||||
: Subsystem(name) {
|
||||
m_controller = std::make_shared<PIDController>(p, i, d, f, this, this);
|
||||
AddChild("PIDController", m_controller);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -58,6 +60,7 @@ PIDSubsystem::PIDSubsystem(const std::string& name, double p, double i,
|
||||
: Subsystem(name) {
|
||||
m_controller =
|
||||
std::make_shared<PIDController>(p, i, d, f, this, this, period);
|
||||
AddChild("PIDController", m_controller);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -72,6 +75,7 @@ PIDSubsystem::PIDSubsystem(const std::string& name, double p, double i,
|
||||
PIDSubsystem::PIDSubsystem(double p, double i, double d)
|
||||
: Subsystem("PIDSubsystem") {
|
||||
m_controller = std::make_shared<PIDController>(p, i, d, this, this);
|
||||
AddChild("PIDController", m_controller);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -87,6 +91,7 @@ PIDSubsystem::PIDSubsystem(double p, double i, double d)
|
||||
PIDSubsystem::PIDSubsystem(double p, double i, double d, double f)
|
||||
: Subsystem("PIDSubsystem") {
|
||||
m_controller = std::make_shared<PIDController>(p, i, d, f, this, this);
|
||||
AddChild("PIDController", m_controller);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -106,6 +111,7 @@ PIDSubsystem::PIDSubsystem(double p, double i, double d, double f,
|
||||
: Subsystem("PIDSubsystem") {
|
||||
m_controller =
|
||||
std::make_shared<PIDController>(p, i, d, f, this, this, period);
|
||||
AddChild("PIDController", m_controller);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -233,10 +239,3 @@ double PIDSubsystem::GetRate() { return ReturnPIDInput(); }
|
||||
void PIDSubsystem::PIDWrite(double output) { UsePIDOutput(output); }
|
||||
|
||||
double PIDSubsystem::PIDGet() { return ReturnPIDInput(); }
|
||||
|
||||
std::string PIDSubsystem::GetSmartDashboardType() const { return "PIDCommand"; }
|
||||
|
||||
void PIDSubsystem::InitTable(std::shared_ptr<nt::NetworkTable> subtable) {
|
||||
m_controller->InitTable(subtable);
|
||||
Subsystem::InitTable(subtable);
|
||||
}
|
||||
|
||||
@@ -13,11 +13,15 @@
|
||||
#include "Buttons/ButtonScheduler.h"
|
||||
#include "Commands/Subsystem.h"
|
||||
#include "HLUsageReporting.h"
|
||||
#include "SmartDashboard/SendableBuilder.h"
|
||||
#include "WPIErrors.h"
|
||||
|
||||
using namespace frc;
|
||||
|
||||
Scheduler::Scheduler() { HLUsageReporting::ReportScheduler(); }
|
||||
Scheduler::Scheduler() {
|
||||
HLUsageReporting::ReportScheduler();
|
||||
SetName("Scheduler");
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the Scheduler, creating it if one does not exist.
|
||||
@@ -161,8 +165,6 @@ void Scheduler::Run() {
|
||||
}
|
||||
lock->ConfirmCommand();
|
||||
}
|
||||
|
||||
UpdateTable();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -223,12 +225,12 @@ void Scheduler::ResetAll() {
|
||||
m_cancelEntry = nt::NetworkTableEntry();
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the network tables associated with the Scheduler object on the
|
||||
* SmartDashboard.
|
||||
*/
|
||||
void Scheduler::UpdateTable() {
|
||||
if (m_cancelEntry && m_namesEntry && m_idsEntry) {
|
||||
void Scheduler::InitSendable(SendableBuilder& builder) {
|
||||
builder.SetSmartDashboardType("Scheduler");
|
||||
m_namesEntry = builder.GetEntry("Names");
|
||||
m_idsEntry = builder.GetEntry("Ids");
|
||||
m_cancelEntry = builder.GetEntry("Cancel");
|
||||
builder.SetUpdateTable([=]() {
|
||||
// Get the list of possible commands to cancel
|
||||
auto new_toCancel = m_cancelEntry.GetValue();
|
||||
if (new_toCancel)
|
||||
@@ -264,26 +266,5 @@ void Scheduler::UpdateTable() {
|
||||
m_namesEntry.SetStringArray(commands);
|
||||
m_idsEntry.SetDoubleArray(ids);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::string Scheduler::GetName() const { return "Scheduler"; }
|
||||
|
||||
std::string Scheduler::GetType() const { return "Scheduler"; }
|
||||
|
||||
std::string Scheduler::GetSmartDashboardType() const { return "Scheduler"; }
|
||||
|
||||
void Scheduler::InitTable(std::shared_ptr<nt::NetworkTable> subTable) {
|
||||
if (subTable) {
|
||||
m_namesEntry = subTable->GetEntry("Names");
|
||||
m_idsEntry = subTable->GetEntry("Ids");
|
||||
m_cancelEntry = subTable->GetEntry("Cancel");
|
||||
m_namesEntry.SetStringArray(commands);
|
||||
m_idsEntry.SetDoubleArray(ids);
|
||||
m_cancelEntry.SetDoubleArray(toCancel);
|
||||
} else {
|
||||
m_namesEntry = nt::NetworkTableEntry();
|
||||
m_idsEntry = nt::NetworkTableEntry();
|
||||
m_cancelEntry = nt::NetworkTableEntry();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -9,6 +9,8 @@
|
||||
|
||||
#include "Commands/Command.h"
|
||||
#include "Commands/Scheduler.h"
|
||||
#include "LiveWindow/LiveWindow.h"
|
||||
#include "SmartDashboard/SendableBuilder.h"
|
||||
#include "WPIErrors.h"
|
||||
|
||||
using namespace frc;
|
||||
@@ -18,10 +20,11 @@ using namespace frc;
|
||||
*
|
||||
* @param name the name of the subsystem
|
||||
*/
|
||||
Subsystem::Subsystem(const std::string& name) {
|
||||
m_name = name;
|
||||
Subsystem::Subsystem(const llvm::Twine& name) {
|
||||
SetName(name, name);
|
||||
Scheduler::GetInstance()->RegisterSubsystem(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the default command for this subsystem.
|
||||
*
|
||||
@@ -64,14 +67,6 @@ void Subsystem::SetDefaultCommand(Command* command) {
|
||||
|
||||
m_defaultCommand = command;
|
||||
}
|
||||
if (m_hasDefaultEntry && m_defaultEntry) {
|
||||
if (m_defaultCommand != nullptr) {
|
||||
m_hasDefaultEntry.SetBoolean(true);
|
||||
m_defaultEntry.SetString(m_defaultCommand->GetName());
|
||||
} else {
|
||||
m_hasDefaultEntry.SetBoolean(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -87,6 +82,20 @@ Command* Subsystem::GetDefaultCommand() {
|
||||
return m_defaultCommand;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the default command name, or empty string is there is none.
|
||||
*
|
||||
* @return the default command name
|
||||
*/
|
||||
llvm::StringRef Subsystem::GetDefaultCommandName() {
|
||||
Command* defaultCommand = GetDefaultCommand();
|
||||
if (defaultCommand) {
|
||||
return defaultCommand->GetName();
|
||||
} else {
|
||||
return llvm::StringRef();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the current command.
|
||||
*
|
||||
@@ -104,6 +113,20 @@ void Subsystem::SetCurrentCommand(Command* command) {
|
||||
*/
|
||||
Command* Subsystem::GetCurrentCommand() const { return m_currentCommand; }
|
||||
|
||||
/**
|
||||
* Returns the current command name, or empty string if no current command.
|
||||
*
|
||||
* @return the current command name
|
||||
*/
|
||||
llvm::StringRef Subsystem::GetCurrentCommandName() const {
|
||||
Command* currentCommand = GetCurrentCommand();
|
||||
if (currentCommand) {
|
||||
return currentCommand->GetName();
|
||||
} else {
|
||||
return llvm::StringRef();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* When the run method of the scheduler is called this method will be called.
|
||||
*/
|
||||
@@ -118,41 +141,78 @@ void Subsystem::Periodic() {}
|
||||
* avoid that situation.
|
||||
*/
|
||||
void Subsystem::ConfirmCommand() {
|
||||
if (m_currentCommandChanged) {
|
||||
if (m_hasCommandEntry && m_commandEntry) {
|
||||
if (m_currentCommand != nullptr) {
|
||||
m_hasCommandEntry.SetBoolean(true);
|
||||
m_commandEntry.SetString(m_currentCommand->GetName());
|
||||
} else {
|
||||
m_hasCommandEntry.SetBoolean(false);
|
||||
}
|
||||
}
|
||||
m_currentCommandChanged = false;
|
||||
}
|
||||
if (m_currentCommandChanged) m_currentCommandChanged = false;
|
||||
}
|
||||
|
||||
std::string Subsystem::GetName() const { return m_name; }
|
||||
|
||||
std::string Subsystem::GetSmartDashboardType() const { return "Subsystem"; }
|
||||
|
||||
void Subsystem::InitTable(std::shared_ptr<nt::NetworkTable> subtable) {
|
||||
if (subtable != nullptr) {
|
||||
m_hasDefaultEntry = subtable->GetEntry("hasDefault");
|
||||
m_defaultEntry = subtable->GetEntry("default");
|
||||
m_hasCommandEntry = subtable->GetEntry("hasCommand");
|
||||
m_commandEntry = subtable->GetEntry("command");
|
||||
|
||||
if (m_defaultCommand != nullptr) {
|
||||
m_hasDefaultEntry.SetBoolean(true);
|
||||
m_defaultEntry.SetString(m_defaultCommand->GetName());
|
||||
} else {
|
||||
m_hasDefaultEntry.SetBoolean(false);
|
||||
}
|
||||
if (m_currentCommand != nullptr) {
|
||||
m_hasCommandEntry.SetBoolean(true);
|
||||
m_commandEntry.SetString(m_currentCommand->GetName());
|
||||
} else {
|
||||
m_hasCommandEntry.SetBoolean(false);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Associate a Sendable with this Subsystem.
|
||||
* Also update the child's name.
|
||||
*
|
||||
* @param name name to give child
|
||||
* @param child sendable
|
||||
*/
|
||||
void Subsystem::AddChild(const llvm::Twine& name,
|
||||
std::shared_ptr<Sendable> child) {
|
||||
AddChild(name, *child);
|
||||
}
|
||||
|
||||
/**
|
||||
* Associate a Sendable with this Subsystem.
|
||||
* Also update the child's name.
|
||||
*
|
||||
* @param name name to give child
|
||||
* @param child sendable
|
||||
*/
|
||||
void Subsystem::AddChild(const llvm::Twine& name, Sendable* child) {
|
||||
AddChild(name, *child);
|
||||
}
|
||||
|
||||
/**
|
||||
* Associate a Sendable with this Subsystem.
|
||||
* Also update the child's name.
|
||||
*
|
||||
* @param name name to give child
|
||||
* @param child sendable
|
||||
*/
|
||||
void Subsystem::AddChild(const llvm::Twine& name, Sendable& child) {
|
||||
child.SetName(GetSubsystem(), name);
|
||||
LiveWindow::GetInstance()->Add(&child);
|
||||
}
|
||||
|
||||
/**
|
||||
* Associate a {@link Sendable} with this Subsystem.
|
||||
*
|
||||
* @param child sendable
|
||||
*/
|
||||
void Subsystem::AddChild(std::shared_ptr<Sendable> child) { AddChild(*child); }
|
||||
|
||||
/**
|
||||
* Associate a {@link Sendable} with this Subsystem.
|
||||
*
|
||||
* @param child sendable
|
||||
*/
|
||||
void Subsystem::AddChild(Sendable* child) { AddChild(*child); }
|
||||
|
||||
/**
|
||||
* Associate a {@link Sendable} with this Subsystem.
|
||||
*
|
||||
* @param child sendable
|
||||
*/
|
||||
void Subsystem::AddChild(Sendable& child) {
|
||||
child.SetSubsystem(GetSubsystem());
|
||||
LiveWindow::GetInstance()->Add(&child);
|
||||
}
|
||||
|
||||
void Subsystem::InitSendable(SendableBuilder& builder) {
|
||||
builder.SetSmartDashboardType("Subsystem");
|
||||
|
||||
builder.AddBooleanProperty(
|
||||
"hasDefault", [=]() { return m_defaultCommand != nullptr; }, nullptr);
|
||||
builder.AddStringProperty("default",
|
||||
[=]() { return GetDefaultCommandName(); }, nullptr);
|
||||
|
||||
builder.AddBooleanProperty(
|
||||
"hasCommand", [=]() { return m_currentCommand != nullptr; }, nullptr);
|
||||
builder.AddStringProperty("command",
|
||||
[=]() { return GetCurrentCommandName(); }, nullptr);
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
#include <HAL/Ports.h>
|
||||
#include <HAL/Solenoid.h>
|
||||
|
||||
#include "SmartDashboard/SendableBuilder.h"
|
||||
#include "WPIErrors.h"
|
||||
|
||||
using namespace frc;
|
||||
@@ -32,13 +33,7 @@ Compressor::Compressor(int pcmID) : m_module(pcmID) {
|
||||
SetClosedLoopControl(true);
|
||||
|
||||
HAL_Report(HALUsageReporting::kResourceType_Compressor, pcmID);
|
||||
}
|
||||
|
||||
/**
|
||||
* Destructor.
|
||||
*/
|
||||
Compressor::~Compressor() {
|
||||
if (m_enabledListener != 0) m_enabledEntry.RemoveListener(m_enabledListener);
|
||||
SetName("Compressor", pcmID);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -308,42 +303,15 @@ void Compressor::ClearAllPCMStickyFaults() {
|
||||
}
|
||||
}
|
||||
|
||||
void Compressor::UpdateTable() {
|
||||
if (m_enabledEntry) m_enabledEntry.SetBoolean(Enabled());
|
||||
if (m_pressureSwitchEntry)
|
||||
m_pressureSwitchEntry.SetBoolean(GetPressureSwitchValue());
|
||||
}
|
||||
|
||||
void Compressor::StartLiveWindowMode() {
|
||||
if (m_enabledEntry) {
|
||||
m_enabledListener = m_enabledEntry.AddListener(
|
||||
[=](const nt::EntryNotification& event) {
|
||||
if (!event.value->IsBoolean()) return;
|
||||
if (event.value->GetBoolean())
|
||||
Start();
|
||||
else
|
||||
Stop();
|
||||
},
|
||||
NT_NOTIFY_IMMEDIATE | NT_NOTIFY_NEW | NT_NOTIFY_UPDATE);
|
||||
}
|
||||
}
|
||||
|
||||
void Compressor::StopLiveWindowMode() {
|
||||
if (m_enabledListener != 0) {
|
||||
m_enabledEntry.RemoveListener(m_enabledListener);
|
||||
m_enabledListener = 0;
|
||||
}
|
||||
}
|
||||
|
||||
std::string Compressor::GetSmartDashboardType() const { return "Compressor"; }
|
||||
|
||||
void Compressor::InitTable(std::shared_ptr<nt::NetworkTable> subTable) {
|
||||
if (subTable) {
|
||||
m_enabledEntry = subTable->GetEntry("Enabled");
|
||||
m_pressureSwitchEntry = subTable->GetEntry("Pressure switch");
|
||||
UpdateTable();
|
||||
} else {
|
||||
m_enabledEntry = nt::NetworkTableEntry();
|
||||
m_pressureSwitchEntry = nt::NetworkTableEntry();
|
||||
}
|
||||
void Compressor::InitSendable(SendableBuilder& builder) {
|
||||
builder.SetSmartDashboardType("Compressor");
|
||||
builder.AddBooleanProperty("Enabled", [=]() { return Enabled(); },
|
||||
[=](bool value) {
|
||||
if (value)
|
||||
Start();
|
||||
else
|
||||
Stop();
|
||||
});
|
||||
builder.AddBooleanProperty(
|
||||
"Pressure switch", [=]() { return GetPressureSwitchValue(); }, nullptr);
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
|
||||
#include "AnalogTrigger.h"
|
||||
#include "DigitalInput.h"
|
||||
#include "SmartDashboard/SendableBuilder.h"
|
||||
#include "WPIErrors.h"
|
||||
|
||||
using namespace frc;
|
||||
@@ -36,6 +37,7 @@ Counter::Counter(Mode mode) {
|
||||
SetMaxPeriod(.5);
|
||||
|
||||
HAL_Report(HALUsageReporting::kResourceType_Counter, m_index, mode);
|
||||
SetName("Counter", m_index);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -181,6 +183,7 @@ Counter::~Counter() {
|
||||
void Counter::SetUpSource(int channel) {
|
||||
if (StatusIsFatal()) return;
|
||||
SetUpSource(std::make_shared<DigitalInput>(channel));
|
||||
AddChild(m_upSource);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -287,6 +290,7 @@ void Counter::ClearUpSource() {
|
||||
void Counter::SetDownSource(int channel) {
|
||||
if (StatusIsFatal()) return;
|
||||
SetDownSource(std::make_shared<DigitalInput>(channel));
|
||||
AddChild(m_downSource);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -603,21 +607,7 @@ void Counter::SetReverseDirection(bool reverseDirection) {
|
||||
wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
|
||||
}
|
||||
|
||||
void Counter::UpdateTable() {
|
||||
if (m_valueEntry) m_valueEntry.SetDouble(Get());
|
||||
}
|
||||
|
||||
void Counter::StartLiveWindowMode() {}
|
||||
|
||||
void Counter::StopLiveWindowMode() {}
|
||||
|
||||
std::string Counter::GetSmartDashboardType() const { return "Counter"; }
|
||||
|
||||
void Counter::InitTable(std::shared_ptr<nt::NetworkTable> subTable) {
|
||||
if (subTable) {
|
||||
m_valueEntry = subTable->GetEntry("Value");
|
||||
UpdateTable();
|
||||
} else {
|
||||
m_valueEntry = nt::NetworkTableEntry();
|
||||
}
|
||||
void Counter::InitSendable(SendableBuilder& builder) {
|
||||
builder.SetSmartDashboardType("Counter");
|
||||
builder.AddDoubleProperty("Value", [=]() { return Get(); }, nullptr);
|
||||
}
|
||||
|
||||
@@ -35,6 +35,7 @@ DigitalGlitchFilter::DigitalGlitchFilter() {
|
||||
*index = true;
|
||||
|
||||
HAL_Report(HALUsageReporting::kResourceType_DigitalFilter, m_channelIndex);
|
||||
SetName("DigitalGlitchFilter", m_channelIndex);
|
||||
}
|
||||
|
||||
DigitalGlitchFilter::~DigitalGlitchFilter() {
|
||||
@@ -199,3 +200,5 @@ uint64_t DigitalGlitchFilter::GetPeriodNanoSeconds() {
|
||||
return static_cast<uint64_t>(fpgaCycles) * 1000L /
|
||||
static_cast<uint64_t>(HAL_GetSystemClockTicksPerMicrosecond() / 4);
|
||||
}
|
||||
|
||||
void DigitalGlitchFilter::InitSendable(SendableBuilder&) {}
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
#include <llvm/SmallString.h>
|
||||
#include <llvm/raw_ostream.h>
|
||||
|
||||
#include "LiveWindow/LiveWindow.h"
|
||||
#include "SmartDashboard/SendableBuilder.h"
|
||||
#include "WPIErrors.h"
|
||||
|
||||
using namespace frc;
|
||||
@@ -49,8 +49,8 @@ DigitalInput::DigitalInput(int channel) {
|
||||
return;
|
||||
}
|
||||
|
||||
LiveWindow::GetInstance()->AddSensor("DigitalInput", channel, this);
|
||||
HAL_Report(HALUsageReporting::kResourceType_DigitalInput, channel);
|
||||
SetName("DigitalInput", channel);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -103,23 +103,7 @@ AnalogTriggerType DigitalInput::GetAnalogTriggerTypeForRouting() const {
|
||||
return (AnalogTriggerType)0;
|
||||
}
|
||||
|
||||
void DigitalInput::UpdateTable() {
|
||||
if (m_valueEntry) m_valueEntry.SetBoolean(Get());
|
||||
}
|
||||
|
||||
void DigitalInput::StartLiveWindowMode() {}
|
||||
|
||||
void DigitalInput::StopLiveWindowMode() {}
|
||||
|
||||
std::string DigitalInput::GetSmartDashboardType() const {
|
||||
return "DigitalInput";
|
||||
}
|
||||
|
||||
void DigitalInput::InitTable(std::shared_ptr<nt::NetworkTable> subTable) {
|
||||
if (subTable) {
|
||||
m_valueEntry = subTable->GetEntry("Value");
|
||||
UpdateTable();
|
||||
} else {
|
||||
m_valueEntry = nt::NetworkTableEntry();
|
||||
}
|
||||
void DigitalInput::InitSendable(SendableBuilder& builder) {
|
||||
builder.SetSmartDashboardType("Digital Input");
|
||||
builder.AddBooleanProperty("Value", [=]() { return Get(); }, nullptr);
|
||||
}
|
||||
|
||||
@@ -15,6 +15,8 @@
|
||||
#include <llvm/SmallString.h>
|
||||
#include <llvm/raw_ostream.h>
|
||||
|
||||
#include "SensorBase.h"
|
||||
#include "SmartDashboard/SendableBuilder.h"
|
||||
#include "WPIErrors.h"
|
||||
|
||||
using namespace frc;
|
||||
@@ -32,7 +34,7 @@ DigitalOutput::DigitalOutput(int channel) {
|
||||
llvm::raw_svector_ostream buf(str);
|
||||
|
||||
m_pwmGenerator = HAL_kInvalidHandle;
|
||||
if (!CheckDigitalChannel(channel)) {
|
||||
if (!SensorBase::CheckDigitalChannel(channel)) {
|
||||
buf << "Digital Channel " << channel;
|
||||
wpi_setWPIErrorWithContext(ChannelIndexOutOfRange, buf.str());
|
||||
m_channel = std::numeric_limits<int>::max();
|
||||
@@ -51,13 +53,13 @@ DigitalOutput::DigitalOutput(int channel) {
|
||||
}
|
||||
|
||||
HAL_Report(HALUsageReporting::kResourceType_DigitalOutput, channel);
|
||||
SetName("DigitalOutput", channel);
|
||||
}
|
||||
|
||||
/**
|
||||
* Free the resources associated with a digital output.
|
||||
*/
|
||||
DigitalOutput::~DigitalOutput() {
|
||||
if (m_valueListener != 0) m_valueEntry.RemoveListener(m_valueListener);
|
||||
if (StatusIsFatal()) return;
|
||||
// Disable the PWM in case it was running.
|
||||
DisablePWM();
|
||||
@@ -190,7 +192,8 @@ void DigitalOutput::DisablePWM() {
|
||||
int32_t status = 0;
|
||||
|
||||
// Disable the output by routing to a dead bit.
|
||||
HAL_SetDigitalPWMOutputChannel(m_pwmGenerator, kDigitalChannels, &status);
|
||||
HAL_SetDigitalPWMOutputChannel(m_pwmGenerator, SensorBase::kDigitalChannels,
|
||||
&status);
|
||||
wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
|
||||
|
||||
HAL_FreeDigitalPWM(m_pwmGenerator, &status);
|
||||
@@ -215,52 +218,8 @@ void DigitalOutput::UpdateDutyCycle(double dutyCycle) {
|
||||
wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The HAL Handle to the specified source.
|
||||
*/
|
||||
HAL_Handle DigitalOutput::GetPortHandleForRouting() const { return m_handle; }
|
||||
|
||||
/**
|
||||
* Is source an AnalogTrigger
|
||||
*/
|
||||
bool DigitalOutput::IsAnalogTrigger() const { return false; }
|
||||
|
||||
/**
|
||||
* @return The type of analog trigger output to be used. 0 for Digitals
|
||||
*/
|
||||
AnalogTriggerType DigitalOutput::GetAnalogTriggerTypeForRouting() const {
|
||||
return (AnalogTriggerType)0;
|
||||
}
|
||||
|
||||
void DigitalOutput::UpdateTable() {}
|
||||
|
||||
void DigitalOutput::StartLiveWindowMode() {
|
||||
if (m_valueEntry) {
|
||||
m_valueListener = m_valueEntry.AddListener(
|
||||
[=](const nt::EntryNotification& event) {
|
||||
if (!event.value->IsBoolean()) return;
|
||||
Set(event.value->GetBoolean());
|
||||
},
|
||||
NT_NOTIFY_IMMEDIATE | NT_NOTIFY_NEW | NT_NOTIFY_UPDATE);
|
||||
}
|
||||
}
|
||||
|
||||
void DigitalOutput::StopLiveWindowMode() {
|
||||
if (m_valueListener != 0) {
|
||||
m_valueEntry.RemoveListener(m_valueListener);
|
||||
m_valueListener = 0;
|
||||
}
|
||||
}
|
||||
|
||||
std::string DigitalOutput::GetSmartDashboardType() const {
|
||||
return "Digital Output";
|
||||
}
|
||||
|
||||
void DigitalOutput::InitTable(std::shared_ptr<nt::NetworkTable> subTable) {
|
||||
if (subTable) {
|
||||
m_valueEntry = subTable->GetEntry("Value");
|
||||
UpdateTable();
|
||||
} else {
|
||||
m_valueEntry = nt::NetworkTableEntry();
|
||||
}
|
||||
void DigitalOutput::InitSendable(SendableBuilder& builder) {
|
||||
builder.SetSmartDashboardType("Digital Output");
|
||||
builder.AddBooleanProperty("Value", [=]() { return Get(); },
|
||||
[=](bool value) { Set(value); });
|
||||
}
|
||||
|
||||
@@ -13,7 +13,8 @@
|
||||
#include <llvm/SmallString.h>
|
||||
#include <llvm/raw_ostream.h>
|
||||
|
||||
#include "LiveWindow/LiveWindow.h"
|
||||
#include "SensorBase.h"
|
||||
#include "SmartDashboard/SendableBuilder.h"
|
||||
#include "WPIErrors.h"
|
||||
|
||||
using namespace frc;
|
||||
@@ -27,7 +28,7 @@ using namespace frc;
|
||||
* @param reverseChannel The reverse channel number on the PCM (0..7).
|
||||
*/
|
||||
DoubleSolenoid::DoubleSolenoid(int forwardChannel, int reverseChannel)
|
||||
: DoubleSolenoid(GetDefaultSolenoidModule(), forwardChannel,
|
||||
: DoubleSolenoid(SensorBase::GetDefaultSolenoidModule(), forwardChannel,
|
||||
reverseChannel) {}
|
||||
|
||||
/**
|
||||
@@ -44,17 +45,17 @@ DoubleSolenoid::DoubleSolenoid(int moduleNumber, int forwardChannel,
|
||||
m_reverseChannel(reverseChannel) {
|
||||
llvm::SmallString<32> str;
|
||||
llvm::raw_svector_ostream buf(str);
|
||||
if (!CheckSolenoidModule(m_moduleNumber)) {
|
||||
if (!SensorBase::CheckSolenoidModule(m_moduleNumber)) {
|
||||
buf << "Solenoid Module " << m_moduleNumber;
|
||||
wpi_setWPIErrorWithContext(ModuleIndexOutOfRange, buf.str());
|
||||
return;
|
||||
}
|
||||
if (!CheckSolenoidChannel(m_forwardChannel)) {
|
||||
if (!SensorBase::CheckSolenoidChannel(m_forwardChannel)) {
|
||||
buf << "Solenoid Module " << m_forwardChannel;
|
||||
wpi_setWPIErrorWithContext(ChannelIndexOutOfRange, buf.str());
|
||||
return;
|
||||
}
|
||||
if (!CheckSolenoidChannel(m_reverseChannel)) {
|
||||
if (!SensorBase::CheckSolenoidChannel(m_reverseChannel)) {
|
||||
buf << "Solenoid Module " << m_reverseChannel;
|
||||
wpi_setWPIErrorWithContext(ChannelIndexOutOfRange, buf.str());
|
||||
return;
|
||||
@@ -89,8 +90,7 @@ DoubleSolenoid::DoubleSolenoid(int moduleNumber, int forwardChannel,
|
||||
m_moduleNumber);
|
||||
HAL_Report(HALUsageReporting::kResourceType_Solenoid, m_reverseChannel,
|
||||
m_moduleNumber);
|
||||
LiveWindow::GetInstance()->AddActuator("DoubleSolenoid", m_moduleNumber,
|
||||
m_forwardChannel, this);
|
||||
SetName("DoubleSolenoid", m_moduleNumber, m_forwardChannel);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -99,7 +99,6 @@ DoubleSolenoid::DoubleSolenoid(int moduleNumber, int forwardChannel,
|
||||
DoubleSolenoid::~DoubleSolenoid() {
|
||||
HAL_FreeSolenoidPort(m_forwardHandle);
|
||||
HAL_FreeSolenoidPort(m_reverseHandle);
|
||||
if (m_valueListener != 0) m_valueEntry.RemoveListener(m_valueListener);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -183,56 +182,27 @@ bool DoubleSolenoid::IsRevSolenoidBlackListed() const {
|
||||
return (blackList & m_reverseMask) != 0;
|
||||
}
|
||||
|
||||
void DoubleSolenoid::UpdateTable() {
|
||||
if (m_valueEntry) {
|
||||
switch (Get()) {
|
||||
case kForward:
|
||||
m_valueEntry.SetString("Forward");
|
||||
break;
|
||||
case kReverse:
|
||||
m_valueEntry.SetString("Reverse");
|
||||
break;
|
||||
default:
|
||||
m_valueEntry.SetString("Off");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DoubleSolenoid::StartLiveWindowMode() {
|
||||
Set(kOff);
|
||||
if (m_valueEntry) {
|
||||
m_valueListener = m_valueEntry.AddListener(
|
||||
[=](const nt::EntryNotification& event) {
|
||||
if (!event.value->IsString()) return;
|
||||
Value lvalue = kOff;
|
||||
if (event.value->GetString() == "Forward")
|
||||
lvalue = kForward;
|
||||
else if (event.value->GetString() == "Reverse")
|
||||
lvalue = kReverse;
|
||||
Set(lvalue);
|
||||
},
|
||||
NT_NOTIFY_IMMEDIATE | NT_NOTIFY_NEW | NT_NOTIFY_UPDATE);
|
||||
}
|
||||
}
|
||||
|
||||
void DoubleSolenoid::StopLiveWindowMode() {
|
||||
Set(kOff);
|
||||
if (m_valueListener != 0) {
|
||||
m_valueEntry.RemoveListener(m_valueListener);
|
||||
m_valueListener = 0;
|
||||
}
|
||||
}
|
||||
|
||||
std::string DoubleSolenoid::GetSmartDashboardType() const {
|
||||
return "Double Solenoid";
|
||||
}
|
||||
|
||||
void DoubleSolenoid::InitTable(std::shared_ptr<nt::NetworkTable> subTable) {
|
||||
if (subTable) {
|
||||
m_valueEntry = subTable->GetEntry("Value");
|
||||
UpdateTable();
|
||||
} else {
|
||||
m_valueEntry = nt::NetworkTableEntry();
|
||||
}
|
||||
void DoubleSolenoid::InitSendable(SendableBuilder& builder) {
|
||||
builder.SetSmartDashboardType("Double Solenoid");
|
||||
builder.SetSafeState([=]() { Set(kOff); });
|
||||
builder.AddSmallStringProperty(
|
||||
"Value",
|
||||
[=](llvm::SmallVectorImpl<char>& buf) -> llvm::StringRef {
|
||||
switch (Get()) {
|
||||
case kForward:
|
||||
return "Forward";
|
||||
case kReverse:
|
||||
return "Reverse";
|
||||
default:
|
||||
return "Off";
|
||||
}
|
||||
},
|
||||
[=](llvm::StringRef value) {
|
||||
Value lvalue = kOff;
|
||||
if (value == "Forward")
|
||||
lvalue = kForward;
|
||||
else if (value == "Reverse")
|
||||
lvalue = kReverse;
|
||||
Set(lvalue);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
|
||||
#include <HAL/HAL.h>
|
||||
|
||||
#include "SmartDashboard/SendableBuilder.h"
|
||||
#include "SpeedController.h"
|
||||
|
||||
using namespace frc;
|
||||
@@ -23,7 +24,13 @@ using namespace frc;
|
||||
*/
|
||||
DifferentialDrive::DifferentialDrive(SpeedController& leftMotor,
|
||||
SpeedController& rightMotor)
|
||||
: m_leftMotor(leftMotor), m_rightMotor(rightMotor) {}
|
||||
: m_leftMotor(leftMotor), m_rightMotor(rightMotor) {
|
||||
AddChild(&m_leftMotor);
|
||||
AddChild(&m_rightMotor);
|
||||
static int instances = 0;
|
||||
++instances;
|
||||
SetName("DifferentialDrive", instances);
|
||||
}
|
||||
|
||||
/**
|
||||
* Arcade drive method for differential drive platform.
|
||||
@@ -249,3 +256,13 @@ void DifferentialDrive::StopMotor() {
|
||||
void DifferentialDrive::GetDescription(llvm::raw_ostream& desc) const {
|
||||
desc << "DifferentialDrive";
|
||||
}
|
||||
|
||||
void DifferentialDrive::InitSendable(SendableBuilder& builder) {
|
||||
builder.SetSmartDashboardType("DifferentialDrive");
|
||||
builder.AddDoubleProperty("Left Motor Speed",
|
||||
[=]() { return m_leftMotor.Get(); },
|
||||
[=](double value) { m_leftMotor.Set(value); });
|
||||
builder.AddDoubleProperty("Right Motor Speed",
|
||||
[=]() { return m_rightMotor.Get(); },
|
||||
[=](double value) { m_rightMotor.Set(value); });
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
|
||||
#include <HAL/HAL.h>
|
||||
|
||||
#include "SmartDashboard/SendableBuilder.h"
|
||||
#include "SpeedController.h"
|
||||
|
||||
using namespace frc;
|
||||
@@ -62,6 +63,12 @@ KilloughDrive::KilloughDrive(SpeedController& leftMotor,
|
||||
std::sin(rightMotorAngle * (kPi / 180.0))};
|
||||
m_backVec = {std::cos(backMotorAngle * (kPi / 180.0)),
|
||||
std::sin(backMotorAngle * (kPi / 180.0))};
|
||||
AddChild(&m_leftMotor);
|
||||
AddChild(&m_rightMotor);
|
||||
AddChild(&m_backMotor);
|
||||
static int instances = 0;
|
||||
++instances;
|
||||
SetName("KilloughDrive", instances);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -146,3 +153,16 @@ void KilloughDrive::StopMotor() {
|
||||
void KilloughDrive::GetDescription(llvm::raw_ostream& desc) const {
|
||||
desc << "KilloughDrive";
|
||||
}
|
||||
|
||||
void KilloughDrive::InitSendable(SendableBuilder& builder) {
|
||||
builder.SetSmartDashboardType("KilloughDrive");
|
||||
builder.AddDoubleProperty("Left Motor Speed",
|
||||
[=]() { return m_leftMotor.Get(); },
|
||||
[=](double value) { m_leftMotor.Set(value); });
|
||||
builder.AddDoubleProperty("Right Motor Speed",
|
||||
[=]() { return m_rightMotor.Get(); },
|
||||
[=](double value) { m_rightMotor.Set(value); });
|
||||
builder.AddDoubleProperty("Back Motor Speed",
|
||||
[=]() { return m_backMotor.Get(); },
|
||||
[=](double value) { m_backMotor.Set(value); });
|
||||
}
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
#include <HAL/HAL.h>
|
||||
|
||||
#include "Drive/Vector2d.h"
|
||||
#include "SmartDashboard/SendableBuilder.h"
|
||||
#include "SpeedController.h"
|
||||
|
||||
using namespace frc;
|
||||
@@ -31,7 +32,15 @@ MecanumDrive::MecanumDrive(SpeedController& frontLeftMotor,
|
||||
: m_frontLeftMotor(frontLeftMotor),
|
||||
m_rearLeftMotor(rearLeftMotor),
|
||||
m_frontRightMotor(frontRightMotor),
|
||||
m_rearRightMotor(rearRightMotor) {}
|
||||
m_rearRightMotor(rearRightMotor) {
|
||||
AddChild(&m_frontLeftMotor);
|
||||
AddChild(&m_rearLeftMotor);
|
||||
AddChild(&m_frontRightMotor);
|
||||
AddChild(&m_rearRightMotor);
|
||||
static int instances = 0;
|
||||
++instances;
|
||||
SetName("MecanumDrive", instances);
|
||||
}
|
||||
|
||||
/**
|
||||
* Drive method for Mecanum platform.
|
||||
@@ -118,3 +127,19 @@ void MecanumDrive::StopMotor() {
|
||||
void MecanumDrive::GetDescription(llvm::raw_ostream& desc) const {
|
||||
desc << "MecanumDrive";
|
||||
}
|
||||
|
||||
void MecanumDrive::InitSendable(SendableBuilder& builder) {
|
||||
builder.SetSmartDashboardType("MecanumDrive");
|
||||
builder.AddDoubleProperty("Front Left Motor Speed",
|
||||
[=]() { return m_frontLeftMotor.Get(); },
|
||||
[=](double value) { m_frontLeftMotor.Set(value); });
|
||||
builder.AddDoubleProperty(
|
||||
"Front Right Motor Speed", [=]() { return m_frontRightMotor.Get(); },
|
||||
[=](double value) { m_frontRightMotor.Set(value); });
|
||||
builder.AddDoubleProperty("Rear Left Motor Speed",
|
||||
[=]() { return m_rearLeftMotor.Get(); },
|
||||
[=](double value) { m_rearLeftMotor.Set(value); });
|
||||
builder.AddDoubleProperty("Rear Right Motor Speed",
|
||||
[=]() { return m_rearRightMotor.Get(); },
|
||||
[=](double value) { m_rearRightMotor.Set(value); });
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
#include <HAL/HAL.h>
|
||||
|
||||
#include "DigitalInput.h"
|
||||
#include "LiveWindow/LiveWindow.h"
|
||||
#include "SmartDashboard/SendableBuilder.h"
|
||||
#include "WPIErrors.h"
|
||||
|
||||
using namespace frc;
|
||||
@@ -45,8 +45,7 @@ void Encoder::InitEncoder(bool reverseDirection, EncodingType encodingType) {
|
||||
|
||||
HAL_Report(HALUsageReporting::kResourceType_Encoder, GetFPGAIndex(),
|
||||
encodingType);
|
||||
LiveWindow::GetInstance()->AddSensor("Encoder", m_aSource->GetChannel(),
|
||||
this);
|
||||
SetName("Encoder", m_aSource->GetChannel());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -77,6 +76,8 @@ Encoder::Encoder(int aChannel, int bChannel, bool reverseDirection,
|
||||
m_aSource = std::make_shared<DigitalInput>(aChannel);
|
||||
m_bSource = std::make_shared<DigitalInput>(bChannel);
|
||||
InitEncoder(reverseDirection, encodingType);
|
||||
AddChild(m_aSource);
|
||||
AddChild(m_bSource);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -371,6 +372,19 @@ void Encoder::SetDistancePerPulse(double distancePerPulse) {
|
||||
wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the distance per pulse for this encoder.
|
||||
*
|
||||
* @return The scale factor that will be used to convert pulses to useful units.
|
||||
*/
|
||||
double Encoder::GetDistancePerPulse() const {
|
||||
if (StatusIsFatal()) return 0.0;
|
||||
int32_t status = 0;
|
||||
double distancePerPulse = HAL_GetEncoderDistancePerPulse(m_encoder, &status);
|
||||
wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
|
||||
return distancePerPulse;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the direction sensing for this encoder.
|
||||
*
|
||||
@@ -479,41 +493,18 @@ int Encoder::GetFPGAIndex() const {
|
||||
return val;
|
||||
}
|
||||
|
||||
void Encoder::UpdateTable() {
|
||||
if (m_speedEntry) m_speedEntry.SetDouble(GetRate());
|
||||
if (m_distanceEntry) m_distanceEntry.SetDouble(GetDistance());
|
||||
if (m_distancePerTickEntry) {
|
||||
int32_t status = 0;
|
||||
double distancePerPulse =
|
||||
HAL_GetEncoderDistancePerPulse(m_encoder, &status);
|
||||
wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
|
||||
m_distancePerTickEntry.SetDouble(distancePerPulse);
|
||||
}
|
||||
}
|
||||
|
||||
void Encoder::StartLiveWindowMode() {}
|
||||
|
||||
void Encoder::StopLiveWindowMode() {}
|
||||
|
||||
std::string Encoder::GetSmartDashboardType() const {
|
||||
void Encoder::InitSendable(SendableBuilder& builder) {
|
||||
int32_t status = 0;
|
||||
HAL_EncoderEncodingType type = HAL_GetEncoderEncodingType(m_encoder, &status);
|
||||
wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
|
||||
if (type == HAL_EncoderEncodingType::HAL_Encoder_k4X)
|
||||
return "Quadrature Encoder";
|
||||
builder.SetSmartDashboardType("Quadrature Encoder");
|
||||
else
|
||||
return "Encoder";
|
||||
}
|
||||
builder.SetSmartDashboardType("Encoder");
|
||||
|
||||
void Encoder::InitTable(std::shared_ptr<nt::NetworkTable> subTable) {
|
||||
if (subTable) {
|
||||
m_speedEntry = subTable->GetEntry("Speed");
|
||||
m_distanceEntry = subTable->GetEntry("Distance");
|
||||
m_distancePerTickEntry = subTable->GetEntry("Distance per Tick");
|
||||
UpdateTable();
|
||||
} else {
|
||||
m_speedEntry = nt::NetworkTableEntry();
|
||||
m_distanceEntry = nt::NetworkTableEntry();
|
||||
m_distancePerTickEntry = nt::NetworkTableEntry();
|
||||
}
|
||||
builder.AddDoubleProperty("Speed", [=]() { return GetRate(); }, nullptr);
|
||||
builder.AddDoubleProperty("Distance", [=]() { return GetDistance(); },
|
||||
nullptr);
|
||||
builder.AddDoubleProperty("Distance per Tick",
|
||||
[=]() { return GetDistancePerPulse(); }, nullptr);
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
|
||||
#include "GearTooth.h"
|
||||
|
||||
#include "LiveWindow/LiveWindow.h"
|
||||
#include "SmartDashboard/SendableBuilder.h"
|
||||
|
||||
using namespace frc;
|
||||
|
||||
@@ -32,7 +32,7 @@ void GearTooth::EnableDirectionSensing(bool directionSensitive) {
|
||||
*/
|
||||
GearTooth::GearTooth(int channel, bool directionSensitive) : Counter(channel) {
|
||||
EnableDirectionSensing(directionSensitive);
|
||||
LiveWindow::GetInstance()->AddSensor("GearTooth", channel, this);
|
||||
SetName("GearTooth", channel);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -48,6 +48,7 @@ GearTooth::GearTooth(int channel, bool directionSensitive) : Counter(channel) {
|
||||
GearTooth::GearTooth(DigitalSource* source, bool directionSensitive)
|
||||
: Counter(source) {
|
||||
EnableDirectionSensing(directionSensitive);
|
||||
SetName("GearTooth", source->GetChannel());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -64,6 +65,10 @@ GearTooth::GearTooth(std::shared_ptr<DigitalSource> source,
|
||||
bool directionSensitive)
|
||||
: Counter(source) {
|
||||
EnableDirectionSensing(directionSensitive);
|
||||
SetName("GearTooth", source->GetChannel());
|
||||
}
|
||||
|
||||
std::string GearTooth::GetSmartDashboardType() const { return "GearTooth"; }
|
||||
void GearTooth::InitSendable(SendableBuilder& builder) {
|
||||
Counter::InitSendable(builder);
|
||||
builder.SetSmartDashboardType("Gear Tooth");
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
|
||||
#include "GyroBase.h"
|
||||
|
||||
#include "LiveWindow/LiveWindow.h"
|
||||
#include "SmartDashboard/SendableBuilder.h"
|
||||
#include "WPIErrors.h"
|
||||
|
||||
using namespace frc;
|
||||
@@ -29,21 +29,7 @@ double GyroBase::PIDGet() {
|
||||
}
|
||||
}
|
||||
|
||||
void GyroBase::UpdateTable() {
|
||||
if (m_valueEntry) m_valueEntry.SetDouble(GetAngle());
|
||||
}
|
||||
|
||||
void GyroBase::StartLiveWindowMode() {}
|
||||
|
||||
void GyroBase::StopLiveWindowMode() {}
|
||||
|
||||
std::string GyroBase::GetSmartDashboardType() const { return "Gyro"; }
|
||||
|
||||
void GyroBase::InitTable(std::shared_ptr<nt::NetworkTable> subTable) {
|
||||
if (subTable) {
|
||||
m_valueEntry = subTable->GetEntry("Value");
|
||||
UpdateTable();
|
||||
} else {
|
||||
m_valueEntry = nt::NetworkTableEntry();
|
||||
}
|
||||
void GyroBase::InitSendable(SendableBuilder& builder) {
|
||||
builder.SetSmartDashboardType("Gyro");
|
||||
builder.AddDoubleProperty("Value", [=]() { return GetAngle(); }, nullptr);
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
#include <HAL/HAL.h>
|
||||
#include <llvm/raw_ostream.h>
|
||||
|
||||
#include "Commands/Scheduler.h"
|
||||
#include "LiveWindow/LiveWindow.h"
|
||||
|
||||
using namespace frc;
|
||||
@@ -191,4 +192,5 @@ void IterativeRobotBase::LoopFunc() {
|
||||
TestPeriodic();
|
||||
}
|
||||
RobotPeriodic();
|
||||
LiveWindow::GetInstance()->UpdateValues();
|
||||
}
|
||||
|
||||
@@ -9,8 +9,6 @@
|
||||
|
||||
#include <HAL/HAL.h>
|
||||
|
||||
#include "LiveWindow/LiveWindow.h"
|
||||
|
||||
using namespace frc;
|
||||
|
||||
/**
|
||||
@@ -35,5 +33,5 @@ Jaguar::Jaguar(int channel) : PWMSpeedController(channel) {
|
||||
SetZeroLatch();
|
||||
|
||||
HAL_Report(HALUsageReporting::kResourceType_Jaguar, GetChannel());
|
||||
LiveWindow::GetInstance()->AddActuator("Jaguar", GetChannel(), this);
|
||||
SetName("Jaguar", GetChannel());
|
||||
}
|
||||
|
||||
@@ -9,14 +9,52 @@
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include <llvm/DenseMap.h>
|
||||
#include <llvm/SmallString.h>
|
||||
#include <llvm/raw_ostream.h>
|
||||
#include <support/mutex.h>
|
||||
|
||||
#include "Commands/Scheduler.h"
|
||||
#include "SmartDashboard/SendableBuilderImpl.h"
|
||||
#include "networktables/NetworkTable.h"
|
||||
#include "networktables/NetworkTableEntry.h"
|
||||
#include "networktables/NetworkTableInstance.h"
|
||||
|
||||
using namespace frc;
|
||||
|
||||
using llvm::Twine;
|
||||
|
||||
struct LiveWindow::Impl {
|
||||
Impl();
|
||||
|
||||
struct Component {
|
||||
std::shared_ptr<Sendable> sendable;
|
||||
Sendable* parent = nullptr;
|
||||
SendableBuilderImpl builder;
|
||||
bool firstTime = true;
|
||||
bool telemetryEnabled = true;
|
||||
};
|
||||
|
||||
wpi::mutex mutex;
|
||||
|
||||
llvm::DenseMap<void*, Component> components;
|
||||
|
||||
std::shared_ptr<nt::NetworkTable> liveWindowTable;
|
||||
std::shared_ptr<nt::NetworkTable> statusTable;
|
||||
nt::NetworkTableEntry enabledEntry;
|
||||
|
||||
bool startLiveWindow = false;
|
||||
bool liveWindowEnabled = false;
|
||||
bool telemetryEnabled = true;
|
||||
};
|
||||
|
||||
LiveWindow::Impl::Impl()
|
||||
: liveWindowTable(
|
||||
nt::NetworkTableInstance::GetDefault().GetTable("LiveWindow")) {
|
||||
statusTable = liveWindowTable->GetSubTable(".status");
|
||||
enabledEntry = statusTable->GetEntry("LW Enabled");
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an instance of the LiveWindow main class.
|
||||
*
|
||||
@@ -33,11 +71,11 @@ LiveWindow* LiveWindow::GetInstance() {
|
||||
*
|
||||
* Allocate the necessary tables.
|
||||
*/
|
||||
LiveWindow::LiveWindow() : m_scheduler(Scheduler::GetInstance()) {
|
||||
m_liveWindowTable =
|
||||
nt::NetworkTableInstance::GetDefault().GetTable("LiveWindow");
|
||||
m_statusTable = m_liveWindowTable->GetSubTable(".status");
|
||||
m_enabledEntry = m_statusTable->GetEntry("LW Enabled");
|
||||
LiveWindow::LiveWindow() : m_impl(new Impl) {}
|
||||
|
||||
bool LiveWindow::IsEnabled() const {
|
||||
std::lock_guard<wpi::mutex> lock(m_impl->mutex);
|
||||
return m_impl->liveWindowEnabled;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -46,25 +84,21 @@ LiveWindow::LiveWindow() : m_scheduler(Scheduler::GetInstance()) {
|
||||
* If it changes to enabled, start livewindow running otherwise stop it
|
||||
*/
|
||||
void LiveWindow::SetEnabled(bool enabled) {
|
||||
if (m_enabled == enabled) return;
|
||||
std::lock_guard<wpi::mutex> lock(m_impl->mutex);
|
||||
if (m_impl->liveWindowEnabled == enabled) return;
|
||||
Scheduler* scheduler = Scheduler::GetInstance();
|
||||
if (enabled) {
|
||||
if (m_firstTime) {
|
||||
InitializeLiveWindowComponents();
|
||||
m_firstTime = false;
|
||||
}
|
||||
m_scheduler->SetEnabled(false);
|
||||
m_scheduler->RemoveAll();
|
||||
for (auto& elem : m_components) {
|
||||
elem.first->StartLiveWindowMode();
|
||||
}
|
||||
scheduler->SetEnabled(false);
|
||||
scheduler->RemoveAll();
|
||||
} else {
|
||||
for (auto& elem : m_components) {
|
||||
elem.first->StopLiveWindowMode();
|
||||
for (auto& i : m_impl->components) {
|
||||
i.getSecond().builder.StopLiveWindowMode();
|
||||
}
|
||||
m_scheduler->SetEnabled(true);
|
||||
scheduler->SetEnabled(true);
|
||||
}
|
||||
m_enabled = enabled;
|
||||
m_enabledEntry.SetBoolean(m_enabled);
|
||||
m_impl->startLiveWindow = enabled;
|
||||
m_impl->liveWindowEnabled = enabled;
|
||||
m_impl->enabledEntry.SetBoolean(enabled);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -74,41 +108,38 @@ void LiveWindow::SetEnabled(bool enabled) {
|
||||
*
|
||||
* @param subsystem The subsystem this component is part of.
|
||||
* @param name The name of this component.
|
||||
* @param component A LiveWindowSendable component that represents a sensor.
|
||||
* @param component A Sendable component that represents a sensor.
|
||||
*/
|
||||
//@{
|
||||
/**
|
||||
* @brief Use a STL smart pointer to share ownership of component.
|
||||
* @deprecated Use Sendable::SetName() instead.
|
||||
*/
|
||||
void LiveWindow::AddSensor(const std::string& subsystem,
|
||||
const std::string& name,
|
||||
std::shared_ptr<LiveWindowSendable> component) {
|
||||
m_components[component].subsystem = subsystem;
|
||||
m_components[component].name = name;
|
||||
m_components[component].isSensor = true;
|
||||
void LiveWindow::AddSensor(const llvm::Twine& subsystem,
|
||||
const llvm::Twine& name,
|
||||
std::shared_ptr<Sendable> component) {
|
||||
Add(component);
|
||||
component->SetName(subsystem, name);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Pass a reference to LiveWindow and retain ownership of the component.
|
||||
* @deprecated Use Sendable::SetName() instead.
|
||||
*/
|
||||
void LiveWindow::AddSensor(const std::string& subsystem,
|
||||
const std::string& name,
|
||||
LiveWindowSendable& component) {
|
||||
AddSensor(subsystem, name,
|
||||
std::shared_ptr<LiveWindowSendable>(&component,
|
||||
[](LiveWindowSendable*) {}));
|
||||
void LiveWindow::AddSensor(const llvm::Twine& subsystem,
|
||||
const llvm::Twine& name, Sendable& component) {
|
||||
Add(&component);
|
||||
component.SetName(subsystem, name);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Use a raw pointer to the LiveWindow.
|
||||
* @deprecated Prefer smart pointers or references.
|
||||
* @deprecated Use Sendable::SetName() instead.
|
||||
*/
|
||||
void LiveWindow::AddSensor(const std::string& subsystem,
|
||||
const std::string& name,
|
||||
LiveWindowSendable* component) {
|
||||
AddSensor(subsystem, name,
|
||||
std::shared_ptr<LiveWindowSendable>(
|
||||
component, NullDeleter<LiveWindowSendable>()));
|
||||
void LiveWindow::AddSensor(const llvm::Twine& subsystem,
|
||||
const llvm::Twine& name, Sendable* component) {
|
||||
Add(component);
|
||||
component->SetName(subsystem, name);
|
||||
}
|
||||
//@}
|
||||
|
||||
@@ -116,87 +147,161 @@ void LiveWindow::AddSensor(const std::string& subsystem,
|
||||
* @name AddActuator(subsystem, name, component)
|
||||
*
|
||||
* Add an Actuator associated with the subsystem and call it by the given name.
|
||||
* @deprecated Use Sendable::SetName() instead.
|
||||
*
|
||||
* @param subsystem The subsystem this component is part of.
|
||||
* @param name The name of this component.
|
||||
* @param component A LiveWindowSendable component that represents a actuator.
|
||||
* @param component A Sendable component that represents a actuator.
|
||||
*/
|
||||
//@{
|
||||
/**
|
||||
* @brief Use a STL smart pointer to share ownership of component.
|
||||
*/
|
||||
void LiveWindow::AddActuator(const std::string& subsystem,
|
||||
const std::string& name,
|
||||
std::shared_ptr<LiveWindowSendable> component) {
|
||||
m_components[component].subsystem = subsystem;
|
||||
m_components[component].name = name;
|
||||
m_components[component].isSensor = false;
|
||||
void LiveWindow::AddActuator(const llvm::Twine& subsystem,
|
||||
const llvm::Twine& name,
|
||||
std::shared_ptr<Sendable> component) {
|
||||
Add(component);
|
||||
component->SetName(subsystem, name);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Pass a reference to LiveWindow and retain ownership of the component.
|
||||
* @deprecated Use Sendable::SetName() instead.
|
||||
*/
|
||||
void LiveWindow::AddActuator(const std::string& subsystem,
|
||||
const std::string& name,
|
||||
LiveWindowSendable& component) {
|
||||
AddActuator(subsystem, name,
|
||||
std::shared_ptr<LiveWindowSendable>(&component,
|
||||
[](LiveWindowSendable*) {}));
|
||||
void LiveWindow::AddActuator(const llvm::Twine& subsystem,
|
||||
const llvm::Twine& name, Sendable& component) {
|
||||
Add(&component);
|
||||
component.SetName(subsystem, name);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Use a raw pointer to the LiveWindow.
|
||||
* @deprecated Prefer smart pointers or references.
|
||||
* @deprecated Use Sendable::SetName() instead.
|
||||
*/
|
||||
void LiveWindow::AddActuator(const std::string& subsystem,
|
||||
const std::string& name,
|
||||
LiveWindowSendable* component) {
|
||||
AddActuator(subsystem, name,
|
||||
std::shared_ptr<LiveWindowSendable>(
|
||||
component, NullDeleter<LiveWindowSendable>()));
|
||||
void LiveWindow::AddActuator(const llvm::Twine& subsystem,
|
||||
const llvm::Twine& name, Sendable* component) {
|
||||
Add(component);
|
||||
component->SetName(subsystem, name);
|
||||
}
|
||||
//@}
|
||||
|
||||
/**
|
||||
* Meant for internal use in other WPILib classes.
|
||||
* @deprecated Use SensorBase::SetName() instead.
|
||||
*/
|
||||
void LiveWindow::AddSensor(std::string type, int channel,
|
||||
LiveWindowSendable* component) {
|
||||
llvm::SmallString<128> buf;
|
||||
llvm::raw_svector_ostream oss(buf);
|
||||
oss << type << "[" << channel << "]";
|
||||
AddSensor("Ungrouped", oss.str(), component);
|
||||
std::shared_ptr<LiveWindowSendable> component_stl(
|
||||
component, NullDeleter<LiveWindowSendable>());
|
||||
if (std::find(m_sensors.begin(), m_sensors.end(), component_stl) ==
|
||||
m_sensors.end())
|
||||
m_sensors.push_back(component_stl);
|
||||
void LiveWindow::AddSensor(const llvm::Twine& type, int channel,
|
||||
Sendable* component) {
|
||||
Add(component);
|
||||
component->SetName("Ungrouped",
|
||||
type + Twine('[') + Twine(channel) + Twine(']'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Meant for internal use in other WPILib classes.
|
||||
* @deprecated Use SensorBase::SetName() instead.
|
||||
*/
|
||||
void LiveWindow::AddActuator(std::string type, int channel,
|
||||
LiveWindowSendable* component) {
|
||||
llvm::SmallString<128> buf;
|
||||
llvm::raw_svector_ostream oss(buf);
|
||||
oss << type << "[" << channel << "]";
|
||||
AddActuator("Ungrouped", oss.str(),
|
||||
std::shared_ptr<LiveWindowSendable>(component,
|
||||
[](LiveWindowSendable*) {}));
|
||||
void LiveWindow::AddActuator(const llvm::Twine& type, int channel,
|
||||
Sendable* component) {
|
||||
Add(component);
|
||||
component->SetName("Ungrouped",
|
||||
type + Twine('[') + Twine(channel) + Twine(']'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Meant for internal use in other WPILib classes.
|
||||
* @deprecated Use SensorBase::SetName() instead.
|
||||
*/
|
||||
void LiveWindow::AddActuator(std::string type, int module, int channel,
|
||||
LiveWindowSendable* component) {
|
||||
llvm::SmallString<128> buf;
|
||||
llvm::raw_svector_ostream oss(buf);
|
||||
oss << type << "[" << module << "," << channel << "]";
|
||||
AddActuator("Ungrouped", oss.str(),
|
||||
std::shared_ptr<LiveWindowSendable>(component,
|
||||
[](LiveWindowSendable*) {}));
|
||||
void LiveWindow::AddActuator(const llvm::Twine& type, int module, int channel,
|
||||
Sendable* component) {
|
||||
Add(component);
|
||||
component->SetName("Ungrouped", type + Twine('[') + Twine(module) +
|
||||
Twine(',') + Twine(channel) + Twine(']'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a component to the LiveWindow.
|
||||
*
|
||||
* @param sendable component to add
|
||||
*/
|
||||
void LiveWindow::Add(std::shared_ptr<Sendable> sendable) {
|
||||
std::lock_guard<wpi::mutex> lock(m_impl->mutex);
|
||||
auto& comp = m_impl->components[sendable.get()];
|
||||
comp.sendable = sendable;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a component to the LiveWindow.
|
||||
*
|
||||
* @param sendable component to add
|
||||
*/
|
||||
void LiveWindow::Add(Sendable* sendable) {
|
||||
Add(std::shared_ptr<Sendable>(sendable, NullDeleter<Sendable>()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a child component to a component.
|
||||
*
|
||||
* @param parent parent component
|
||||
* @param child child component
|
||||
*/
|
||||
void LiveWindow::AddChild(Sendable* parent, std::shared_ptr<Sendable> child) {
|
||||
AddChild(parent, child.get());
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a child component to a component.
|
||||
*
|
||||
* @param parent parent component
|
||||
* @param child child component
|
||||
*/
|
||||
void LiveWindow::AddChild(Sendable* parent, void* child) {
|
||||
std::lock_guard<wpi::mutex> lock(m_impl->mutex);
|
||||
auto& comp = m_impl->components[child];
|
||||
comp.parent = parent;
|
||||
comp.telemetryEnabled = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the component from the LiveWindow.
|
||||
*
|
||||
* @param sendable component to remove
|
||||
*/
|
||||
void LiveWindow::Remove(Sendable* sendable) {
|
||||
std::lock_guard<wpi::mutex> lock(m_impl->mutex);
|
||||
m_impl->components.erase(sendable);
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable telemetry for a single component.
|
||||
*
|
||||
* @param sendable component
|
||||
*/
|
||||
void LiveWindow::EnableTelemetry(Sendable* sendable) {
|
||||
std::lock_guard<wpi::mutex> lock(m_impl->mutex);
|
||||
// Re-enable global setting in case DisableAllTelemetry() was called.
|
||||
m_impl->telemetryEnabled = true;
|
||||
auto i = m_impl->components.find(sendable);
|
||||
if (i != m_impl->components.end()) i->getSecond().telemetryEnabled = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Disable telemetry for a single component.
|
||||
*
|
||||
* @param sendable component
|
||||
*/
|
||||
void LiveWindow::DisableTelemetry(Sendable* sendable) {
|
||||
std::lock_guard<wpi::mutex> lock(m_impl->mutex);
|
||||
auto i = m_impl->components.find(sendable);
|
||||
if (i != m_impl->components.end()) i->getSecond().telemetryEnabled = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Disable ALL telemetry.
|
||||
*/
|
||||
void LiveWindow::DisableAllTelemetry() {
|
||||
std::lock_guard<wpi::mutex> lock(m_impl->mutex);
|
||||
m_impl->telemetryEnabled = false;
|
||||
for (auto& i : m_impl->components) i.getSecond().telemetryEnabled = false;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -206,44 +311,41 @@ void LiveWindow::AddActuator(std::string type, int module, int channel,
|
||||
* SmartDashboard widgets.
|
||||
*/
|
||||
void LiveWindow::UpdateValues() {
|
||||
for (auto& elem : m_sensors) {
|
||||
elem->UpdateTable();
|
||||
}
|
||||
}
|
||||
std::lock_guard<wpi::mutex> lock(m_impl->mutex);
|
||||
// Only do this if either LiveWindow mode or telemetry is enabled.
|
||||
if (!m_impl->liveWindowEnabled && !m_impl->telemetryEnabled) return;
|
||||
|
||||
/**
|
||||
* This method is called periodically to cause the sensors to send new values
|
||||
* to the SmartDashboard.
|
||||
*/
|
||||
void LiveWindow::Run() {
|
||||
if (m_enabled) {
|
||||
UpdateValues();
|
||||
}
|
||||
}
|
||||
for (auto& i : m_impl->components) {
|
||||
auto& comp = i.getSecond();
|
||||
if (comp.sendable && !comp.parent &&
|
||||
(m_impl->liveWindowEnabled || comp.telemetryEnabled)) {
|
||||
if (comp.firstTime) {
|
||||
// By holding off creating the NetworkTable entries, it allows the
|
||||
// components to be redefined. This allows default sensor and actuator
|
||||
// values to be created that are replaced with the custom names from
|
||||
// users calling setName.
|
||||
auto name = comp.sendable->GetName();
|
||||
if (name.empty()) continue;
|
||||
auto subsystem = comp.sendable->GetSubsystem();
|
||||
auto ssTable = m_impl->liveWindowTable->GetSubTable(subsystem);
|
||||
std::shared_ptr<NetworkTable> table;
|
||||
// Treat name==subsystem as top level of subsystem
|
||||
if (name == subsystem)
|
||||
table = ssTable;
|
||||
else
|
||||
table = ssTable->GetSubTable(name);
|
||||
table->GetEntry(".name").SetString(name);
|
||||
comp.builder.SetTable(table);
|
||||
comp.sendable->InitSendable(comp.builder);
|
||||
ssTable->GetEntry(".type").SetString("LW Subsystem");
|
||||
|
||||
/**
|
||||
* Initialize all the LiveWindow elements the first time we enter LiveWindow
|
||||
* mode. By holding off creating the NetworkTable entries, it allows them to be
|
||||
* redefined before the first time in LiveWindow mode. This allows default
|
||||
* sensor and actuator values to be created that are replaced with the custom
|
||||
* names from users calling addActuator and addSensor.
|
||||
*/
|
||||
void LiveWindow::InitializeLiveWindowComponents() {
|
||||
for (auto& elem : m_components) {
|
||||
std::shared_ptr<LiveWindowSendable> component = elem.first;
|
||||
LiveWindowComponent c = elem.second;
|
||||
std::string subsystem = c.subsystem;
|
||||
std::string name = c.name;
|
||||
m_liveWindowTable->GetSubTable(subsystem)->GetEntry(".type").SetString(
|
||||
"LW Subsystem");
|
||||
std::shared_ptr<NetworkTable> table(
|
||||
m_liveWindowTable->GetSubTable(subsystem)->GetSubTable(name));
|
||||
table->GetEntry(".type").SetString(component->GetSmartDashboardType());
|
||||
table->GetEntry(".name").SetString(name);
|
||||
table->GetEntry("Subsystem").SetString(subsystem);
|
||||
component->InitTable(table);
|
||||
if (c.isSensor) {
|
||||
m_sensors.push_back(component);
|
||||
comp.firstTime = false;
|
||||
}
|
||||
|
||||
if (m_impl->startLiveWindow) comp.builder.StartLiveWindowMode();
|
||||
comp.builder.UpdateTable();
|
||||
}
|
||||
}
|
||||
|
||||
m_impl->startLiveWindow = false;
|
||||
}
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
|
||||
#include <HAL/HAL.h>
|
||||
|
||||
#include "LiveWindow/LiveWindow.h"
|
||||
#include "SmartDashboard/SendableBuilder.h"
|
||||
|
||||
using namespace frc;
|
||||
|
||||
@@ -23,6 +23,8 @@ using namespace frc;
|
||||
*/
|
||||
NidecBrushless::NidecBrushless(int pwmChannel, int dioChannel)
|
||||
: m_safetyHelper(this), m_dio(dioChannel), m_pwm(pwmChannel) {
|
||||
AddChild(&m_dio);
|
||||
AddChild(&m_pwm);
|
||||
m_safetyHelper.SetExpiration(0.0);
|
||||
m_safetyHelper.SetSafetyEnabled(false);
|
||||
|
||||
@@ -30,8 +32,8 @@ NidecBrushless::NidecBrushless(int pwmChannel, int dioChannel)
|
||||
m_dio.SetPWMRate(15625);
|
||||
m_dio.EnablePWM(0.5);
|
||||
|
||||
LiveWindow::GetInstance()->AddActuator("Nidec Brushless", pwmChannel, this);
|
||||
HAL_Report(HALUsageReporting::kResourceType_NidecBrushless, pwmChannel);
|
||||
SetName("Nidec Brushless", pwmChannel);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -145,44 +147,9 @@ void NidecBrushless::Enable() { m_disabled = false; }
|
||||
*/
|
||||
int NidecBrushless::GetChannel() const { return m_pwm.GetChannel(); }
|
||||
|
||||
/*
|
||||
* Live Window code, only does anything if live window is activated.
|
||||
*/
|
||||
std::string NidecBrushless::GetSmartDashboardType() const {
|
||||
return "Nidec Brushless";
|
||||
}
|
||||
|
||||
void NidecBrushless::InitTable(std::shared_ptr<nt::NetworkTable> subtable) {
|
||||
if (subtable) {
|
||||
m_valueEntry = subtable->GetEntry("Value");
|
||||
UpdateTable();
|
||||
} else {
|
||||
m_valueEntry = nt::NetworkTableEntry();
|
||||
}
|
||||
}
|
||||
|
||||
void NidecBrushless::UpdateTable() {
|
||||
if (m_valueEntry) {
|
||||
m_valueEntry.SetDouble(Get());
|
||||
}
|
||||
}
|
||||
|
||||
void NidecBrushless::StartLiveWindowMode() {
|
||||
Set(0); // Stop for safety
|
||||
if (m_valueEntry) {
|
||||
m_valueListener = m_valueEntry.AddListener(
|
||||
[=](const nt::EntryNotification& event) {
|
||||
if (!event.value->IsDouble()) return;
|
||||
Set(event.value->GetDouble());
|
||||
},
|
||||
NT_NOTIFY_IMMEDIATE | NT_NOTIFY_NEW | NT_NOTIFY_UPDATE);
|
||||
}
|
||||
}
|
||||
|
||||
void NidecBrushless::StopLiveWindowMode() {
|
||||
Set(0); // Stop for safety
|
||||
if (m_valueListener != 0) {
|
||||
m_valueEntry.RemoveListener(m_valueListener);
|
||||
m_valueListener = 0;
|
||||
}
|
||||
void NidecBrushless::InitSendable(SendableBuilder& builder) {
|
||||
builder.SetSmartDashboardType("Nidec Brushless");
|
||||
builder.SetSafeState([=]() { StopMotor(); });
|
||||
builder.AddDoubleProperty("Value", [=]() { return Get(); },
|
||||
[=](double value) { Set(value); });
|
||||
}
|
||||
|
||||
@@ -16,16 +16,10 @@
|
||||
#include "Notifier.h"
|
||||
#include "PIDOutput.h"
|
||||
#include "PIDSource.h"
|
||||
#include "SmartDashboard/SendableBuilder.h"
|
||||
|
||||
using namespace frc;
|
||||
|
||||
static const std::string kP = "p";
|
||||
static const std::string kI = "i";
|
||||
static const std::string kD = "d";
|
||||
static const std::string kF = "f";
|
||||
static const std::string kSetpoint = "setpoint";
|
||||
static const std::string kEnabled = "enabled";
|
||||
|
||||
template <class T>
|
||||
constexpr const T& clamp(const T& value, const T& low, const T& high) {
|
||||
return std::max(low, std::min(value, high));
|
||||
@@ -61,7 +55,8 @@ PIDController::PIDController(double Kp, double Ki, double Kd, PIDSource* source,
|
||||
*/
|
||||
PIDController::PIDController(double Kp, double Ki, double Kd, double Kf,
|
||||
PIDSource* source, PIDOutput* output,
|
||||
double period) {
|
||||
double period)
|
||||
: SendableBase(false) {
|
||||
m_controlLoop = std::make_unique<Notifier>(&PIDController::Calculate, this);
|
||||
|
||||
m_P = Kp;
|
||||
@@ -85,6 +80,7 @@ PIDController::PIDController(double Kp, double Ki, double Kd, double Kf,
|
||||
static int instances = 0;
|
||||
instances++;
|
||||
HAL_Report(HALUsageReporting::kResourceType_PIDController, instances);
|
||||
SetName("PIDController", instances);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -123,7 +119,6 @@ PIDController::PIDController(double Kp, double Ki, double Kd, double Kf,
|
||||
PIDController::~PIDController() {
|
||||
// forcefully stopping the notifier so the callback can successfully run.
|
||||
m_controlLoop->Stop();
|
||||
RemoveListeners();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -257,10 +252,6 @@ void PIDController::SetPID(double p, double i, double d) {
|
||||
m_I = i;
|
||||
m_D = d;
|
||||
}
|
||||
|
||||
if (m_pEntry) m_pEntry.SetDouble(m_P);
|
||||
if (m_iEntry) m_iEntry.SetDouble(m_I);
|
||||
if (m_dEntry) m_dEntry.SetDouble(m_D);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -274,18 +265,51 @@ void PIDController::SetPID(double p, double i, double d) {
|
||||
* @param f Feed forward coefficient
|
||||
*/
|
||||
void PIDController::SetPID(double p, double i, double d, double f) {
|
||||
{
|
||||
std::lock_guard<wpi::mutex> lock(m_thisMutex);
|
||||
m_P = p;
|
||||
m_I = i;
|
||||
m_D = d;
|
||||
m_F = f;
|
||||
}
|
||||
std::lock_guard<wpi::mutex> lock(m_thisMutex);
|
||||
m_P = p;
|
||||
m_I = i;
|
||||
m_D = d;
|
||||
m_F = f;
|
||||
}
|
||||
|
||||
if (m_pEntry) m_pEntry.SetDouble(m_P);
|
||||
if (m_iEntry) m_iEntry.SetDouble(m_I);
|
||||
if (m_dEntry) m_dEntry.SetDouble(m_D);
|
||||
if (m_fEntry) m_fEntry.SetDouble(m_F);
|
||||
/**
|
||||
* Set the Proportional coefficient of the PID controller gain.
|
||||
*
|
||||
* @param p proportional coefficient
|
||||
*/
|
||||
void PIDController::SetP(double p) {
|
||||
std::lock_guard<wpi::mutex> lock(m_thisMutex);
|
||||
m_P = p;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the Integral coefficient of the PID controller gain.
|
||||
*
|
||||
* @param i integral coefficient
|
||||
*/
|
||||
void PIDController::SetI(double i) {
|
||||
std::lock_guard<wpi::mutex> lock(m_thisMutex);
|
||||
m_I = i;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the Differential coefficient of the PID controller gain.
|
||||
*
|
||||
* @param d differential coefficient
|
||||
*/
|
||||
void PIDController::SetD(double d) {
|
||||
std::lock_guard<wpi::mutex> lock(m_thisMutex);
|
||||
m_D = d;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Feed forward coefficient of the PID controller gain.
|
||||
*
|
||||
* @param f Feed forward coefficient
|
||||
*/
|
||||
void PIDController::SetF(double f) {
|
||||
std::lock_guard<wpi::mutex> lock(m_thisMutex);
|
||||
m_F = f;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -403,8 +427,6 @@ void PIDController::SetSetpoint(double setpoint) {
|
||||
m_setpoint = setpoint;
|
||||
}
|
||||
}
|
||||
|
||||
if (m_setpointEntry) m_setpointEntry.SetDouble(m_setpoint);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -556,8 +578,6 @@ void PIDController::Enable() {
|
||||
std::lock_guard<wpi::mutex> lock(m_thisMutex);
|
||||
m_enabled = true;
|
||||
}
|
||||
|
||||
if (m_enabledEntry) m_enabledEntry.SetBoolean(true);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -574,8 +594,17 @@ void PIDController::Disable() {
|
||||
|
||||
m_pidOutput->PIDWrite(0);
|
||||
}
|
||||
}
|
||||
|
||||
if (m_enabledEntry) m_enabledEntry.SetBoolean(false);
|
||||
/**
|
||||
* Set the enabled state of the PIDController.
|
||||
*/
|
||||
void PIDController::SetEnabled(bool enable) {
|
||||
if (enable) {
|
||||
Enable();
|
||||
} else {
|
||||
Disable();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -598,76 +627,21 @@ void PIDController::Reset() {
|
||||
m_result = 0;
|
||||
}
|
||||
|
||||
std::string PIDController::GetSmartDashboardType() const {
|
||||
return "PIDController";
|
||||
}
|
||||
|
||||
void PIDController::InitTable(std::shared_ptr<nt::NetworkTable> subtable) {
|
||||
RemoveListeners();
|
||||
if (subtable) {
|
||||
m_pEntry = subtable->GetEntry(kP);
|
||||
m_pEntry.SetDouble(GetP());
|
||||
m_iEntry = subtable->GetEntry(kI);
|
||||
m_iEntry.SetDouble(GetI());
|
||||
m_dEntry = subtable->GetEntry(kD);
|
||||
m_dEntry.SetDouble(GetD());
|
||||
m_fEntry = subtable->GetEntry(kF);
|
||||
m_fEntry.SetDouble(GetF());
|
||||
m_setpointEntry = subtable->GetEntry(kSetpoint);
|
||||
m_setpointEntry.SetDouble(GetSetpoint());
|
||||
m_enabledEntry = subtable->GetEntry(kEnabled);
|
||||
m_enabledEntry.SetBoolean(IsEnabled());
|
||||
|
||||
m_pListener = m_pEntry.AddListener(
|
||||
[=](const nt::EntryNotification& event) {
|
||||
if (!event.value->IsDouble()) return;
|
||||
std::lock_guard<wpi::mutex> lock(m_thisMutex);
|
||||
m_P = event.value->GetDouble();
|
||||
},
|
||||
NT_NOTIFY_NEW | NT_NOTIFY_UPDATE);
|
||||
|
||||
m_iListener = m_iEntry.AddListener(
|
||||
[=](const nt::EntryNotification& event) {
|
||||
if (!event.value->IsDouble()) return;
|
||||
std::lock_guard<wpi::mutex> lock(m_thisMutex);
|
||||
m_I = event.value->GetDouble();
|
||||
},
|
||||
NT_NOTIFY_NEW | NT_NOTIFY_UPDATE);
|
||||
|
||||
m_dListener = m_dEntry.AddListener(
|
||||
[=](const nt::EntryNotification& event) {
|
||||
if (!event.value->IsDouble()) return;
|
||||
std::lock_guard<wpi::mutex> lock(m_thisMutex);
|
||||
m_D = event.value->GetDouble();
|
||||
},
|
||||
NT_NOTIFY_NEW | NT_NOTIFY_UPDATE);
|
||||
|
||||
m_fListener = m_fEntry.AddListener(
|
||||
[=](const nt::EntryNotification& event) {
|
||||
if (!event.value->IsDouble()) return;
|
||||
std::lock_guard<wpi::mutex> lock(m_thisMutex);
|
||||
m_F = event.value->GetDouble();
|
||||
},
|
||||
NT_NOTIFY_NEW | NT_NOTIFY_UPDATE);
|
||||
|
||||
m_setpointListener = m_setpointEntry.AddListener(
|
||||
[=](const nt::EntryNotification& event) {
|
||||
if (!event.value->IsDouble()) return;
|
||||
SetSetpoint(event.value->GetDouble());
|
||||
},
|
||||
NT_NOTIFY_NEW | NT_NOTIFY_UPDATE);
|
||||
|
||||
m_enabledListener = m_enabledEntry.AddListener(
|
||||
[=](const nt::EntryNotification& event) {
|
||||
if (!event.value->IsBoolean()) return;
|
||||
if (event.value->GetBoolean()) {
|
||||
Enable();
|
||||
} else {
|
||||
Disable();
|
||||
}
|
||||
},
|
||||
NT_NOTIFY_NEW | NT_NOTIFY_UPDATE);
|
||||
}
|
||||
void PIDController::InitSendable(SendableBuilder& builder) {
|
||||
builder.SetSmartDashboardType("PIDController");
|
||||
builder.SetSafeState([=]() { Reset(); });
|
||||
builder.AddDoubleProperty("p", [=]() { return GetP(); },
|
||||
[=](bool value) { SetP(value); });
|
||||
builder.AddDoubleProperty("i", [=]() { return GetI(); },
|
||||
[=](bool value) { SetI(value); });
|
||||
builder.AddDoubleProperty("d", [=]() { return GetD(); },
|
||||
[=](bool value) { SetD(value); });
|
||||
builder.AddDoubleProperty("f", [=]() { return GetF(); },
|
||||
[=](bool value) { SetF(value); });
|
||||
builder.AddDoubleProperty("setpoint", [=]() { return GetSetpoint(); },
|
||||
[=](bool value) { SetSetpoint(value); });
|
||||
builder.AddBooleanProperty("enabled", [=]() { return IsEnabled(); },
|
||||
[=](bool value) { SetEnabled(value); });
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -691,36 +665,3 @@ double PIDController::GetContinuousError(double error) const {
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
void PIDController::UpdateTable() {}
|
||||
|
||||
void PIDController::StartLiveWindowMode() { Disable(); }
|
||||
|
||||
void PIDController::StopLiveWindowMode() {}
|
||||
|
||||
void PIDController::RemoveListeners() {
|
||||
if (m_pListener != 0) {
|
||||
m_pEntry.RemoveListener(m_pListener);
|
||||
m_pListener = 0;
|
||||
}
|
||||
if (m_iListener != 0) {
|
||||
m_iEntry.RemoveListener(m_iListener);
|
||||
m_iListener = 0;
|
||||
}
|
||||
if (m_dListener != 0) {
|
||||
m_dEntry.RemoveListener(m_dListener);
|
||||
m_dListener = 0;
|
||||
}
|
||||
if (m_fListener != 0) {
|
||||
m_fEntry.RemoveListener(m_fListener);
|
||||
m_fListener = 0;
|
||||
}
|
||||
if (m_setpointListener != 0) {
|
||||
m_setpointEntry.RemoveListener(m_setpointListener);
|
||||
m_setpointListener = 0;
|
||||
}
|
||||
if (m_enabledListener != 0) {
|
||||
m_enabledEntry.RemoveListener(m_enabledListener);
|
||||
m_enabledListener = 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,6 +13,8 @@
|
||||
#include <llvm/SmallString.h>
|
||||
#include <llvm/raw_ostream.h>
|
||||
|
||||
#include "SensorBase.h"
|
||||
#include "SmartDashboard/SendableBuilder.h"
|
||||
#include "Utility.h"
|
||||
#include "WPIErrors.h"
|
||||
|
||||
@@ -32,7 +34,7 @@ PWM::PWM(int channel) {
|
||||
llvm::SmallString<32> str;
|
||||
llvm::raw_svector_ostream buf(str);
|
||||
|
||||
if (!CheckPWMChannel(channel)) {
|
||||
if (!SensorBase::CheckPWMChannel(channel)) {
|
||||
buf << "PWM Channel " << channel;
|
||||
wpi_setWPIErrorWithContext(ChannelIndexOutOfRange, buf.str());
|
||||
return;
|
||||
@@ -57,6 +59,7 @@ PWM::PWM(int channel) {
|
||||
wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
|
||||
|
||||
HAL_Report(HALUsageReporting::kResourceType_PWM, channel);
|
||||
SetName("PWM", channel);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -72,8 +75,6 @@ PWM::~PWM() {
|
||||
|
||||
HAL_FreePWMPort(m_handle, &status);
|
||||
wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
|
||||
|
||||
if (m_valueListener != 0) m_valueEntry.RemoveListener(m_valueListener);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -314,37 +315,9 @@ void PWM::SetZeroLatch() {
|
||||
wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
|
||||
}
|
||||
|
||||
void PWM::UpdateTable() {
|
||||
if (m_valueEntry) m_valueEntry.SetDouble(GetSpeed());
|
||||
}
|
||||
|
||||
void PWM::StartLiveWindowMode() {
|
||||
SetSpeed(0);
|
||||
if (m_valueEntry) {
|
||||
m_valueListener = m_valueEntry.AddListener(
|
||||
[=](const nt::EntryNotification& event) {
|
||||
if (!event.value->IsDouble()) return;
|
||||
SetSpeed(event.value->GetDouble());
|
||||
},
|
||||
NT_NOTIFY_IMMEDIATE | NT_NOTIFY_NEW | NT_NOTIFY_UPDATE);
|
||||
}
|
||||
}
|
||||
|
||||
void PWM::StopLiveWindowMode() {
|
||||
SetSpeed(0);
|
||||
if (m_valueListener != 0) {
|
||||
m_valueEntry.RemoveListener(m_valueListener);
|
||||
m_valueListener = 0;
|
||||
}
|
||||
}
|
||||
|
||||
std::string PWM::GetSmartDashboardType() const { return "Speed Controller"; }
|
||||
|
||||
void PWM::InitTable(std::shared_ptr<NetworkTable> subTable) {
|
||||
if (subTable) {
|
||||
m_valueEntry = subTable->GetEntry("Value");
|
||||
UpdateTable();
|
||||
} else {
|
||||
m_valueEntry = nt::NetworkTableEntry();
|
||||
}
|
||||
void PWM::InitSendable(SendableBuilder& builder) {
|
||||
builder.SetSmartDashboardType("Speed Controller");
|
||||
builder.SetSafeState([=]() { SetDisabled(); });
|
||||
builder.AddDoubleProperty("Value", [=]() { return GetSpeed(); },
|
||||
[=](double value) { SetSpeed(value); });
|
||||
}
|
||||
|
||||
@@ -9,8 +9,6 @@
|
||||
|
||||
#include <HAL/HAL.h>
|
||||
|
||||
#include "LiveWindow/LiveWindow.h"
|
||||
|
||||
using namespace frc;
|
||||
|
||||
/**
|
||||
@@ -38,5 +36,5 @@ PWMTalonSRX::PWMTalonSRX(int channel) : PWMSpeedController(channel) {
|
||||
SetZeroLatch();
|
||||
|
||||
HAL_Report(HALUsageReporting::kResourceType_PWMTalonSRX, GetChannel());
|
||||
LiveWindow::GetInstance()->AddActuator("PWMTalonSRX", GetChannel(), this);
|
||||
SetName("PWMTalonSRX", GetChannel());
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
#include <llvm/SmallString.h>
|
||||
#include <llvm/raw_ostream.h>
|
||||
|
||||
#include "LiveWindow/LiveWindow.h"
|
||||
#include "SmartDashboard/SendableBuilder.h"
|
||||
#include "WPIErrors.h"
|
||||
|
||||
using namespace frc;
|
||||
@@ -32,6 +32,7 @@ PowerDistributionPanel::PowerDistributionPanel(int module) : m_module(module) {
|
||||
m_module = -1;
|
||||
return;
|
||||
}
|
||||
SetName("PowerDistributionPanel", module);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -171,39 +172,13 @@ void PowerDistributionPanel::ClearStickyFaults() {
|
||||
}
|
||||
}
|
||||
|
||||
void PowerDistributionPanel::UpdateTable() {
|
||||
for (size_t i = 0; i < sizeof(m_chanEntry) / sizeof(m_chanEntry[0]); ++i) {
|
||||
if (m_chanEntry[i]) m_chanEntry[i].SetDouble(GetCurrent(i));
|
||||
}
|
||||
if (m_voltageEntry) m_voltageEntry.SetDouble(GetVoltage());
|
||||
if (m_totalCurrentEntry) m_totalCurrentEntry.SetDouble(GetTotalCurrent());
|
||||
}
|
||||
|
||||
void PowerDistributionPanel::StartLiveWindowMode() {}
|
||||
|
||||
void PowerDistributionPanel::StopLiveWindowMode() {}
|
||||
|
||||
std::string PowerDistributionPanel::GetSmartDashboardType() const {
|
||||
return "PowerDistributionPanel";
|
||||
}
|
||||
|
||||
void PowerDistributionPanel::InitTable(
|
||||
std::shared_ptr<nt::NetworkTable> subTable) {
|
||||
if (subTable != nullptr) {
|
||||
for (size_t i = 0; i < sizeof(m_chanEntry) / sizeof(m_chanEntry[0]); ++i) {
|
||||
llvm::SmallString<32> buf;
|
||||
llvm::raw_svector_ostream oss(buf);
|
||||
oss << "Chan" << i;
|
||||
m_chanEntry[i] = subTable->GetEntry(oss.str());
|
||||
}
|
||||
m_voltageEntry = subTable->GetEntry("Voltage");
|
||||
m_totalCurrentEntry = subTable->GetEntry("TotalCurrent");
|
||||
UpdateTable();
|
||||
} else {
|
||||
for (size_t i = 0; i < sizeof(m_chanEntry) / sizeof(m_chanEntry[0]); ++i) {
|
||||
m_chanEntry[i] = nt::NetworkTableEntry();
|
||||
}
|
||||
m_voltageEntry = nt::NetworkTableEntry();
|
||||
m_totalCurrentEntry = nt::NetworkTableEntry();
|
||||
void PowerDistributionPanel::InitSendable(SendableBuilder& builder) {
|
||||
builder.SetSmartDashboardType("PowerDistributionPanel");
|
||||
for (int i = 0; i < kPDPChannels; ++i) {
|
||||
builder.AddDoubleProperty("Chan" + llvm::Twine(i),
|
||||
[=]() { return GetCurrent(i); }, nullptr);
|
||||
}
|
||||
builder.AddDoubleProperty("Voltage", [=]() { return GetVoltage(); }, nullptr);
|
||||
builder.AddDoubleProperty("TotalCurrent", [=]() { return GetTotalCurrent(); },
|
||||
nullptr);
|
||||
}
|
||||
|
||||
@@ -12,8 +12,9 @@
|
||||
#include <HAL/Relay.h>
|
||||
#include <llvm/SmallString.h>
|
||||
|
||||
#include "LiveWindow/LiveWindow.h"
|
||||
#include "MotorSafetyHelper.h"
|
||||
#include "SensorBase.h"
|
||||
#include "SmartDashboard/SendableBuilder.h"
|
||||
#include "WPIErrors.h"
|
||||
|
||||
using namespace frc;
|
||||
@@ -88,7 +89,7 @@ Relay::Relay(int channel, Relay::Direction direction)
|
||||
m_safetyHelper = std::make_unique<MotorSafetyHelper>(this);
|
||||
m_safetyHelper->SetSafetyEnabled(false);
|
||||
|
||||
LiveWindow::GetInstance()->AddActuator("Relay", 1, m_channel, this);
|
||||
SetName("Relay", m_channel);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -103,8 +104,6 @@ Relay::~Relay() {
|
||||
// ignore errors, as we want to make sure a free happens.
|
||||
if (m_forwardHandle != HAL_kInvalidHandle) HAL_FreeRelayPort(m_forwardHandle);
|
||||
if (m_reverseHandle != HAL_kInvalidHandle) HAL_FreeRelayPort(m_reverseHandle);
|
||||
|
||||
if (m_valueListener != 0) m_valueEntry.RemoveListener(m_valueListener);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -275,52 +274,31 @@ void Relay::GetDescription(llvm::raw_ostream& desc) const {
|
||||
desc << "Relay " << GetChannel();
|
||||
}
|
||||
|
||||
void Relay::UpdateTable() {
|
||||
if (m_valueEntry) {
|
||||
if (Get() == kOn) {
|
||||
m_valueEntry.SetString("On");
|
||||
} else if (Get() == kForward) {
|
||||
m_valueEntry.SetString("Forward");
|
||||
} else if (Get() == kReverse) {
|
||||
m_valueEntry.SetString("Reverse");
|
||||
} else {
|
||||
m_valueEntry.SetString("Off");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Relay::StartLiveWindowMode() {
|
||||
if (m_valueEntry) {
|
||||
m_valueListener = m_valueEntry.AddListener(
|
||||
[=](const nt::EntryNotification& event) {
|
||||
if (!event.value->IsString()) return;
|
||||
if (event.value->GetString() == "Off")
|
||||
Set(kOff);
|
||||
else if (event.value->GetString() == "Forward")
|
||||
Set(kForward);
|
||||
else if (event.value->GetString() == "Reverse")
|
||||
Set(kReverse);
|
||||
else if (event.value->GetString() == "On")
|
||||
Set(kOn);
|
||||
},
|
||||
NT_NOTIFY_IMMEDIATE | NT_NOTIFY_NEW | NT_NOTIFY_UPDATE);
|
||||
}
|
||||
}
|
||||
|
||||
void Relay::StopLiveWindowMode() {
|
||||
if (m_valueListener != 0) {
|
||||
m_valueEntry.RemoveListener(m_valueListener);
|
||||
m_valueListener = 0;
|
||||
}
|
||||
}
|
||||
|
||||
std::string Relay::GetSmartDashboardType() const { return "Relay"; }
|
||||
|
||||
void Relay::InitTable(std::shared_ptr<nt::NetworkTable> subTable) {
|
||||
if (subTable) {
|
||||
m_valueEntry = subTable->GetEntry("Value");
|
||||
UpdateTable();
|
||||
} else {
|
||||
m_valueEntry = nt::NetworkTableEntry();
|
||||
}
|
||||
void Relay::InitSendable(SendableBuilder& builder) {
|
||||
builder.SetSmartDashboardType("Relay");
|
||||
builder.SetSafeState([=]() { Set(kOff); });
|
||||
builder.AddSmallStringProperty(
|
||||
"Value",
|
||||
[=](llvm::SmallVectorImpl<char>& buf) -> llvm::StringRef {
|
||||
switch (Get()) {
|
||||
case kOn:
|
||||
return "On";
|
||||
case kForward:
|
||||
return "Forward";
|
||||
case kReverse:
|
||||
return "Reverse";
|
||||
default:
|
||||
return "Off";
|
||||
}
|
||||
},
|
||||
[=](llvm::StringRef value) {
|
||||
if (value == "Off")
|
||||
Set(kOff);
|
||||
else if (value == "Forward")
|
||||
Set(kForward);
|
||||
else if (value == "Reverse")
|
||||
Set(kReverse);
|
||||
else if (value == "On")
|
||||
Set(kOn);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -9,8 +9,6 @@
|
||||
|
||||
#include <HAL/HAL.h>
|
||||
|
||||
#include "LiveWindow/LiveWindow.h"
|
||||
|
||||
using namespace frc;
|
||||
|
||||
/**
|
||||
@@ -41,5 +39,5 @@ SD540::SD540(int channel) : PWMSpeedController(channel) {
|
||||
SetZeroLatch();
|
||||
|
||||
HAL_Report(HALUsageReporting::kResourceType_MindsensorsSD540, GetChannel());
|
||||
LiveWindow::GetInstance()->AddActuator("SD540", GetChannel(), this);
|
||||
SetName("SD540", GetChannel());
|
||||
}
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
|
||||
#include <HAL/HAL.h>
|
||||
|
||||
#include "LiveWindow/LiveWindow.h"
|
||||
#include "SmartDashboard/SendableBuilder.h"
|
||||
|
||||
using namespace frc;
|
||||
|
||||
@@ -31,10 +31,7 @@ Servo::Servo(int channel) : SafePWM(channel) {
|
||||
SetPeriodMultiplier(kPeriodMultiplier_4X);
|
||||
|
||||
HAL_Report(HALUsageReporting::kResourceType_Servo, channel);
|
||||
}
|
||||
|
||||
Servo::~Servo() {
|
||||
if (m_valueListener != 0) m_valueEntry.RemoveListener(m_valueListener);
|
||||
SetName("Servo", channel);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -100,35 +97,8 @@ double Servo::GetAngle() const {
|
||||
return GetPosition() * GetServoAngleRange() + kMinServoAngle;
|
||||
}
|
||||
|
||||
void Servo::UpdateTable() {
|
||||
if (m_valueEntry) m_valueEntry.SetDouble(Get());
|
||||
}
|
||||
|
||||
void Servo::StartLiveWindowMode() {
|
||||
if (m_valueEntry) {
|
||||
m_valueListener = m_valueEntry.AddListener(
|
||||
[=](const nt::EntryNotification& event) {
|
||||
if (!event.value->IsDouble()) return;
|
||||
Set(event.value->GetDouble());
|
||||
},
|
||||
NT_NOTIFY_IMMEDIATE | NT_NOTIFY_NEW | NT_NOTIFY_UPDATE);
|
||||
}
|
||||
}
|
||||
|
||||
void Servo::StopLiveWindowMode() {
|
||||
if (m_valueListener != 0) {
|
||||
m_valueEntry.RemoveListener(m_valueListener);
|
||||
m_valueListener = 0;
|
||||
}
|
||||
}
|
||||
|
||||
std::string Servo::GetSmartDashboardType() const { return "Servo"; }
|
||||
|
||||
void Servo::InitTable(std::shared_ptr<nt::NetworkTable> subTable) {
|
||||
if (subTable) {
|
||||
m_valueEntry = subTable->GetEntry("Value");
|
||||
UpdateTable();
|
||||
} else {
|
||||
m_valueEntry = nt::NetworkTableEntry();
|
||||
}
|
||||
void Servo::InitSendable(SendableBuilder& builder) {
|
||||
builder.SetSmartDashboardType("Servo");
|
||||
builder.AddDoubleProperty("Value", [=]() { return Get(); },
|
||||
[=](double value) { Set(value); });
|
||||
}
|
||||
|
||||
91
wpilibc/src/main/native/cpp/SmartDashboard/SendableBase.cpp
Normal file
91
wpilibc/src/main/native/cpp/SmartDashboard/SendableBase.cpp
Normal file
@@ -0,0 +1,91 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) 2017 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 "SmartDashboard/SendableBase.h"
|
||||
|
||||
#include "LiveWindow/LiveWindow.h"
|
||||
|
||||
using namespace frc;
|
||||
|
||||
/**
|
||||
* Creates an instance of the sensor base.
|
||||
*
|
||||
* @param addLiveWindow if true, add this Sendable to LiveWindow
|
||||
*/
|
||||
SendableBase::SendableBase(bool addLiveWindow) {
|
||||
if (addLiveWindow) LiveWindow::GetInstance()->Add(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Free the resources used by this object.
|
||||
*/
|
||||
SendableBase::~SendableBase() { LiveWindow::GetInstance()->Remove(this); }
|
||||
|
||||
std::string SendableBase::GetName() const {
|
||||
std::lock_guard<wpi::mutex> lock(m_mutex);
|
||||
return m_name;
|
||||
}
|
||||
|
||||
void SendableBase::SetName(const llvm::Twine& name) {
|
||||
std::lock_guard<wpi::mutex> lock(m_mutex);
|
||||
m_name = name.str();
|
||||
}
|
||||
|
||||
std::string SendableBase::GetSubsystem() const {
|
||||
std::lock_guard<wpi::mutex> lock(m_mutex);
|
||||
return m_subsystem;
|
||||
}
|
||||
|
||||
void SendableBase::SetSubsystem(const llvm::Twine& subsystem) {
|
||||
std::lock_guard<wpi::mutex> lock(m_mutex);
|
||||
m_subsystem = subsystem.str();
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a child component.
|
||||
*
|
||||
* @param child child component
|
||||
*/
|
||||
void SendableBase::AddChild(std::shared_ptr<Sendable> child) {
|
||||
LiveWindow::GetInstance()->AddChild(this, child);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a child component.
|
||||
*
|
||||
* @param child child component
|
||||
*/
|
||||
void SendableBase::AddChild(void* child) {
|
||||
LiveWindow::GetInstance()->AddChild(this, child);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the name of the sensor with a channel number.
|
||||
*
|
||||
* @param moduleType A string that defines the module name in the label for the
|
||||
* value
|
||||
* @param channel The channel number the device is plugged into
|
||||
*/
|
||||
void SendableBase::SetName(const llvm::Twine& moduleType, int channel) {
|
||||
SetName(moduleType + llvm::Twine('[') + llvm::Twine(channel) +
|
||||
llvm::Twine(']'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the name of the sensor with a module and channel number.
|
||||
*
|
||||
* @param moduleType A string that defines the module name in the label for
|
||||
* the value
|
||||
* @param moduleNumber The number of the particular module type
|
||||
* @param channel The channel number the device is plugged into (usually
|
||||
* PWM)
|
||||
*/
|
||||
void SendableBase::SetName(const llvm::Twine& moduleType, int moduleNumber,
|
||||
int channel) {
|
||||
SetName(moduleType + llvm::Twine('[') + llvm::Twine(moduleNumber) +
|
||||
llvm::Twine(',') + llvm::Twine(channel) + llvm::Twine(']'));
|
||||
}
|
||||
@@ -0,0 +1,365 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) 2017 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 "SmartDashboard/SendableBuilderImpl.h"
|
||||
|
||||
#include <llvm/SmallString.h>
|
||||
|
||||
#include "ntcore_cpp.h"
|
||||
|
||||
using namespace frc;
|
||||
|
||||
void SendableBuilderImpl::SetTable(std::shared_ptr<nt::NetworkTable> table) {
|
||||
m_table = table;
|
||||
}
|
||||
|
||||
std::shared_ptr<nt::NetworkTable> SendableBuilderImpl::GetTable() {
|
||||
return m_table;
|
||||
}
|
||||
|
||||
void SendableBuilderImpl::UpdateTable() {
|
||||
uint64_t time = nt::Now();
|
||||
for (auto& property : m_properties) {
|
||||
if (property.update) property.update(property.entry, time);
|
||||
}
|
||||
if (m_updateTable) m_updateTable();
|
||||
}
|
||||
|
||||
void SendableBuilderImpl::StartLiveWindowMode() {
|
||||
if (m_safeState) m_safeState();
|
||||
for (auto& property : m_properties) property.StartListener();
|
||||
}
|
||||
|
||||
void SendableBuilderImpl::StopLiveWindowMode() {
|
||||
if (m_safeState) m_safeState();
|
||||
for (auto& property : m_properties) property.StopListener();
|
||||
}
|
||||
|
||||
void SendableBuilderImpl::SetSmartDashboardType(const llvm::Twine& type) {
|
||||
m_table->GetEntry(".type").SetString(type);
|
||||
}
|
||||
|
||||
void SendableBuilderImpl::SetSafeState(std::function<void()> func) {
|
||||
m_safeState = func;
|
||||
}
|
||||
|
||||
void SendableBuilderImpl::SetUpdateTable(std::function<void()> func) {
|
||||
m_updateTable = func;
|
||||
}
|
||||
|
||||
nt::NetworkTableEntry SendableBuilderImpl::GetEntry(const llvm::Twine& key) {
|
||||
return m_table->GetEntry(key);
|
||||
}
|
||||
|
||||
void SendableBuilderImpl::AddBooleanProperty(const llvm::Twine& key,
|
||||
std::function<bool()> getter,
|
||||
std::function<void(bool)> setter) {
|
||||
m_properties.emplace_back(*m_table, key);
|
||||
if (getter) {
|
||||
m_properties.back().update = [=](nt::NetworkTableEntry entry,
|
||||
uint64_t time) {
|
||||
entry.SetValue(nt::Value::MakeBoolean(getter(), time));
|
||||
};
|
||||
}
|
||||
if (setter) {
|
||||
m_properties.back().createListener =
|
||||
[=](nt::NetworkTableEntry entry) -> NT_EntryListener {
|
||||
return entry.AddListener(
|
||||
[=](const nt::EntryNotification& event) {
|
||||
if (!event.value->IsBoolean()) return;
|
||||
setter(event.value->GetBoolean());
|
||||
},
|
||||
NT_NOTIFY_IMMEDIATE | NT_NOTIFY_NEW | NT_NOTIFY_UPDATE);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
void SendableBuilderImpl::AddDoubleProperty(
|
||||
const llvm::Twine& key, std::function<double()> getter,
|
||||
std::function<void(double)> setter) {
|
||||
m_properties.emplace_back(*m_table, key);
|
||||
if (getter) {
|
||||
m_properties.back().update = [=](nt::NetworkTableEntry entry,
|
||||
uint64_t time) {
|
||||
entry.SetValue(nt::Value::MakeDouble(getter(), time));
|
||||
};
|
||||
}
|
||||
if (setter) {
|
||||
m_properties.back().createListener =
|
||||
[=](nt::NetworkTableEntry entry) -> NT_EntryListener {
|
||||
return entry.AddListener(
|
||||
[=](const nt::EntryNotification& event) {
|
||||
if (!event.value->IsDouble()) return;
|
||||
setter(event.value->GetDouble());
|
||||
},
|
||||
NT_NOTIFY_IMMEDIATE | NT_NOTIFY_NEW | NT_NOTIFY_UPDATE);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
void SendableBuilderImpl::AddStringProperty(
|
||||
const llvm::Twine& key, std::function<std::string()> getter,
|
||||
std::function<void(llvm::StringRef)> setter) {
|
||||
m_properties.emplace_back(*m_table, key);
|
||||
if (getter) {
|
||||
m_properties.back().update = [=](nt::NetworkTableEntry entry,
|
||||
uint64_t time) {
|
||||
entry.SetValue(nt::Value::MakeString(getter(), time));
|
||||
};
|
||||
}
|
||||
if (setter) {
|
||||
m_properties.back().createListener =
|
||||
[=](nt::NetworkTableEntry entry) -> NT_EntryListener {
|
||||
return entry.AddListener(
|
||||
[=](const nt::EntryNotification& event) {
|
||||
if (!event.value->IsString()) return;
|
||||
setter(event.value->GetString());
|
||||
},
|
||||
NT_NOTIFY_IMMEDIATE | NT_NOTIFY_NEW | NT_NOTIFY_UPDATE);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
void SendableBuilderImpl::AddBooleanArrayProperty(
|
||||
const llvm::Twine& key, std::function<std::vector<int>()> getter,
|
||||
std::function<void(llvm::ArrayRef<int>)> setter) {
|
||||
m_properties.emplace_back(*m_table, key);
|
||||
if (getter) {
|
||||
m_properties.back().update = [=](nt::NetworkTableEntry entry,
|
||||
uint64_t time) {
|
||||
entry.SetValue(nt::Value::MakeBooleanArray(getter(), time));
|
||||
};
|
||||
}
|
||||
if (setter) {
|
||||
m_properties.back().createListener =
|
||||
[=](nt::NetworkTableEntry entry) -> NT_EntryListener {
|
||||
return entry.AddListener(
|
||||
[=](const nt::EntryNotification& event) {
|
||||
if (!event.value->IsBooleanArray()) return;
|
||||
setter(event.value->GetBooleanArray());
|
||||
},
|
||||
NT_NOTIFY_IMMEDIATE | NT_NOTIFY_NEW | NT_NOTIFY_UPDATE);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
void SendableBuilderImpl::AddDoubleArrayProperty(
|
||||
const llvm::Twine& key, std::function<std::vector<double>()> getter,
|
||||
std::function<void(llvm::ArrayRef<double>)> setter) {
|
||||
m_properties.emplace_back(*m_table, key);
|
||||
if (getter) {
|
||||
m_properties.back().update = [=](nt::NetworkTableEntry entry,
|
||||
uint64_t time) {
|
||||
entry.SetValue(nt::Value::MakeDoubleArray(getter(), time));
|
||||
};
|
||||
}
|
||||
if (setter) {
|
||||
m_properties.back().createListener =
|
||||
[=](nt::NetworkTableEntry entry) -> NT_EntryListener {
|
||||
return entry.AddListener(
|
||||
[=](const nt::EntryNotification& event) {
|
||||
if (!event.value->IsDoubleArray()) return;
|
||||
setter(event.value->GetDoubleArray());
|
||||
},
|
||||
NT_NOTIFY_IMMEDIATE | NT_NOTIFY_NEW | NT_NOTIFY_UPDATE);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
void SendableBuilderImpl::AddStringArrayProperty(
|
||||
const llvm::Twine& key, std::function<std::vector<std::string>()> getter,
|
||||
std::function<void(llvm::ArrayRef<std::string>)> setter) {
|
||||
m_properties.emplace_back(*m_table, key);
|
||||
if (getter) {
|
||||
m_properties.back().update = [=](nt::NetworkTableEntry entry,
|
||||
uint64_t time) {
|
||||
entry.SetValue(nt::Value::MakeStringArray(getter(), time));
|
||||
};
|
||||
}
|
||||
if (setter) {
|
||||
m_properties.back().createListener =
|
||||
[=](nt::NetworkTableEntry entry) -> NT_EntryListener {
|
||||
return entry.AddListener(
|
||||
[=](const nt::EntryNotification& event) {
|
||||
if (!event.value->IsStringArray()) return;
|
||||
setter(event.value->GetStringArray());
|
||||
},
|
||||
NT_NOTIFY_IMMEDIATE | NT_NOTIFY_NEW | NT_NOTIFY_UPDATE);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
void SendableBuilderImpl::AddRawProperty(
|
||||
const llvm::Twine& key, std::function<std::string()> getter,
|
||||
std::function<void(llvm::StringRef)> setter) {
|
||||
m_properties.emplace_back(*m_table, key);
|
||||
if (getter) {
|
||||
m_properties.back().update = [=](nt::NetworkTableEntry entry,
|
||||
uint64_t time) {
|
||||
entry.SetValue(nt::Value::MakeRaw(getter(), time));
|
||||
};
|
||||
}
|
||||
if (setter) {
|
||||
m_properties.back().createListener =
|
||||
[=](nt::NetworkTableEntry entry) -> NT_EntryListener {
|
||||
return entry.AddListener(
|
||||
[=](const nt::EntryNotification& event) {
|
||||
if (!event.value->IsRaw()) return;
|
||||
setter(event.value->GetRaw());
|
||||
},
|
||||
NT_NOTIFY_IMMEDIATE | NT_NOTIFY_NEW | NT_NOTIFY_UPDATE);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
void SendableBuilderImpl::AddValueProperty(
|
||||
const llvm::Twine& key, std::function<std::shared_ptr<nt::Value>()> getter,
|
||||
std::function<void(std::shared_ptr<nt::Value>)> setter) {
|
||||
m_properties.emplace_back(*m_table, key);
|
||||
if (getter) {
|
||||
m_properties.back().update = [=](nt::NetworkTableEntry entry,
|
||||
uint64_t time) {
|
||||
entry.SetValue(getter());
|
||||
};
|
||||
}
|
||||
if (setter) {
|
||||
m_properties.back().createListener =
|
||||
[=](nt::NetworkTableEntry entry) -> NT_EntryListener {
|
||||
return entry.AddListener(
|
||||
[=](const nt::EntryNotification& event) { setter(event.value); },
|
||||
NT_NOTIFY_IMMEDIATE | NT_NOTIFY_NEW | NT_NOTIFY_UPDATE);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
void SendableBuilderImpl::AddSmallStringProperty(
|
||||
const llvm::Twine& key,
|
||||
std::function<llvm::StringRef(llvm::SmallVectorImpl<char>& buf)> getter,
|
||||
std::function<void(llvm::StringRef)> setter) {
|
||||
m_properties.emplace_back(*m_table, key);
|
||||
if (getter) {
|
||||
m_properties.back().update = [=](nt::NetworkTableEntry entry,
|
||||
uint64_t time) {
|
||||
llvm::SmallString<128> buf;
|
||||
entry.SetValue(nt::Value::MakeString(getter(buf), time));
|
||||
};
|
||||
}
|
||||
if (setter) {
|
||||
m_properties.back().createListener =
|
||||
[=](nt::NetworkTableEntry entry) -> NT_EntryListener {
|
||||
return entry.AddListener(
|
||||
[=](const nt::EntryNotification& event) {
|
||||
if (!event.value->IsString()) return;
|
||||
setter(event.value->GetString());
|
||||
},
|
||||
NT_NOTIFY_IMMEDIATE | NT_NOTIFY_NEW | NT_NOTIFY_UPDATE);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
void SendableBuilderImpl::AddSmallBooleanArrayProperty(
|
||||
const llvm::Twine& key,
|
||||
std::function<llvm::ArrayRef<int>(llvm::SmallVectorImpl<int>& buf)> getter,
|
||||
std::function<void(llvm::ArrayRef<int>)> setter) {
|
||||
m_properties.emplace_back(*m_table, key);
|
||||
if (getter) {
|
||||
m_properties.back().update = [=](nt::NetworkTableEntry entry,
|
||||
uint64_t time) {
|
||||
llvm::SmallVector<int, 16> buf;
|
||||
entry.SetValue(nt::Value::MakeBooleanArray(getter(buf), time));
|
||||
};
|
||||
}
|
||||
if (setter) {
|
||||
m_properties.back().createListener =
|
||||
[=](nt::NetworkTableEntry entry) -> NT_EntryListener {
|
||||
return entry.AddListener(
|
||||
[=](const nt::EntryNotification& event) {
|
||||
if (!event.value->IsBooleanArray()) return;
|
||||
setter(event.value->GetBooleanArray());
|
||||
},
|
||||
NT_NOTIFY_IMMEDIATE | NT_NOTIFY_NEW | NT_NOTIFY_UPDATE);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
void SendableBuilderImpl::AddSmallDoubleArrayProperty(
|
||||
const llvm::Twine& key,
|
||||
std::function<llvm::ArrayRef<double>(llvm::SmallVectorImpl<double>& buf)>
|
||||
getter,
|
||||
std::function<void(llvm::ArrayRef<double>)> setter) {
|
||||
m_properties.emplace_back(*m_table, key);
|
||||
if (getter) {
|
||||
m_properties.back().update = [=](nt::NetworkTableEntry entry,
|
||||
uint64_t time) {
|
||||
llvm::SmallVector<double, 16> buf;
|
||||
entry.SetValue(nt::Value::MakeDoubleArray(getter(buf), time));
|
||||
};
|
||||
}
|
||||
if (setter) {
|
||||
m_properties.back().createListener =
|
||||
[=](nt::NetworkTableEntry entry) -> NT_EntryListener {
|
||||
return entry.AddListener(
|
||||
[=](const nt::EntryNotification& event) {
|
||||
if (!event.value->IsDoubleArray()) return;
|
||||
setter(event.value->GetDoubleArray());
|
||||
},
|
||||
NT_NOTIFY_IMMEDIATE | NT_NOTIFY_NEW | NT_NOTIFY_UPDATE);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
void SendableBuilderImpl::AddSmallStringArrayProperty(
|
||||
const llvm::Twine& key,
|
||||
std::function<
|
||||
llvm::ArrayRef<std::string>(llvm::SmallVectorImpl<std::string>& buf)>
|
||||
getter,
|
||||
std::function<void(llvm::ArrayRef<std::string>)> setter) {
|
||||
m_properties.emplace_back(*m_table, key);
|
||||
if (getter) {
|
||||
m_properties.back().update = [=](nt::NetworkTableEntry entry,
|
||||
uint64_t time) {
|
||||
llvm::SmallVector<std::string, 16> buf;
|
||||
entry.SetValue(nt::Value::MakeStringArray(getter(buf), time));
|
||||
};
|
||||
}
|
||||
if (setter) {
|
||||
m_properties.back().createListener =
|
||||
[=](nt::NetworkTableEntry entry) -> NT_EntryListener {
|
||||
return entry.AddListener(
|
||||
[=](const nt::EntryNotification& event) {
|
||||
if (!event.value->IsStringArray()) return;
|
||||
setter(event.value->GetStringArray());
|
||||
},
|
||||
NT_NOTIFY_IMMEDIATE | NT_NOTIFY_NEW | NT_NOTIFY_UPDATE);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
void SendableBuilderImpl::AddSmallRawProperty(
|
||||
const llvm::Twine& key,
|
||||
std::function<llvm::StringRef(llvm::SmallVectorImpl<char>& buf)> getter,
|
||||
std::function<void(llvm::StringRef)> setter) {
|
||||
m_properties.emplace_back(*m_table, key);
|
||||
if (getter) {
|
||||
m_properties.back().update = [=](nt::NetworkTableEntry entry,
|
||||
uint64_t time) {
|
||||
llvm::SmallVector<char, 128> buf;
|
||||
entry.SetValue(nt::Value::MakeRaw(getter(buf), time));
|
||||
};
|
||||
}
|
||||
if (setter) {
|
||||
m_properties.back().createListener =
|
||||
[=](nt::NetworkTableEntry entry) -> NT_EntryListener {
|
||||
return entry.AddListener(
|
||||
[=](const nt::EntryNotification& event) {
|
||||
if (!event.value->IsRaw()) return;
|
||||
setter(event.value->GetRaw());
|
||||
},
|
||||
NT_NOTIFY_IMMEDIATE | NT_NOTIFY_NEW | NT_NOTIFY_UPDATE);
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -12,7 +12,3 @@ using namespace frc;
|
||||
const char* SendableChooserBase::kDefault = "default";
|
||||
const char* SendableChooserBase::kOptions = "options";
|
||||
const char* SendableChooserBase::kSelected = "selected";
|
||||
|
||||
std::string SendableChooserBase::GetSmartDashboardType() const {
|
||||
return "String Chooser";
|
||||
}
|
||||
|
||||
@@ -7,18 +7,28 @@
|
||||
|
||||
#include "SmartDashboard/SmartDashboard.h"
|
||||
|
||||
#include <map>
|
||||
#include <llvm/StringMap.h>
|
||||
#include <support/mutex.h>
|
||||
|
||||
#include "HLUsageReporting.h"
|
||||
#include "SmartDashboard/NamedSendable.h"
|
||||
#include "SmartDashboard/Sendable.h"
|
||||
#include "SmartDashboard/SendableBuilderImpl.h"
|
||||
#include "WPIErrors.h"
|
||||
#include "networktables/NetworkTable.h"
|
||||
#include "networktables/NetworkTableInstance.h"
|
||||
|
||||
using namespace frc;
|
||||
|
||||
namespace {
|
||||
struct SmartDashboardData {
|
||||
Sendable* sendable = nullptr;
|
||||
SendableBuilderImpl builder;
|
||||
};
|
||||
} // namespace
|
||||
|
||||
static std::shared_ptr<nt::NetworkTable> s_table;
|
||||
static std::map<std::shared_ptr<nt::NetworkTable>, Sendable*> s_tablesToData;
|
||||
static llvm::StringMap<SmartDashboardData> s_tablesToData;
|
||||
static wpi::mutex s_tablesToDataMutex;
|
||||
|
||||
void SmartDashboard::init() {
|
||||
s_table = nt::NetworkTableInstance::GetDefault().GetTable("SmartDashboard");
|
||||
@@ -126,22 +136,26 @@ void SmartDashboard::PutData(llvm::StringRef key, Sendable* data) {
|
||||
wpi_setGlobalWPIErrorWithContext(NullParameter, "value");
|
||||
return;
|
||||
}
|
||||
std::shared_ptr<nt::NetworkTable> dataTable(s_table->GetSubTable(key));
|
||||
dataTable->GetEntry(".type").SetString(data->GetSmartDashboardType());
|
||||
data->InitTable(dataTable);
|
||||
s_tablesToData[dataTable] = data;
|
||||
std::lock_guard<wpi::mutex> lock(s_tablesToDataMutex);
|
||||
auto& sddata = s_tablesToData[key];
|
||||
if (!sddata.sendable || sddata.sendable != data) {
|
||||
sddata.sendable = data;
|
||||
sddata.builder.SetTable(s_table->GetSubTable(key));
|
||||
data->InitSendable(sddata.builder);
|
||||
}
|
||||
sddata.builder.UpdateTable();
|
||||
}
|
||||
|
||||
/**
|
||||
* Maps the specified key (where the key is the name of the
|
||||
* {@link SmartDashboardNamedData} to the specified value in this table.
|
||||
* Maps the specified key (where the key is the name of the Sendable)
|
||||
* to the specified value in this table.
|
||||
*
|
||||
* The value can be retrieved by calling the get method with a key that is equal
|
||||
* to the original key.
|
||||
*
|
||||
* @param value the value
|
||||
*/
|
||||
void SmartDashboard::PutData(NamedSendable* value) {
|
||||
void SmartDashboard::PutData(Sendable* value) {
|
||||
if (value == nullptr) {
|
||||
wpi_setGlobalWPIErrorWithContext(NullParameter, "value");
|
||||
return;
|
||||
@@ -156,13 +170,13 @@ void SmartDashboard::PutData(NamedSendable* value) {
|
||||
* @return the value
|
||||
*/
|
||||
Sendable* SmartDashboard::GetData(llvm::StringRef key) {
|
||||
std::shared_ptr<nt::NetworkTable> subtable(s_table->GetSubTable(key));
|
||||
Sendable* data = s_tablesToData[subtable];
|
||||
if (data == nullptr) {
|
||||
std::lock_guard<wpi::mutex> lock(s_tablesToDataMutex);
|
||||
auto data = s_tablesToData.find(key);
|
||||
if (data == s_tablesToData.end()) {
|
||||
wpi_setGlobalWPIErrorWithContext(SmartDashboardMissingKey, key);
|
||||
return nullptr;
|
||||
}
|
||||
return data;
|
||||
return data->getValue().sendable;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -13,7 +13,8 @@
|
||||
#include <llvm/SmallString.h>
|
||||
#include <llvm/raw_ostream.h>
|
||||
|
||||
#include "LiveWindow/LiveWindow.h"
|
||||
#include "SensorBase.h"
|
||||
#include "SmartDashboard/SendableBuilder.h"
|
||||
#include "WPIErrors.h"
|
||||
|
||||
using namespace frc;
|
||||
@@ -24,7 +25,7 @@ using namespace frc;
|
||||
* @param channel The channel on the PCM to control (0..7).
|
||||
*/
|
||||
Solenoid::Solenoid(int channel)
|
||||
: Solenoid(GetDefaultSolenoidModule(), channel) {}
|
||||
: Solenoid(SensorBase::GetDefaultSolenoidModule(), channel) {}
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
@@ -36,12 +37,12 @@ Solenoid::Solenoid(int moduleNumber, int channel)
|
||||
: SolenoidBase(moduleNumber), m_channel(channel) {
|
||||
llvm::SmallString<32> str;
|
||||
llvm::raw_svector_ostream buf(str);
|
||||
if (!CheckSolenoidModule(m_moduleNumber)) {
|
||||
if (!SensorBase::CheckSolenoidModule(m_moduleNumber)) {
|
||||
buf << "Solenoid Module " << m_moduleNumber;
|
||||
wpi_setWPIErrorWithContext(ModuleIndexOutOfRange, buf.str());
|
||||
return;
|
||||
}
|
||||
if (!CheckSolenoidChannel(m_channel)) {
|
||||
if (!SensorBase::CheckSolenoidChannel(m_channel)) {
|
||||
buf << "Solenoid Module " << m_channel;
|
||||
wpi_setWPIErrorWithContext(ChannelIndexOutOfRange, buf.str());
|
||||
return;
|
||||
@@ -57,19 +58,15 @@ Solenoid::Solenoid(int moduleNumber, int channel)
|
||||
return;
|
||||
}
|
||||
|
||||
LiveWindow::GetInstance()->AddActuator("Solenoid", m_moduleNumber, m_channel,
|
||||
this);
|
||||
HAL_Report(HALUsageReporting::kResourceType_Solenoid, m_channel,
|
||||
m_moduleNumber);
|
||||
SetName("Solenoid", m_moduleNumber, m_channel);
|
||||
}
|
||||
|
||||
/**
|
||||
* Destructor.
|
||||
*/
|
||||
Solenoid::~Solenoid() {
|
||||
HAL_FreeSolenoidPort(m_solenoidHandle);
|
||||
if (m_valueListener != 0) m_valueEntry.RemoveListener(m_valueListener);
|
||||
}
|
||||
Solenoid::~Solenoid() { HAL_FreeSolenoidPort(m_solenoidHandle); }
|
||||
|
||||
/**
|
||||
* Set the value of a solenoid.
|
||||
@@ -141,34 +138,9 @@ void Solenoid::StartPulse() {
|
||||
wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
|
||||
}
|
||||
|
||||
void Solenoid::UpdateTable() {
|
||||
if (m_valueEntry) m_valueEntry.SetBoolean(Get());
|
||||
}
|
||||
|
||||
void Solenoid::StartLiveWindowMode() {
|
||||
Set(false);
|
||||
if (m_valueEntry) {
|
||||
m_valueEntry.AddListener(
|
||||
[=](const nt::EntryNotification& event) {
|
||||
if (!event.value->IsBoolean()) return;
|
||||
Set(event.value->GetBoolean());
|
||||
},
|
||||
NT_NOTIFY_IMMEDIATE | NT_NOTIFY_NEW | NT_NOTIFY_UPDATE);
|
||||
}
|
||||
}
|
||||
|
||||
void Solenoid::StopLiveWindowMode() {
|
||||
Set(false);
|
||||
if (m_valueListener != 0) m_valueEntry.RemoveListener(m_valueListener);
|
||||
}
|
||||
|
||||
std::string Solenoid::GetSmartDashboardType() const { return "Solenoid"; }
|
||||
|
||||
void Solenoid::InitTable(std::shared_ptr<nt::NetworkTable> subTable) {
|
||||
if (subTable) {
|
||||
m_valueEntry = subTable->GetEntry("Value");
|
||||
UpdateTable();
|
||||
} else {
|
||||
m_valueEntry = nt::NetworkTableEntry();
|
||||
}
|
||||
void Solenoid::InitSendable(SendableBuilder& builder) {
|
||||
builder.SetSmartDashboardType("Solenoid");
|
||||
builder.SetSafeState([=]() { Set(false); });
|
||||
builder.AddBooleanProperty("Value", [=]() { return Get(); },
|
||||
[=](bool value) { Set(value); });
|
||||
}
|
||||
|
||||
@@ -9,8 +9,6 @@
|
||||
|
||||
#include <HAL/HAL.h>
|
||||
|
||||
#include "LiveWindow/LiveWindow.h"
|
||||
|
||||
using namespace frc;
|
||||
|
||||
/**
|
||||
@@ -41,5 +39,5 @@ Spark::Spark(int channel) : PWMSpeedController(channel) {
|
||||
SetZeroLatch();
|
||||
|
||||
HAL_Report(HALUsageReporting::kResourceType_RevSPARK, GetChannel());
|
||||
LiveWindow::GetInstance()->AddActuator("Spark", GetChannel(), this);
|
||||
SetName("Spark", GetChannel());
|
||||
}
|
||||
|
||||
@@ -7,6 +7,8 @@
|
||||
|
||||
#include "SpeedControllerGroup.h"
|
||||
|
||||
#include "SmartDashboard/SendableBuilder.h"
|
||||
|
||||
using namespace frc;
|
||||
|
||||
void SpeedControllerGroup::Set(double speed) {
|
||||
@@ -45,3 +47,10 @@ void SpeedControllerGroup::PIDWrite(double output) {
|
||||
speedController.get().PIDWrite(output);
|
||||
}
|
||||
}
|
||||
|
||||
void SpeedControllerGroup::InitSendable(SendableBuilder& builder) {
|
||||
builder.SetSmartDashboardType("Speed Controller");
|
||||
builder.SetSafeState([=]() { StopMotor(); });
|
||||
builder.AddDoubleProperty("Value", [=]() { return Get(); },
|
||||
[=](double value) { Set(value); });
|
||||
}
|
||||
|
||||
@@ -9,8 +9,6 @@
|
||||
|
||||
#include <HAL/HAL.h>
|
||||
|
||||
#include "LiveWindow/LiveWindow.h"
|
||||
|
||||
using namespace frc;
|
||||
|
||||
/**
|
||||
@@ -39,5 +37,5 @@ Talon::Talon(int channel) : PWMSpeedController(channel) {
|
||||
SetZeroLatch();
|
||||
|
||||
HAL_Report(HALUsageReporting::kResourceType_Talon, GetChannel());
|
||||
LiveWindow::GetInstance()->AddActuator("Talon", GetChannel(), this);
|
||||
SetName("Talon", GetChannel());
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
#include "Counter.h"
|
||||
#include "DigitalInput.h"
|
||||
#include "DigitalOutput.h"
|
||||
#include "LiveWindow/LiveWindow.h"
|
||||
#include "SmartDashboard/SendableBuilder.h"
|
||||
#include "Timer.h"
|
||||
#include "Utility.h"
|
||||
#include "WPIErrors.h"
|
||||
@@ -72,8 +72,7 @@ void Ultrasonic::Initialize() {
|
||||
static int instances = 0;
|
||||
instances++;
|
||||
HAL_Report(HALUsageReporting::kResourceType_Ultrasonic, instances);
|
||||
LiveWindow::GetInstance()->AddSensor("Ultrasonic",
|
||||
m_echoChannel->GetChannel(), this);
|
||||
SetName("Ultrasonic", m_echoChannel->GetChannel());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -94,6 +93,8 @@ Ultrasonic::Ultrasonic(int pingChannel, int echoChannel, DistanceUnit units)
|
||||
m_counter(m_echoChannel) {
|
||||
m_units = units;
|
||||
Initialize();
|
||||
AddChild(m_pingChannel);
|
||||
AddChild(m_echoChannel);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -314,23 +315,8 @@ Ultrasonic::DistanceUnit Ultrasonic::GetDistanceUnits() const {
|
||||
return m_units;
|
||||
}
|
||||
|
||||
void Ultrasonic::UpdateTable() {
|
||||
if (m_valueEntry) {
|
||||
m_valueEntry.SetDouble(GetRangeInches());
|
||||
}
|
||||
}
|
||||
|
||||
void Ultrasonic::StartLiveWindowMode() {}
|
||||
|
||||
void Ultrasonic::StopLiveWindowMode() {}
|
||||
|
||||
std::string Ultrasonic::GetSmartDashboardType() const { return "Ultrasonic"; }
|
||||
|
||||
void Ultrasonic::InitTable(std::shared_ptr<NetworkTable> subTable) {
|
||||
if (subTable) {
|
||||
m_valueEntry = subTable->GetEntry("Value");
|
||||
UpdateTable();
|
||||
} else {
|
||||
m_valueEntry = nt::NetworkTableEntry();
|
||||
}
|
||||
void Ultrasonic::InitSendable(SendableBuilder& builder) {
|
||||
builder.SetSmartDashboardType("Ultrasonic");
|
||||
builder.AddDoubleProperty("Value", [=]() { return GetRangeInches(); },
|
||||
nullptr);
|
||||
}
|
||||
|
||||
@@ -9,8 +9,6 @@
|
||||
|
||||
#include <HAL/HAL.h>
|
||||
|
||||
#include "LiveWindow/LiveWindow.h"
|
||||
|
||||
using namespace frc;
|
||||
|
||||
/**
|
||||
@@ -39,6 +37,6 @@ Victor::Victor(int channel) : PWMSpeedController(channel) {
|
||||
SetSpeed(0.0);
|
||||
SetZeroLatch();
|
||||
|
||||
LiveWindow::GetInstance()->AddActuator("Victor", GetChannel(), this);
|
||||
HAL_Report(HALUsageReporting::kResourceType_Victor, GetChannel());
|
||||
SetName("Victor", GetChannel());
|
||||
}
|
||||
|
||||
@@ -9,8 +9,6 @@
|
||||
|
||||
#include <HAL/HAL.h>
|
||||
|
||||
#include "LiveWindow/LiveWindow.h"
|
||||
|
||||
using namespace frc;
|
||||
|
||||
/**
|
||||
@@ -40,5 +38,5 @@ VictorSP::VictorSP(int channel) : PWMSpeedController(channel) {
|
||||
SetZeroLatch();
|
||||
|
||||
HAL_Report(HALUsageReporting::kResourceType_VictorSP, GetChannel());
|
||||
LiveWindow::GetInstance()->AddActuator("VictorSP", GetChannel(), this);
|
||||
SetName("VictorSP", GetChannel());
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user