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:
Peter Johnson
2017-12-04 23:28:33 -08:00
committed by GitHub
parent 3befc7015b
commit f9bece2ffb
213 changed files with 3704 additions and 3758 deletions

View File

@@ -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);
});
}

View File

@@ -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);
});
}

View File

@@ -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);
});
}

View File

@@ -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) {

View File

@@ -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);
}

View File

@@ -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() {

View File

@@ -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);
}

View File

@@ -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); });
}

View File

@@ -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);
}

View File

@@ -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);
}

View File

@@ -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&) {}

View File

@@ -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);
}

View File

@@ -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; });
}

View File

@@ -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);
}

View File

@@ -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");
}

View File

@@ -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);
}

View File

@@ -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();
}
});
}

View File

@@ -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);
}

View File

@@ -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);
}

View File

@@ -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);
}

View File

@@ -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&) {}

View File

@@ -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);
}

View File

@@ -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); });
}

View File

@@ -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);
});
}

View File

@@ -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); });
}

View File

@@ -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); });
}

View File

@@ -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); });
}

View File

@@ -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);
}

View File

@@ -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");
}

View File

@@ -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);
}

View File

@@ -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();
}

View File

@@ -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());
}

View File

@@ -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;
}

View File

@@ -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); });
}

View File

@@ -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;
}
}

View File

@@ -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); });
}

View File

@@ -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());
}

View File

@@ -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);
}

View File

@@ -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);
});
}

View File

@@ -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());
}

View File

@@ -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); });
}

View 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(']'));
}

View File

@@ -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);
};
}
}

View File

@@ -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";
}

View File

@@ -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;
}
/**

View File

@@ -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); });
}

View File

@@ -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());
}

View File

@@ -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); });
}

View File

@@ -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());
}

View File

@@ -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);
}

View File

@@ -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());
}

View File

@@ -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());
}