mirror of
https://github.com/wpilibsuite/allwpilib
synced 2026-06-23 01:21:42 +00:00
Update LiveWindow to provide continuous telemetry. (#771)
LiveWindow.updateValues() is now called from IterativeRobotBase on every loop iteration. Telemetry for all WPILib classes is enabled by default; it can be disabled for specific classes using LiveWindow.disableTelemetry(), or all telemetry can be disabled using LiveWindow.disableAllTelemetry(). This necessitated changing the hook methodology into other classes to be more property-based rather than each class providing multiple functions. This had the benefit of reducing boilerplate and increasing consistency. - Remove NamedSendable, add name to Sendable. - Provide SendableBase abstract class. - Deprecate LiveWindow addSensor/addActuator interfaces. - Add LiveWindow support to drive classes. - Add addChild() helper functions to Subsystem. - Fix inheritance hierarchy. Now only sensors inherit from SensorBase. Other devices inherit from some combination of SendableBase, ErrorBase, or nothing.
This commit is contained in:
@@ -10,20 +10,18 @@ package edu.wpi.first.wpilibj;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.ByteOrder;
|
||||
|
||||
import edu.wpi.first.networktables.NetworkTable;
|
||||
import edu.wpi.first.networktables.NetworkTableEntry;
|
||||
import edu.wpi.first.wpilibj.hal.FRCNetComm.tInstances;
|
||||
import edu.wpi.first.wpilibj.hal.FRCNetComm.tResourceType;
|
||||
import edu.wpi.first.wpilibj.hal.HAL;
|
||||
import edu.wpi.first.wpilibj.interfaces.Accelerometer;
|
||||
import edu.wpi.first.wpilibj.livewindow.LiveWindow;
|
||||
import edu.wpi.first.wpilibj.livewindow.LiveWindowSendable;
|
||||
import edu.wpi.first.wpilibj.smartdashboard.SendableBuilder;
|
||||
|
||||
/**
|
||||
* ADXL345 I2C Accelerometer.
|
||||
*/
|
||||
@SuppressWarnings({"TypeName", "PMD.UnusedPrivateField"})
|
||||
public class ADXL345_I2C extends SensorBase implements Accelerometer, LiveWindowSendable {
|
||||
public class ADXL345_I2C extends SensorBase implements Accelerometer, Sendable {
|
||||
|
||||
private static final byte kAddress = 0x1D;
|
||||
private static final byte kPowerCtlRegister = 0x2D;
|
||||
@@ -93,9 +91,14 @@ public class ADXL345_I2C extends SensorBase implements Accelerometer, LiveWindow
|
||||
setRange(range);
|
||||
|
||||
HAL.report(tResourceType.kResourceType_ADXL345, tInstances.kADXL345_I2C);
|
||||
LiveWindow.addSensor("ADXL345_I2C", port.value, this);
|
||||
setName("ADXL345_I2C", port.value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void free() {
|
||||
super.free();
|
||||
m_i2c.free();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setRange(Range range) {
|
||||
@@ -171,49 +174,16 @@ public class ADXL345_I2C extends SensorBase implements Accelerometer, LiveWindow
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSmartDashboardType() {
|
||||
return "3AxisAccelerometer";
|
||||
}
|
||||
|
||||
@SuppressWarnings("MemberName")
|
||||
private NetworkTableEntry m_xEntry;
|
||||
@SuppressWarnings("MemberName")
|
||||
private NetworkTableEntry m_yEntry;
|
||||
@SuppressWarnings("MemberName")
|
||||
private NetworkTableEntry m_zEntry;
|
||||
|
||||
@Override
|
||||
public void initTable(NetworkTable subtable) {
|
||||
if (subtable != null) {
|
||||
m_xEntry = subtable.getEntry("X");
|
||||
m_yEntry = subtable.getEntry("Y");
|
||||
m_zEntry = subtable.getEntry("Z");
|
||||
updateTable();
|
||||
} else {
|
||||
m_xEntry = null;
|
||||
m_yEntry = null;
|
||||
m_zEntry = null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateTable() {
|
||||
if (m_xEntry != null) {
|
||||
m_xEntry.setDouble(getX());
|
||||
}
|
||||
if (m_yEntry != null) {
|
||||
m_yEntry.setDouble(getY());
|
||||
}
|
||||
if (m_zEntry != null) {
|
||||
m_zEntry.setDouble(getZ());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void startLiveWindowMode() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stopLiveWindowMode() {
|
||||
public void initSendable(SendableBuilder builder) {
|
||||
builder.setSmartDashboardType("3AxisAccelerometer");
|
||||
NetworkTableEntry entryX = builder.getEntry("X");
|
||||
NetworkTableEntry entryY = builder.getEntry("Y");
|
||||
NetworkTableEntry entryZ = builder.getEntry("Z");
|
||||
builder.setUpdateTable(() -> {
|
||||
AllAxes data = getAccelerations();
|
||||
entryX.setDouble(data.XAxis);
|
||||
entryY.setDouble(data.YAxis);
|
||||
entryZ.setDouble(data.ZAxis);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,20 +10,18 @@ package edu.wpi.first.wpilibj;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.ByteOrder;
|
||||
|
||||
import edu.wpi.first.networktables.NetworkTable;
|
||||
import edu.wpi.first.networktables.NetworkTableEntry;
|
||||
import edu.wpi.first.wpilibj.hal.FRCNetComm.tInstances;
|
||||
import edu.wpi.first.wpilibj.hal.FRCNetComm.tResourceType;
|
||||
import edu.wpi.first.wpilibj.hal.HAL;
|
||||
import edu.wpi.first.wpilibj.interfaces.Accelerometer;
|
||||
import edu.wpi.first.wpilibj.livewindow.LiveWindow;
|
||||
import edu.wpi.first.wpilibj.livewindow.LiveWindowSendable;
|
||||
import edu.wpi.first.wpilibj.smartdashboard.SendableBuilder;
|
||||
|
||||
/**
|
||||
* ADXL345 SPI Accelerometer.
|
||||
*/
|
||||
@SuppressWarnings({"TypeName", "PMD.UnusedPrivateField"})
|
||||
public class ADXL345_SPI extends SensorBase implements Accelerometer, LiveWindowSendable {
|
||||
public class ADXL345_SPI extends SensorBase implements Accelerometer, Sendable {
|
||||
private static final int kPowerCtlRegister = 0x2D;
|
||||
private static final int kDataFormatRegister = 0x31;
|
||||
private static final int kDataRegister = 0x32;
|
||||
@@ -78,10 +76,12 @@ public class ADXL345_SPI extends SensorBase implements Accelerometer, LiveWindow
|
||||
public ADXL345_SPI(SPI.Port port, Range range) {
|
||||
m_spi = new SPI(port);
|
||||
init(range);
|
||||
LiveWindow.addSensor("ADXL345_SPI", port.value, this);
|
||||
setName("ADXL345_SPI", port.value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void free() {
|
||||
super.free();
|
||||
m_spi.free();
|
||||
}
|
||||
|
||||
@@ -189,49 +189,16 @@ public class ADXL345_SPI extends SensorBase implements Accelerometer, LiveWindow
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSmartDashboardType() {
|
||||
return "3AxisAccelerometer";
|
||||
}
|
||||
|
||||
@SuppressWarnings("MemberName")
|
||||
private NetworkTableEntry m_xEntry;
|
||||
@SuppressWarnings("MemberName")
|
||||
private NetworkTableEntry m_yEntry;
|
||||
@SuppressWarnings("MemberName")
|
||||
private NetworkTableEntry m_zEntry;
|
||||
|
||||
@Override
|
||||
public void initTable(NetworkTable subtable) {
|
||||
if (subtable != null) {
|
||||
m_xEntry = subtable.getEntry("X");
|
||||
m_yEntry = subtable.getEntry("Y");
|
||||
m_zEntry = subtable.getEntry("Z");
|
||||
updateTable();
|
||||
} else {
|
||||
m_xEntry = null;
|
||||
m_yEntry = null;
|
||||
m_zEntry = null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateTable() {
|
||||
if (m_xEntry != null) {
|
||||
m_xEntry.setDouble(getX());
|
||||
}
|
||||
if (m_yEntry != null) {
|
||||
m_yEntry.setDouble(getY());
|
||||
}
|
||||
if (m_zEntry != null) {
|
||||
m_zEntry.setDouble(getZ());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void startLiveWindowMode() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stopLiveWindowMode() {
|
||||
public void initSendable(SendableBuilder builder) {
|
||||
builder.setSmartDashboardType("3AxisAccelerometer");
|
||||
NetworkTableEntry entryX = builder.getEntry("X");
|
||||
NetworkTableEntry entryY = builder.getEntry("Y");
|
||||
NetworkTableEntry entryZ = builder.getEntry("Z");
|
||||
builder.setUpdateTable(() -> {
|
||||
AllAxes data = getAccelerations();
|
||||
entryX.setDouble(data.XAxis);
|
||||
entryY.setDouble(data.YAxis);
|
||||
entryZ.setDouble(data.ZAxis);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,13 +10,11 @@ package edu.wpi.first.wpilibj;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.ByteOrder;
|
||||
|
||||
import edu.wpi.first.networktables.NetworkTable;
|
||||
import edu.wpi.first.networktables.NetworkTableEntry;
|
||||
import edu.wpi.first.wpilibj.hal.FRCNetComm.tResourceType;
|
||||
import edu.wpi.first.wpilibj.hal.HAL;
|
||||
import edu.wpi.first.wpilibj.interfaces.Accelerometer;
|
||||
import edu.wpi.first.wpilibj.livewindow.LiveWindow;
|
||||
import edu.wpi.first.wpilibj.livewindow.LiveWindowSendable;
|
||||
import edu.wpi.first.wpilibj.smartdashboard.SendableBuilder;
|
||||
|
||||
/**
|
||||
* ADXL362 SPI Accelerometer.
|
||||
@@ -24,7 +22,7 @@ import edu.wpi.first.wpilibj.livewindow.LiveWindowSendable;
|
||||
* <p>This class allows access to an Analog Devices ADXL362 3-axis accelerometer.
|
||||
*/
|
||||
@SuppressWarnings("PMD.UnusedPrivateField")
|
||||
public class ADXL362 extends SensorBase implements Accelerometer, LiveWindowSendable {
|
||||
public class ADXL362 extends SensorBase implements Accelerometer, Sendable {
|
||||
private static final byte kRegWrite = 0x0A;
|
||||
private static final byte kRegRead = 0x0B;
|
||||
|
||||
@@ -82,6 +80,7 @@ public class ADXL362 extends SensorBase implements Accelerometer, LiveWindowSend
|
||||
*/
|
||||
public ADXL362(SPI.Port port, Range range) {
|
||||
m_spi = new SPI(port);
|
||||
|
||||
m_spi.setClockRate(3000000);
|
||||
m_spi.setMSBFirst();
|
||||
m_spi.setSampleDataOnFalling();
|
||||
@@ -109,17 +108,25 @@ public class ADXL362 extends SensorBase implements Accelerometer, LiveWindowSend
|
||||
m_spi.write(transferBuffer, 3);
|
||||
|
||||
HAL.report(tResourceType.kResourceType_ADXL362, port.value);
|
||||
LiveWindow.addSensor("ADXL362", port.value, this);
|
||||
setName("ADXL362", port.value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void free() {
|
||||
m_spi.free();
|
||||
super.free();
|
||||
if (m_spi != null) {
|
||||
m_spi.free();
|
||||
m_spi = null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setRange(Range range) {
|
||||
final byte value;
|
||||
if (m_spi == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
final byte value;
|
||||
switch (range) {
|
||||
case k2G:
|
||||
value = kFilterCtl_Range2G;
|
||||
@@ -205,49 +212,16 @@ public class ADXL362 extends SensorBase implements Accelerometer, LiveWindowSend
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSmartDashboardType() {
|
||||
return "3AxisAccelerometer";
|
||||
}
|
||||
|
||||
@SuppressWarnings("MemberName")
|
||||
private NetworkTableEntry m_xEntry;
|
||||
@SuppressWarnings("MemberName")
|
||||
private NetworkTableEntry m_yEntry;
|
||||
@SuppressWarnings("MemberName")
|
||||
private NetworkTableEntry m_zEntry;
|
||||
|
||||
@Override
|
||||
public void initTable(NetworkTable subtable) {
|
||||
if (subtable != null) {
|
||||
m_xEntry = subtable.getEntry("X");
|
||||
m_yEntry = subtable.getEntry("Y");
|
||||
m_zEntry = subtable.getEntry("Z");
|
||||
updateTable();
|
||||
} else {
|
||||
m_xEntry = null;
|
||||
m_yEntry = null;
|
||||
m_zEntry = null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateTable() {
|
||||
if (m_xEntry != null) {
|
||||
m_xEntry.setDouble(getX());
|
||||
}
|
||||
if (m_yEntry != null) {
|
||||
m_yEntry.setDouble(getY());
|
||||
}
|
||||
if (m_zEntry != null) {
|
||||
m_zEntry.setDouble(getZ());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void startLiveWindowMode() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stopLiveWindowMode() {
|
||||
public void initSendable(SendableBuilder builder) {
|
||||
builder.setSmartDashboardType("3AxisAccelerometer");
|
||||
NetworkTableEntry entryX = builder.getEntry("X");
|
||||
NetworkTableEntry entryY = builder.getEntry("Y");
|
||||
NetworkTableEntry entryZ = builder.getEntry("Z");
|
||||
builder.setUpdateTable(() -> {
|
||||
AllAxes data = getAccelerations();
|
||||
entryX.setDouble(data.XAxis);
|
||||
entryY.setDouble(data.YAxis);
|
||||
entryZ.setDouble(data.ZAxis);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,8 +13,6 @@ import java.nio.ByteOrder;
|
||||
import edu.wpi.first.wpilibj.hal.FRCNetComm.tResourceType;
|
||||
import edu.wpi.first.wpilibj.hal.HAL;
|
||||
import edu.wpi.first.wpilibj.interfaces.Gyro;
|
||||
import edu.wpi.first.wpilibj.livewindow.LiveWindow;
|
||||
import edu.wpi.first.wpilibj.livewindow.LiveWindowSendable;
|
||||
|
||||
/**
|
||||
* Use a rate gyro to return the robots heading relative to a starting position. The Gyro class
|
||||
@@ -26,7 +24,7 @@ import edu.wpi.first.wpilibj.livewindow.LiveWindowSendable;
|
||||
* <p>This class is for the digital ADXRS450 gyro sensor that connects via SPI.
|
||||
*/
|
||||
@SuppressWarnings({"TypeName", "AbbreviationAsWordInName", "PMD.UnusedPrivateField"})
|
||||
public class ADXRS450_Gyro extends GyroBase implements Gyro, PIDSource, LiveWindowSendable {
|
||||
public class ADXRS450_Gyro extends GyroBase implements Gyro, PIDSource, Sendable {
|
||||
private static final double kSamplePeriod = 0.001;
|
||||
private static final double kCalibrationSampleTime = 5.0;
|
||||
private static final double kDegreePerSecondPerLSB = 0.0125;
|
||||
@@ -57,6 +55,7 @@ public class ADXRS450_Gyro extends GyroBase implements Gyro, PIDSource, LiveWind
|
||||
*/
|
||||
public ADXRS450_Gyro(SPI.Port port) {
|
||||
m_spi = new SPI(port);
|
||||
|
||||
m_spi.setClockRate(3000000);
|
||||
m_spi.setMSBFirst();
|
||||
m_spi.setSampleDataOnRising();
|
||||
@@ -78,7 +77,7 @@ public class ADXRS450_Gyro extends GyroBase implements Gyro, PIDSource, LiveWind
|
||||
calibrate();
|
||||
|
||||
HAL.report(tResourceType.kResourceType_ADXRS450, port.value);
|
||||
LiveWindow.addSensor("ADXRS450_Gyro", port.value, this);
|
||||
setName("ADXRS450_Gyro", port.value);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -137,6 +136,7 @@ public class ADXRS450_Gyro extends GyroBase implements Gyro, PIDSource, LiveWind
|
||||
*/
|
||||
@Override
|
||||
public void free() {
|
||||
super.free();
|
||||
if (m_spi != null) {
|
||||
m_spi.free();
|
||||
m_spi = null;
|
||||
|
||||
@@ -7,12 +7,9 @@
|
||||
|
||||
package edu.wpi.first.wpilibj;
|
||||
|
||||
import edu.wpi.first.networktables.NetworkTable;
|
||||
import edu.wpi.first.networktables.NetworkTableEntry;
|
||||
import edu.wpi.first.wpilibj.hal.FRCNetComm.tResourceType;
|
||||
import edu.wpi.first.wpilibj.hal.HAL;
|
||||
import edu.wpi.first.wpilibj.livewindow.LiveWindow;
|
||||
import edu.wpi.first.wpilibj.livewindow.LiveWindowSendable;
|
||||
import edu.wpi.first.wpilibj.smartdashboard.SendableBuilder;
|
||||
|
||||
import static java.util.Objects.requireNonNull;
|
||||
|
||||
@@ -21,7 +18,7 @@ import static java.util.Objects.requireNonNull;
|
||||
* through the sensor. Many sensors have multiple axis and can be treated as multiple devices. Each
|
||||
* is calibrated by finding the center value over a period of time.
|
||||
*/
|
||||
public class AnalogAccelerometer extends SensorBase implements PIDSource, LiveWindowSendable {
|
||||
public class AnalogAccelerometer extends SensorBase implements PIDSource, Sendable {
|
||||
|
||||
private AnalogInput m_analogChannel;
|
||||
private double m_voltsPerG = 1.0;
|
||||
@@ -35,7 +32,7 @@ public class AnalogAccelerometer extends SensorBase implements PIDSource, LiveWi
|
||||
private void initAccelerometer() {
|
||||
HAL.report(tResourceType.kResourceType_Accelerometer,
|
||||
m_analogChannel.getChannel());
|
||||
LiveWindow.addSensor("Accelerometer", m_analogChannel.getChannel(), this);
|
||||
setName("Accelerometer", m_analogChannel.getChannel());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -46,9 +43,9 @@ public class AnalogAccelerometer extends SensorBase implements PIDSource, LiveWi
|
||||
* @param channel The channel number for the analog input the accelerometer is connected to
|
||||
*/
|
||||
public AnalogAccelerometer(final int channel) {
|
||||
m_analogChannel = new AnalogInput(channel);
|
||||
this(new AnalogInput(channel));
|
||||
m_allocatedChannel = true;
|
||||
initAccelerometer();
|
||||
addChild(m_analogChannel);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -72,6 +69,7 @@ public class AnalogAccelerometer extends SensorBase implements PIDSource, LiveWi
|
||||
*/
|
||||
@Override
|
||||
public void free() {
|
||||
super.free();
|
||||
if (m_analogChannel != null && m_allocatedChannel) {
|
||||
m_analogChannel.free();
|
||||
}
|
||||
@@ -86,6 +84,9 @@ public class AnalogAccelerometer extends SensorBase implements PIDSource, LiveWi
|
||||
* @return The current acceleration of the sensor in Gs.
|
||||
*/
|
||||
public double getAcceleration() {
|
||||
if (m_analogChannel == null) {
|
||||
return 0.0;
|
||||
}
|
||||
return (m_analogChannel.getAverageVoltage() - m_zeroGVoltage) / m_voltsPerG;
|
||||
}
|
||||
|
||||
@@ -134,43 +135,8 @@ public class AnalogAccelerometer extends SensorBase implements PIDSource, LiveWi
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSmartDashboardType() {
|
||||
return "Accelerometer";
|
||||
}
|
||||
|
||||
/*
|
||||
* Live Window code, only does anything if live window is activated.
|
||||
*/
|
||||
private NetworkTableEntry m_valueEntry;
|
||||
|
||||
@Override
|
||||
public void initTable(NetworkTable subtable) {
|
||||
if (subtable != null) {
|
||||
m_valueEntry = subtable.getEntry("Value");
|
||||
updateTable();
|
||||
} else {
|
||||
m_valueEntry = null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateTable() {
|
||||
if (m_valueEntry != null) {
|
||||
m_valueEntry.setDouble(getAcceleration());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Analog Channels don't have to do anything special when entering the LiveWindow. {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public void startLiveWindowMode() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Analog Channels don't have to do anything special when exiting the LiveWindow. {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public void stopLiveWindowMode() {
|
||||
public void initSendable(SendableBuilder builder) {
|
||||
builder.setSmartDashboardType("Accelerometer");
|
||||
builder.addDoubleProperty("Value", this::getAcceleration, null);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,8 +11,6 @@ import edu.wpi.first.wpilibj.hal.AnalogGyroJNI;
|
||||
import edu.wpi.first.wpilibj.hal.FRCNetComm.tResourceType;
|
||||
import edu.wpi.first.wpilibj.hal.HAL;
|
||||
import edu.wpi.first.wpilibj.interfaces.Gyro;
|
||||
import edu.wpi.first.wpilibj.livewindow.LiveWindow;
|
||||
import edu.wpi.first.wpilibj.livewindow.LiveWindowSendable;
|
||||
|
||||
import static java.util.Objects.requireNonNull;
|
||||
|
||||
@@ -25,7 +23,7 @@ import static java.util.Objects.requireNonNull;
|
||||
*
|
||||
* <p>This class is for gyro sensors that connect to an analog input.
|
||||
*/
|
||||
public class AnalogGyro extends GyroBase implements Gyro, PIDSource, LiveWindowSendable {
|
||||
public class AnalogGyro extends GyroBase implements Gyro, PIDSource, Sendable {
|
||||
|
||||
private static final double kDefaultVoltsPerDegreePerSecond = 0.007;
|
||||
protected AnalogInput m_analog;
|
||||
@@ -44,7 +42,7 @@ public class AnalogGyro extends GyroBase implements Gyro, PIDSource, LiveWindowS
|
||||
AnalogGyroJNI.setupAnalogGyro(m_gyroHandle);
|
||||
|
||||
HAL.report(tResourceType.kResourceType_Gyro, m_analog.getChannel());
|
||||
LiveWindow.addSensor("AnalogGyro", m_analog.getChannel(), this);
|
||||
setName("AnalogGyro", m_analog.getChannel());
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -61,6 +59,7 @@ public class AnalogGyro extends GyroBase implements Gyro, PIDSource, LiveWindowS
|
||||
public AnalogGyro(int channel) {
|
||||
this(new AnalogInput(channel));
|
||||
m_channelAllocated = true;
|
||||
addChild(m_analog);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -90,6 +89,7 @@ public class AnalogGyro extends GyroBase implements Gyro, PIDSource, LiveWindowS
|
||||
public AnalogGyro(int channel, int center, double offset) {
|
||||
this(new AnalogInput(channel), center, offset);
|
||||
m_channelAllocated = true;
|
||||
addChild(m_analog);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -121,6 +121,7 @@ public class AnalogGyro extends GyroBase implements Gyro, PIDSource, LiveWindowS
|
||||
*/
|
||||
@Override
|
||||
public void free() {
|
||||
super.free();
|
||||
if (m_analog != null && m_channelAllocated) {
|
||||
m_analog.free();
|
||||
}
|
||||
|
||||
@@ -7,13 +7,10 @@
|
||||
|
||||
package edu.wpi.first.wpilibj;
|
||||
|
||||
import edu.wpi.first.networktables.NetworkTable;
|
||||
import edu.wpi.first.networktables.NetworkTableEntry;
|
||||
import edu.wpi.first.wpilibj.hal.AnalogJNI;
|
||||
import edu.wpi.first.wpilibj.hal.FRCNetComm.tResourceType;
|
||||
import edu.wpi.first.wpilibj.hal.HAL;
|
||||
import edu.wpi.first.wpilibj.livewindow.LiveWindow;
|
||||
import edu.wpi.first.wpilibj.livewindow.LiveWindowSendable;
|
||||
import edu.wpi.first.wpilibj.smartdashboard.SendableBuilder;
|
||||
import edu.wpi.first.wpilibj.util.AllocationException;
|
||||
|
||||
/**
|
||||
@@ -28,7 +25,7 @@ import edu.wpi.first.wpilibj.util.AllocationException;
|
||||
* accumulated effectively increasing the resolution, while the averaged samples are divided by the
|
||||
* number of samples to retain the resolution, but get more stable values.
|
||||
*/
|
||||
public class AnalogInput extends SensorBase implements PIDSource, LiveWindowSendable {
|
||||
public class AnalogInput extends SensorBase implements PIDSource, Sendable {
|
||||
|
||||
private static final int kAccumulatorSlot = 1;
|
||||
int m_port; // explicit no modifier, private and package accessible.
|
||||
@@ -49,14 +46,16 @@ public class AnalogInput extends SensorBase implements PIDSource, LiveWindowSend
|
||||
final int portHandle = AnalogJNI.getPort((byte) channel);
|
||||
m_port = AnalogJNI.initializeAnalogInputPort(portHandle);
|
||||
|
||||
LiveWindow.addSensor("AnalogInput", channel, this);
|
||||
HAL.report(tResourceType.kResourceType_AnalogChannel, channel);
|
||||
setName("AnalogInput", channel);
|
||||
}
|
||||
|
||||
/**
|
||||
* Channel destructor.
|
||||
*/
|
||||
@Override
|
||||
public void free() {
|
||||
super.free();
|
||||
AnalogJNI.freeAnalogInputPort(m_port);
|
||||
m_port = 0;
|
||||
m_channel = 0;
|
||||
@@ -347,44 +346,9 @@ public class AnalogInput extends SensorBase implements PIDSource, LiveWindowSend
|
||||
return getAverageVoltage();
|
||||
}
|
||||
|
||||
/**
|
||||
* Live Window code, only does anything if live window is activated.
|
||||
*/
|
||||
@Override
|
||||
public String getSmartDashboardType() {
|
||||
return "Analog Input";
|
||||
}
|
||||
|
||||
private NetworkTableEntry m_valueEntry;
|
||||
|
||||
@Override
|
||||
public void initTable(NetworkTable subtable) {
|
||||
if (subtable != null) {
|
||||
m_valueEntry = subtable.getEntry("Value");
|
||||
updateTable();
|
||||
} else {
|
||||
m_valueEntry = null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateTable() {
|
||||
if (m_valueEntry != null) {
|
||||
m_valueEntry.setDouble(getAverageVoltage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Analog Channels don't have to do anything special when entering the LiveWindow. {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public void startLiveWindowMode() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Analog Channels don't have to do anything special when exiting the LiveWindow. {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public void stopLiveWindowMode() {
|
||||
public void initSendable(SendableBuilder builder) {
|
||||
builder.setSmartDashboardType("Analog Input");
|
||||
builder.addDoubleProperty("Value", this::getAverageVoltage, null);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,18 +7,15 @@
|
||||
|
||||
package edu.wpi.first.wpilibj;
|
||||
|
||||
import edu.wpi.first.networktables.NetworkTable;
|
||||
import edu.wpi.first.networktables.NetworkTableEntry;
|
||||
import edu.wpi.first.wpilibj.hal.AnalogJNI;
|
||||
import edu.wpi.first.wpilibj.hal.FRCNetComm.tResourceType;
|
||||
import edu.wpi.first.wpilibj.hal.HAL;
|
||||
import edu.wpi.first.wpilibj.livewindow.LiveWindow;
|
||||
import edu.wpi.first.wpilibj.livewindow.LiveWindowSendable;
|
||||
import edu.wpi.first.wpilibj.smartdashboard.SendableBuilder;
|
||||
|
||||
/**
|
||||
* Analog output class.
|
||||
*/
|
||||
public class AnalogOutput extends SensorBase implements LiveWindowSendable {
|
||||
public class AnalogOutput extends SendableBase implements Sendable {
|
||||
private int m_port;
|
||||
private int m_channel;
|
||||
|
||||
@@ -28,20 +25,22 @@ public class AnalogOutput extends SensorBase implements LiveWindowSendable {
|
||||
* @param channel The channel number to represent.
|
||||
*/
|
||||
public AnalogOutput(final int channel) {
|
||||
checkAnalogOutputChannel(channel);
|
||||
SensorBase.checkAnalogOutputChannel(channel);
|
||||
m_channel = channel;
|
||||
|
||||
final int portHandle = AnalogJNI.getPort((byte) channel);
|
||||
m_port = AnalogJNI.initializeAnalogOutputPort(portHandle);
|
||||
|
||||
LiveWindow.addSensor("AnalogOutput", channel, this);
|
||||
HAL.report(tResourceType.kResourceType_AnalogOutput, channel);
|
||||
setName("AnalogOutput", channel);
|
||||
}
|
||||
|
||||
/**
|
||||
* Channel destructor.
|
||||
*/
|
||||
@Override
|
||||
public void free() {
|
||||
super.free();
|
||||
AnalogJNI.freeAnalogOutputPort(m_port);
|
||||
m_port = 0;
|
||||
m_channel = 0;
|
||||
@@ -62,44 +61,9 @@ public class AnalogOutput extends SensorBase implements LiveWindowSendable {
|
||||
return AnalogJNI.getAnalogOutput(m_port);
|
||||
}
|
||||
|
||||
/*
|
||||
* Live Window code, only does anything if live window is activated.
|
||||
*/
|
||||
@Override
|
||||
public String getSmartDashboardType() {
|
||||
return "Analog Output";
|
||||
}
|
||||
|
||||
private NetworkTableEntry m_valueEntry;
|
||||
|
||||
@Override
|
||||
public void initTable(NetworkTable subtable) {
|
||||
if (subtable != null) {
|
||||
m_valueEntry = subtable.getEntry("Value");
|
||||
updateTable();
|
||||
} else {
|
||||
m_valueEntry = null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateTable() {
|
||||
if (m_valueEntry != null) {
|
||||
m_valueEntry.setDouble(getVoltage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Analog Channels don't have to do anything special when entering the LiveWindow. {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public void startLiveWindowMode() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Analog Channels don't have to do anything special when exiting the LiveWindow. {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public void stopLiveWindowMode() {
|
||||
public void initSendable(SendableBuilder builder) {
|
||||
builder.setSmartDashboardType("Analog Output");
|
||||
builder.addDoubleProperty("Value", this::getVoltage, this::setVoltage);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,17 +7,15 @@
|
||||
|
||||
package edu.wpi.first.wpilibj;
|
||||
|
||||
import edu.wpi.first.networktables.NetworkTable;
|
||||
import edu.wpi.first.networktables.NetworkTableEntry;
|
||||
import edu.wpi.first.wpilibj.interfaces.Potentiometer;
|
||||
import edu.wpi.first.wpilibj.livewindow.LiveWindowSendable;
|
||||
import edu.wpi.first.wpilibj.smartdashboard.SendableBuilder;
|
||||
|
||||
/**
|
||||
* Class for reading analog potentiometers. Analog potentiometers read in an analog voltage that
|
||||
* corresponds to a position. The position is in whichever units you choose, by way of the scaling
|
||||
* and offset constants passed to the constructor.
|
||||
*/
|
||||
public class AnalogPotentiometer implements Potentiometer, LiveWindowSendable {
|
||||
public class AnalogPotentiometer extends SensorBase implements Potentiometer, Sendable {
|
||||
private AnalogInput m_analogInput;
|
||||
private boolean m_initAnalogInput;
|
||||
private double m_fullRange;
|
||||
@@ -40,6 +38,7 @@ public class AnalogPotentiometer implements Potentiometer, LiveWindowSendable {
|
||||
public AnalogPotentiometer(final int channel, double fullRange, double offset) {
|
||||
this(new AnalogInput(channel), fullRange, offset);
|
||||
m_initAnalogInput = true;
|
||||
addChild(m_analogInput);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -56,6 +55,7 @@ public class AnalogPotentiometer implements Potentiometer, LiveWindowSendable {
|
||||
* @param offset The offset to add to the scaled value for controlling the zero value
|
||||
*/
|
||||
public AnalogPotentiometer(final AnalogInput input, double fullRange, double offset) {
|
||||
setName("AnalogPotentiometer", input.getChannel());
|
||||
m_analogInput = input;
|
||||
m_initAnalogInput = false;
|
||||
|
||||
@@ -118,6 +118,9 @@ public class AnalogPotentiometer implements Potentiometer, LiveWindowSendable {
|
||||
*/
|
||||
@Override
|
||||
public double get() {
|
||||
if (m_analogInput == null) {
|
||||
return m_offset;
|
||||
}
|
||||
return (m_analogInput.getVoltage() / ControllerPower.getVoltage5V()) * m_fullRange + m_offset;
|
||||
}
|
||||
|
||||
@@ -144,56 +147,23 @@ public class AnalogPotentiometer implements Potentiometer, LiveWindowSendable {
|
||||
return get();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Live Window code, only does anything if live window is activated.
|
||||
*/
|
||||
@Override
|
||||
public String getSmartDashboardType() {
|
||||
return "Analog Input";
|
||||
}
|
||||
|
||||
private NetworkTableEntry m_valueEntry;
|
||||
|
||||
@Override
|
||||
public void initTable(NetworkTable subtable) {
|
||||
if (subtable != null) {
|
||||
m_valueEntry = subtable.getEntry("Value");
|
||||
updateTable();
|
||||
} else {
|
||||
m_valueEntry = null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateTable() {
|
||||
if (m_valueEntry != null) {
|
||||
m_valueEntry.setDouble(get());
|
||||
public void initSendable(SendableBuilder builder) {
|
||||
if (m_analogInput != null) {
|
||||
m_analogInput.initSendable(builder);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Frees this resource.
|
||||
*/
|
||||
@Override
|
||||
public void free() {
|
||||
super.free();
|
||||
if (m_initAnalogInput) {
|
||||
m_analogInput.free();
|
||||
m_analogInput = null;
|
||||
m_initAnalogInput = false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Analog Channels don't have to do anything special when entering the LiveWindow. {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public void startLiveWindowMode() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Analog Channels don't have to do anything special when exiting the LiveWindow. {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public void stopLiveWindowMode() {
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,12 +14,13 @@ import edu.wpi.first.wpilibj.AnalogTriggerOutput.AnalogTriggerType;
|
||||
import edu.wpi.first.wpilibj.hal.AnalogJNI;
|
||||
import edu.wpi.first.wpilibj.hal.FRCNetComm.tResourceType;
|
||||
import edu.wpi.first.wpilibj.hal.HAL;
|
||||
import edu.wpi.first.wpilibj.smartdashboard.SendableBuilder;
|
||||
import edu.wpi.first.wpilibj.util.BoundaryException;
|
||||
|
||||
/**
|
||||
* Class for creating and configuring Analog Triggers.
|
||||
*/
|
||||
public class AnalogTrigger {
|
||||
public class AnalogTrigger extends SensorBase implements Sendable {
|
||||
|
||||
/**
|
||||
* Exceptions dealing with improper operation of the Analog trigger.
|
||||
@@ -53,6 +54,7 @@ public class AnalogTrigger {
|
||||
public AnalogTrigger(final int channel) {
|
||||
this(new AnalogInput(channel));
|
||||
m_ownsAnalog = true;
|
||||
addChild(m_analogInput);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -71,12 +73,15 @@ public class AnalogTrigger {
|
||||
m_index = index.asIntBuffer().get(0);
|
||||
|
||||
HAL.report(tResourceType.kResourceType_AnalogTrigger, channel.getChannel());
|
||||
setName("AnalogTrigger", channel.getChannel());
|
||||
}
|
||||
|
||||
/**
|
||||
* Release the resources used by this object.
|
||||
*/
|
||||
@Override
|
||||
public void free() {
|
||||
super.free();
|
||||
AnalogJNI.cleanAnalogTrigger(m_port);
|
||||
m_port = 0;
|
||||
if (m_ownsAnalog && m_analogInput != null) {
|
||||
@@ -173,4 +178,11 @@ public class AnalogTrigger {
|
||||
public AnalogTriggerOutput createOutput(AnalogTriggerType type) {
|
||||
return new AnalogTriggerOutput(this, type);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initSendable(SendableBuilder builder) {
|
||||
if (m_ownsAnalog) {
|
||||
m_analogInput.initSendable(builder);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@ package edu.wpi.first.wpilibj;
|
||||
import edu.wpi.first.wpilibj.hal.AnalogJNI;
|
||||
import edu.wpi.first.wpilibj.hal.FRCNetComm.tResourceType;
|
||||
import edu.wpi.first.wpilibj.hal.HAL;
|
||||
import edu.wpi.first.wpilibj.smartdashboard.SendableBuilder;
|
||||
|
||||
import static java.util.Objects.requireNonNull;
|
||||
|
||||
@@ -77,15 +78,6 @@ public class AnalogTriggerOutput extends DigitalSource {
|
||||
trigger.getIndex(), outputType.value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Frees the resources for this output.
|
||||
*/
|
||||
public void free() {
|
||||
if (m_interrupt != 0) {
|
||||
cancelInterrupts();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the state of the analog trigger output.
|
||||
*
|
||||
@@ -130,4 +122,8 @@ public class AnalogTriggerOutput extends DigitalSource {
|
||||
this.value = value;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initSendable(SendableBuilder builder) {
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,21 +7,18 @@
|
||||
|
||||
package edu.wpi.first.wpilibj;
|
||||
|
||||
import edu.wpi.first.networktables.NetworkTable;
|
||||
import edu.wpi.first.networktables.NetworkTableEntry;
|
||||
import edu.wpi.first.wpilibj.hal.AccelerometerJNI;
|
||||
import edu.wpi.first.wpilibj.hal.FRCNetComm.tResourceType;
|
||||
import edu.wpi.first.wpilibj.hal.HAL;
|
||||
import edu.wpi.first.wpilibj.interfaces.Accelerometer;
|
||||
import edu.wpi.first.wpilibj.livewindow.LiveWindow;
|
||||
import edu.wpi.first.wpilibj.livewindow.LiveWindowSendable;
|
||||
import edu.wpi.first.wpilibj.smartdashboard.SendableBuilder;
|
||||
|
||||
/**
|
||||
* Built-in accelerometer.
|
||||
*
|
||||
* <p>This class allows access to the roboRIO's internal accelerometer.
|
||||
*/
|
||||
public class BuiltInAccelerometer implements Accelerometer, LiveWindowSendable {
|
||||
public class BuiltInAccelerometer extends SensorBase implements Accelerometer, Sendable {
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
@@ -30,7 +27,7 @@ public class BuiltInAccelerometer implements Accelerometer, LiveWindowSendable {
|
||||
public BuiltInAccelerometer(Range range) {
|
||||
setRange(range);
|
||||
HAL.report(tResourceType.kResourceType_Accelerometer, 0, 0, "Built-in accelerometer");
|
||||
LiveWindow.addSensor("BuiltInAccel", 0, this);
|
||||
setName("BuiltInAccel", 0);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -94,49 +91,10 @@ public class BuiltInAccelerometer implements Accelerometer, LiveWindowSendable {
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSmartDashboardType() {
|
||||
return "3AxisAccelerometer";
|
||||
}
|
||||
|
||||
@SuppressWarnings("MemberName")
|
||||
private NetworkTableEntry m_xEntry;
|
||||
@SuppressWarnings("MemberName")
|
||||
private NetworkTableEntry m_yEntry;
|
||||
@SuppressWarnings("MemberName")
|
||||
private NetworkTableEntry m_zEntry;
|
||||
|
||||
@Override
|
||||
public void initTable(NetworkTable subtable) {
|
||||
if (subtable != null) {
|
||||
m_xEntry = subtable.getEntry("X");
|
||||
m_yEntry = subtable.getEntry("Y");
|
||||
m_zEntry = subtable.getEntry("Z");
|
||||
updateTable();
|
||||
} else {
|
||||
m_xEntry = null;
|
||||
m_yEntry = null;
|
||||
m_zEntry = null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateTable() {
|
||||
if (m_xEntry != null) {
|
||||
m_xEntry.setDouble(getX());
|
||||
}
|
||||
if (m_yEntry != null) {
|
||||
m_yEntry.setDouble(getY());
|
||||
}
|
||||
if (m_zEntry != null) {
|
||||
m_zEntry.setDouble(getZ());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void startLiveWindowMode() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stopLiveWindowMode() {
|
||||
public void initSendable(SendableBuilder builder) {
|
||||
builder.setSmartDashboardType("3AxisAccelerometer");
|
||||
builder.addDoubleProperty("X", this::getX, null);
|
||||
builder.addDoubleProperty("Y", this::getY, null);
|
||||
builder.addDoubleProperty("Z", this::getZ, null);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,13 +7,10 @@
|
||||
|
||||
package edu.wpi.first.wpilibj;
|
||||
|
||||
import edu.wpi.first.networktables.EntryListenerFlags;
|
||||
import edu.wpi.first.networktables.NetworkTable;
|
||||
import edu.wpi.first.networktables.NetworkTableEntry;
|
||||
import edu.wpi.first.wpilibj.hal.CompressorJNI;
|
||||
import edu.wpi.first.wpilibj.hal.FRCNetComm.tResourceType;
|
||||
import edu.wpi.first.wpilibj.hal.HAL;
|
||||
import edu.wpi.first.wpilibj.livewindow.LiveWindowSendable;
|
||||
import edu.wpi.first.wpilibj.smartdashboard.SendableBuilder;
|
||||
|
||||
/**
|
||||
* Class for operating a compressor connected to a PCM (Pneumatic Control Module). The PCM will
|
||||
@@ -26,7 +23,7 @@ import edu.wpi.first.wpilibj.livewindow.LiveWindowSendable;
|
||||
* the safety provided by using the pressure switch and closed loop control. You can only turn off
|
||||
* closed loop control, thereby stopping the compressor from operating.
|
||||
*/
|
||||
public class Compressor extends SensorBase implements LiveWindowSendable {
|
||||
public class Compressor extends SendableBase implements Sendable {
|
||||
private int m_compressorHandle;
|
||||
private byte m_module;
|
||||
|
||||
@@ -42,6 +39,7 @@ public class Compressor extends SensorBase implements LiveWindowSendable {
|
||||
m_compressorHandle = CompressorJNI.initializeCompressor((byte) module);
|
||||
|
||||
HAL.report(tResourceType.kResourceType_Compressor, module);
|
||||
setName("Compressor", module);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -51,7 +49,7 @@ public class Compressor extends SensorBase implements LiveWindowSendable {
|
||||
* specifying the CAN ID.}
|
||||
*/
|
||||
public Compressor() {
|
||||
this(getDefaultSolenoidModule());
|
||||
this(SensorBase.getDefaultSolenoidModule());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -193,54 +191,15 @@ public class Compressor extends SensorBase implements LiveWindowSendable {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void startLiveWindowMode() {
|
||||
if (m_enabledEntry != null) {
|
||||
m_enabledListener = m_enabledEntry.addListener((event) -> {
|
||||
if (event.value.getBoolean()) {
|
||||
start();
|
||||
} else {
|
||||
stop();
|
||||
}
|
||||
}, EntryListenerFlags.kImmediate | EntryListenerFlags.kNew | EntryListenerFlags.kUpdate);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stopLiveWindowMode() {
|
||||
if (m_enabledEntry != null) {
|
||||
m_enabledEntry.removeListener(m_enabledListener);
|
||||
m_enabledListener = 0;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSmartDashboardType() {
|
||||
return "Compressor";
|
||||
}
|
||||
|
||||
private NetworkTableEntry m_enabledEntry;
|
||||
private NetworkTableEntry m_pressureSwitchEntry;
|
||||
private int m_enabledListener;
|
||||
|
||||
@Override
|
||||
public void initTable(NetworkTable subtable) {
|
||||
if (subtable != null) {
|
||||
m_enabledEntry = subtable.getEntry("Enabled");
|
||||
m_pressureSwitchEntry = subtable.getEntry("Pressure Switch");
|
||||
updateTable();
|
||||
} else {
|
||||
m_enabledEntry = null;
|
||||
m_pressureSwitchEntry = null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateTable() {
|
||||
if (m_enabledEntry != null) {
|
||||
m_enabledEntry.setBoolean(enabled());
|
||||
}
|
||||
if (m_pressureSwitchEntry != null) {
|
||||
m_pressureSwitchEntry.setBoolean(getPressureSwitchValue());
|
||||
}
|
||||
public void initSendable(SendableBuilder builder) {
|
||||
builder.setSmartDashboardType("Compressor");
|
||||
builder.addBooleanProperty("Enabled", this::enabled, (value) -> {
|
||||
if (value) {
|
||||
start();
|
||||
} else {
|
||||
stop();
|
||||
}
|
||||
});
|
||||
builder.addBooleanProperty("Pressure switch", this::getPressureSwitchValue, null);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,13 +10,11 @@ package edu.wpi.first.wpilibj;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.ByteOrder;
|
||||
|
||||
import edu.wpi.first.networktables.NetworkTable;
|
||||
import edu.wpi.first.networktables.NetworkTableEntry;
|
||||
import edu.wpi.first.wpilibj.AnalogTriggerOutput.AnalogTriggerType;
|
||||
import edu.wpi.first.wpilibj.hal.CounterJNI;
|
||||
import edu.wpi.first.wpilibj.hal.FRCNetComm.tResourceType;
|
||||
import edu.wpi.first.wpilibj.hal.HAL;
|
||||
import edu.wpi.first.wpilibj.livewindow.LiveWindowSendable;
|
||||
import edu.wpi.first.wpilibj.smartdashboard.SendableBuilder;
|
||||
|
||||
import static java.util.Objects.requireNonNull;
|
||||
|
||||
@@ -30,7 +28,7 @@ import static java.util.Objects.requireNonNull;
|
||||
* <p>All counters will immediately start counting - reset() them if you need them to be zeroed
|
||||
* before use.
|
||||
*/
|
||||
public class Counter extends SensorBase implements CounterBase, LiveWindowSendable, PIDSource {
|
||||
public class Counter extends SensorBase implements CounterBase, Sendable, PIDSource {
|
||||
|
||||
/**
|
||||
* Mode determines how and what the counter counts.
|
||||
@@ -88,6 +86,7 @@ public class Counter extends SensorBase implements CounterBase, LiveWindowSendab
|
||||
setMaxPeriod(.5);
|
||||
|
||||
HAL.report(tResourceType.kResourceType_Counter, m_index, mode.value);
|
||||
setName("Counter", m_index);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -183,6 +182,7 @@ public class Counter extends SensorBase implements CounterBase, LiveWindowSendab
|
||||
|
||||
@Override
|
||||
public void free() {
|
||||
super.free();
|
||||
setUpdateWhenEmpty(true);
|
||||
|
||||
clearUpSource();
|
||||
@@ -213,6 +213,7 @@ public class Counter extends SensorBase implements CounterBase, LiveWindowSendab
|
||||
public void setUpSource(int channel) {
|
||||
setUpSource(new DigitalInput(channel));
|
||||
m_allocatedUpSource = true;
|
||||
addChild(m_upSource);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -279,6 +280,7 @@ public class Counter extends SensorBase implements CounterBase, LiveWindowSendab
|
||||
public void setDownSource(int channel) {
|
||||
setDownSource(new DigitalInput(channel));
|
||||
m_allocatedDownSource = true;
|
||||
addChild(m_downSource);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -553,34 +555,8 @@ public class Counter extends SensorBase implements CounterBase, LiveWindowSendab
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSmartDashboardType() {
|
||||
return "Counter";
|
||||
}
|
||||
|
||||
private NetworkTableEntry m_valueEntry;
|
||||
|
||||
@Override
|
||||
public void initTable(NetworkTable subtable) {
|
||||
if (subtable != null) {
|
||||
m_valueEntry = subtable.getEntry("Value");
|
||||
updateTable();
|
||||
} else {
|
||||
m_valueEntry = null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateTable() {
|
||||
if (m_valueEntry != null) {
|
||||
m_valueEntry.setDouble(get());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void startLiveWindowMode() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stopLiveWindowMode() {
|
||||
public void initSendable(SendableBuilder builder) {
|
||||
builder.setSmartDashboardType("Counter");
|
||||
builder.addDoubleProperty("Value", this::get, null);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@ import java.util.concurrent.locks.ReentrantLock;
|
||||
|
||||
import edu.wpi.first.wpilibj.hal.DigitalGlitchFilterJNI;
|
||||
import edu.wpi.first.wpilibj.hal.FRCNetComm.tResourceType;
|
||||
import edu.wpi.first.wpilibj.smartdashboard.SendableBuilder;
|
||||
import edu.wpi.first.wpilibj.hal.HAL;
|
||||
|
||||
/**
|
||||
@@ -35,6 +36,7 @@ public class DigitalGlitchFilter extends SensorBase {
|
||||
m_filterAllocated[index] = true;
|
||||
HAL.report(tResourceType.kResourceType_DigitalFilter,
|
||||
m_channelIndex, 0);
|
||||
setName("DigitalGlitchFilter", index);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -43,6 +45,7 @@ public class DigitalGlitchFilter extends SensorBase {
|
||||
* Free the resources used by this object.
|
||||
*/
|
||||
public void free() {
|
||||
super.free();
|
||||
if (m_channelIndex >= 0) {
|
||||
synchronized (m_mutex) {
|
||||
m_filterAllocated[m_channelIndex] = false;
|
||||
@@ -170,6 +173,10 @@ public class DigitalGlitchFilter extends SensorBase {
|
||||
/ (long) (kSystemClockTicksPerMicrosecond / 4);
|
||||
}
|
||||
|
||||
@SuppressWarnings("PMD.UnusedFormalParameter")
|
||||
public void initSendable(SendableBuilder builder) {
|
||||
}
|
||||
|
||||
private int m_channelIndex = -1;
|
||||
private static final Lock m_mutex = new ReentrantLock(true);
|
||||
private static final boolean[] m_filterAllocated = new boolean[3];
|
||||
|
||||
@@ -7,13 +7,10 @@
|
||||
|
||||
package edu.wpi.first.wpilibj;
|
||||
|
||||
import edu.wpi.first.networktables.NetworkTable;
|
||||
import edu.wpi.first.networktables.NetworkTableEntry;
|
||||
import edu.wpi.first.wpilibj.hal.DIOJNI;
|
||||
import edu.wpi.first.wpilibj.hal.FRCNetComm.tResourceType;
|
||||
import edu.wpi.first.wpilibj.hal.HAL;
|
||||
import edu.wpi.first.wpilibj.livewindow.LiveWindow;
|
||||
import edu.wpi.first.wpilibj.livewindow.LiveWindowSendable;
|
||||
import edu.wpi.first.wpilibj.smartdashboard.SendableBuilder;
|
||||
|
||||
/**
|
||||
* Class to read a digital input. This class will read digital inputs and return the current value
|
||||
@@ -21,7 +18,7 @@ import edu.wpi.first.wpilibj.livewindow.LiveWindowSendable;
|
||||
* elsewhere will automatically allocate digital inputs and outputs as required. This class is only
|
||||
* for devices like switches etc. that aren't implemented anywhere else.
|
||||
*/
|
||||
public class DigitalInput extends DigitalSource implements LiveWindowSendable {
|
||||
public class DigitalInput extends DigitalSource implements Sendable {
|
||||
private int m_channel = 0;
|
||||
private int m_handle = 0;
|
||||
|
||||
@@ -36,14 +33,15 @@ public class DigitalInput extends DigitalSource implements LiveWindowSendable {
|
||||
|
||||
m_handle = DIOJNI.initializeDIOPort(DIOJNI.getPort((byte) channel), true);
|
||||
|
||||
LiveWindow.addSensor("DigitalInput", channel, this);
|
||||
HAL.report(tResourceType.kResourceType_DigitalInput, channel);
|
||||
setName("DigitalInput", channel);
|
||||
}
|
||||
|
||||
/**
|
||||
* Frees the resources for this output.
|
||||
*/
|
||||
public void free() {
|
||||
super.free();
|
||||
if (m_interrupt != 0) {
|
||||
cancelInterrupts();
|
||||
}
|
||||
@@ -102,37 +100,8 @@ public class DigitalInput extends DigitalSource implements LiveWindowSendable {
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSmartDashboardType() {
|
||||
return "Digital Input";
|
||||
}
|
||||
|
||||
private NetworkTableEntry m_valueEntry;
|
||||
|
||||
@Override
|
||||
public void initTable(NetworkTable subtable) {
|
||||
if (subtable != null) {
|
||||
m_valueEntry = subtable.getEntry("Value");
|
||||
updateTable();
|
||||
} else {
|
||||
m_valueEntry = null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void updateTable() {
|
||||
if (m_valueEntry != null) {
|
||||
m_valueEntry.setBoolean(get());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void startLiveWindowMode() {
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void stopLiveWindowMode() {
|
||||
public void initSendable(SendableBuilder builder) {
|
||||
builder.setSmartDashboardType("Digital Input");
|
||||
builder.addBooleanProperty("Value", this::get, null);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,19 +7,16 @@
|
||||
|
||||
package edu.wpi.first.wpilibj;
|
||||
|
||||
import edu.wpi.first.networktables.EntryListenerFlags;
|
||||
import edu.wpi.first.networktables.NetworkTable;
|
||||
import edu.wpi.first.networktables.NetworkTableEntry;
|
||||
import edu.wpi.first.wpilibj.hal.DIOJNI;
|
||||
import edu.wpi.first.wpilibj.hal.FRCNetComm.tResourceType;
|
||||
import edu.wpi.first.wpilibj.hal.HAL;
|
||||
import edu.wpi.first.wpilibj.livewindow.LiveWindowSendable;
|
||||
import edu.wpi.first.wpilibj.smartdashboard.SendableBuilder;
|
||||
|
||||
/**
|
||||
* Class to write digital outputs. This class will write digital outputs. Other devices that are
|
||||
* implemented elsewhere will automatically allocate digital inputs and outputs as required.
|
||||
*/
|
||||
public class DigitalOutput extends DigitalSource implements LiveWindowSendable {
|
||||
public class DigitalOutput extends SendableBase implements Sendable {
|
||||
|
||||
private static final int invalidPwmGenerator = 0;
|
||||
private int m_pwmGenerator = invalidPwmGenerator;
|
||||
@@ -35,12 +32,13 @@ public class DigitalOutput extends DigitalSource implements LiveWindowSendable {
|
||||
* the MXP
|
||||
*/
|
||||
public DigitalOutput(int channel) {
|
||||
checkDigitalChannel(channel);
|
||||
SensorBase.checkDigitalChannel(channel);
|
||||
m_channel = channel;
|
||||
|
||||
m_handle = DIOJNI.initializeDIOPort(DIOJNI.getPort((byte) channel), false);
|
||||
|
||||
HAL.report(tResourceType.kResourceType_DigitalOutput, channel);
|
||||
setName("DigitalOutput", channel);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -48,6 +46,7 @@ public class DigitalOutput extends DigitalSource implements LiveWindowSendable {
|
||||
*/
|
||||
@Override
|
||||
public void free() {
|
||||
super.free();
|
||||
// disable the pwm only if we have allocated it
|
||||
if (m_pwmGenerator != invalidPwmGenerator) {
|
||||
disablePWM();
|
||||
@@ -79,7 +78,6 @@ public class DigitalOutput extends DigitalSource implements LiveWindowSendable {
|
||||
*
|
||||
* @return The GPIO channel number.
|
||||
*/
|
||||
@Override
|
||||
public int getChannel() {
|
||||
return m_channel;
|
||||
}
|
||||
@@ -146,7 +144,7 @@ public class DigitalOutput extends DigitalSource implements LiveWindowSendable {
|
||||
return;
|
||||
}
|
||||
// Disable the output by routing to a dead bit.
|
||||
DIOJNI.setDigitalPWMOutputChannel(m_pwmGenerator, kDigitalChannels);
|
||||
DIOJNI.setDigitalPWMOutputChannel(m_pwmGenerator, SensorBase.kDigitalChannels);
|
||||
DIOJNI.freeDigitalPWM(m_pwmGenerator);
|
||||
m_pwmGenerator = invalidPwmGenerator;
|
||||
}
|
||||
@@ -167,76 +165,9 @@ public class DigitalOutput extends DigitalSource implements LiveWindowSendable {
|
||||
DIOJNI.setDigitalPWMDutyCycle(m_pwmGenerator, dutyCycle);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the analog trigger type.
|
||||
*
|
||||
* @return false
|
||||
*/
|
||||
@Override
|
||||
public int getAnalogTriggerTypeForRouting() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Is this an analog trigger.
|
||||
*
|
||||
* @return true if this is an analog trigger
|
||||
*/
|
||||
@Override
|
||||
public boolean isAnalogTrigger() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the HAL Port Handle.
|
||||
*
|
||||
* @return The HAL Handle to the specified source.
|
||||
*/
|
||||
@Override
|
||||
public int getPortHandleForRouting() {
|
||||
return m_handle;
|
||||
}
|
||||
|
||||
/*
|
||||
* Live Window code, only does anything if live window is activated.
|
||||
*/
|
||||
@Override
|
||||
public String getSmartDashboardType() {
|
||||
return "Digital Output";
|
||||
}
|
||||
|
||||
private NetworkTableEntry m_valueEntry;
|
||||
private int m_valueListener;
|
||||
|
||||
|
||||
@Override
|
||||
public void initTable(NetworkTable subtable) {
|
||||
if (subtable != null) {
|
||||
m_valueEntry = subtable.getEntry("Value");
|
||||
updateTable();
|
||||
} else {
|
||||
m_valueEntry = null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void updateTable() {
|
||||
// TODO: Put current value.
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void startLiveWindowMode() {
|
||||
m_valueListener = m_valueEntry.addListener((event) -> set(event.value.getBoolean()),
|
||||
EntryListenerFlags.kImmediate | EntryListenerFlags.kNew | EntryListenerFlags.kUpdate);
|
||||
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void stopLiveWindowMode() {
|
||||
m_valueEntry.removeListener(m_valueListener);
|
||||
m_valueListener = 0;
|
||||
public void initSendable(SendableBuilder builder) {
|
||||
builder.setSmartDashboardType("Digital Output");
|
||||
builder.addBooleanProperty("Value", this::get, this::set);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,14 +7,10 @@
|
||||
|
||||
package edu.wpi.first.wpilibj;
|
||||
|
||||
import edu.wpi.first.networktables.EntryListenerFlags;
|
||||
import edu.wpi.first.networktables.NetworkTable;
|
||||
import edu.wpi.first.networktables.NetworkTableEntry;
|
||||
import edu.wpi.first.wpilibj.hal.FRCNetComm.tResourceType;
|
||||
import edu.wpi.first.wpilibj.hal.HAL;
|
||||
import edu.wpi.first.wpilibj.hal.SolenoidJNI;
|
||||
import edu.wpi.first.wpilibj.livewindow.LiveWindow;
|
||||
import edu.wpi.first.wpilibj.livewindow.LiveWindowSendable;
|
||||
import edu.wpi.first.wpilibj.smartdashboard.SendableBuilder;
|
||||
|
||||
/**
|
||||
* DoubleSolenoid class for running 2 channels of high voltage Digital Output on the PCM.
|
||||
@@ -22,7 +18,7 @@ import edu.wpi.first.wpilibj.livewindow.LiveWindowSendable;
|
||||
* <p>The DoubleSolenoid class is typically used for pneumatics solenoids that have two positions
|
||||
* controlled by two separate channels.
|
||||
*/
|
||||
public class DoubleSolenoid extends SolenoidBase implements LiveWindowSendable {
|
||||
public class DoubleSolenoid extends SolenoidBase implements Sendable {
|
||||
|
||||
/**
|
||||
* Possible values for a DoubleSolenoid.
|
||||
@@ -45,7 +41,7 @@ public class DoubleSolenoid extends SolenoidBase implements LiveWindowSendable {
|
||||
* @param reverseChannel The reverse channel number on the PCM (0..7).
|
||||
*/
|
||||
public DoubleSolenoid(final int forwardChannel, final int reverseChannel) {
|
||||
this(getDefaultSolenoidModule(), forwardChannel, reverseChannel);
|
||||
this(SensorBase.getDefaultSolenoidModule(), forwardChannel, reverseChannel);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -59,9 +55,9 @@ public class DoubleSolenoid extends SolenoidBase implements LiveWindowSendable {
|
||||
final int reverseChannel) {
|
||||
super(moduleNumber);
|
||||
|
||||
checkSolenoidModule(m_moduleNumber);
|
||||
checkSolenoidChannel(forwardChannel);
|
||||
checkSolenoidChannel(reverseChannel);
|
||||
SensorBase.checkSolenoidModule(m_moduleNumber);
|
||||
SensorBase.checkSolenoidChannel(forwardChannel);
|
||||
SensorBase.checkSolenoidChannel(reverseChannel);
|
||||
|
||||
int portHandle = SolenoidJNI.getPortWithModule((byte) m_moduleNumber, (byte) forwardChannel);
|
||||
m_forwardHandle = SolenoidJNI.initializeSolenoidPort(portHandle);
|
||||
@@ -84,13 +80,15 @@ public class DoubleSolenoid extends SolenoidBase implements LiveWindowSendable {
|
||||
m_moduleNumber);
|
||||
HAL.report(tResourceType.kResourceType_Solenoid, reverseChannel,
|
||||
m_moduleNumber);
|
||||
LiveWindow.addActuator("DoubleSolenoid", m_moduleNumber, forwardChannel, this);
|
||||
setName("DoubleSolenoid", m_moduleNumber, forwardChannel);
|
||||
}
|
||||
|
||||
/**
|
||||
* Destructor.
|
||||
*/
|
||||
@Override
|
||||
public synchronized void free() {
|
||||
super.free();
|
||||
SolenoidJNI.freeSolenoidPort(m_forwardHandle);
|
||||
SolenoidJNI.freeSolenoidPort(m_reverseHandle);
|
||||
super.free();
|
||||
@@ -169,52 +167,18 @@ public class DoubleSolenoid extends SolenoidBase implements LiveWindowSendable {
|
||||
return (blackList & m_reverseMask) != 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Live Window code, only does anything if live window is activated.
|
||||
*/
|
||||
public String getSmartDashboardType() {
|
||||
return "Double Solenoid";
|
||||
}
|
||||
|
||||
private NetworkTableEntry m_valueEntry;
|
||||
private int m_valueListener;
|
||||
|
||||
@Override
|
||||
public void initTable(NetworkTable subtable) {
|
||||
if (subtable != null) {
|
||||
m_valueEntry = subtable.getEntry("Value");
|
||||
updateTable();
|
||||
} else {
|
||||
m_valueEntry = null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateTable() {
|
||||
if (m_valueEntry != null) {
|
||||
m_valueEntry.setString(get().name().substring(1));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void startLiveWindowMode() {
|
||||
set(Value.kOff); // Stop for safety
|
||||
m_valueListener = m_valueEntry.addListener((event) -> {
|
||||
String value = event.value.getString();
|
||||
if ("Reverse".equals(value)) {
|
||||
set(Value.kReverse);
|
||||
} else if ("Forward".equals(value)) {
|
||||
public void initSendable(SendableBuilder builder) {
|
||||
builder.setSmartDashboardType("Double Solenoid");
|
||||
builder.setSafeState(() -> set(Value.kOff));
|
||||
builder.addStringProperty("Value", () -> get().name().substring(1), (value) -> {
|
||||
if ("Forward".equals(value)) {
|
||||
set(Value.kForward);
|
||||
} else if ("Reverse".equals(value)) {
|
||||
set(Value.kReverse);
|
||||
} else {
|
||||
set(Value.kOff);
|
||||
}
|
||||
}, EntryListenerFlags.kImmediate | EntryListenerFlags.kNew | EntryListenerFlags.kUpdate);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stopLiveWindowMode() {
|
||||
set(Value.kOff); // Stop for safety
|
||||
m_valueEntry.removeListener(m_valueListener);
|
||||
m_valueListener = 0;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,13 +7,10 @@
|
||||
|
||||
package edu.wpi.first.wpilibj;
|
||||
|
||||
import edu.wpi.first.networktables.NetworkTable;
|
||||
import edu.wpi.first.networktables.NetworkTableEntry;
|
||||
import edu.wpi.first.wpilibj.hal.EncoderJNI;
|
||||
import edu.wpi.first.wpilibj.hal.FRCNetComm.tResourceType;
|
||||
import edu.wpi.first.wpilibj.hal.HAL;
|
||||
import edu.wpi.first.wpilibj.livewindow.LiveWindow;
|
||||
import edu.wpi.first.wpilibj.livewindow.LiveWindowSendable;
|
||||
import edu.wpi.first.wpilibj.smartdashboard.SendableBuilder;
|
||||
import edu.wpi.first.wpilibj.util.AllocationException;
|
||||
|
||||
import static java.util.Objects.requireNonNull;
|
||||
@@ -31,7 +28,7 @@ import static java.util.Objects.requireNonNull;
|
||||
* <p>All encoders will immediately start counting - reset() them if you need them to be zeroed
|
||||
* before use.
|
||||
*/
|
||||
public class Encoder extends SensorBase implements CounterBase, PIDSource, LiveWindowSendable {
|
||||
public class Encoder extends SensorBase implements CounterBase, PIDSource, Sendable {
|
||||
|
||||
public enum IndexingType {
|
||||
kResetWhileHigh(0), kResetWhileLow(1), kResetOnFallingEdge(2), kResetOnRisingEdge(3);
|
||||
@@ -81,8 +78,9 @@ public class Encoder extends SensorBase implements CounterBase, PIDSource, LiveW
|
||||
|
||||
m_pidSource = PIDSourceType.kDisplacement;
|
||||
|
||||
HAL.report(tResourceType.kResourceType_Encoder, getFPGAIndex(), type.value);
|
||||
LiveWindow.addSensor("Encoder", m_aSource.getChannel(), this);
|
||||
int fpgaIndex = getFPGAIndex();
|
||||
HAL.report(tResourceType.kResourceType_Encoder, fpgaIndex, type.value);
|
||||
setName("Encoder", fpgaIndex);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -96,12 +94,7 @@ public class Encoder extends SensorBase implements CounterBase, PIDSource, LiveW
|
||||
* if necessary so forward represents positive values.
|
||||
*/
|
||||
public Encoder(final int channelA, final int channelB, boolean reverseDirection) {
|
||||
m_allocatedA = true;
|
||||
m_allocatedB = true;
|
||||
m_allocatedI = false;
|
||||
m_aSource = new DigitalInput(channelA);
|
||||
m_bSource = new DigitalInput(channelB);
|
||||
initEncoder(reverseDirection, EncodingType.k4X);
|
||||
this(channelA, channelB, reverseDirection, EncodingType.k4X);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -141,6 +134,8 @@ public class Encoder extends SensorBase implements CounterBase, PIDSource, LiveW
|
||||
m_allocatedI = false;
|
||||
m_aSource = new DigitalInput(channelA);
|
||||
m_bSource = new DigitalInput(channelB);
|
||||
addChild(m_aSource);
|
||||
addChild(m_bSource);
|
||||
initEncoder(reverseDirection, encodingType);
|
||||
}
|
||||
|
||||
@@ -158,13 +153,10 @@ public class Encoder extends SensorBase implements CounterBase, PIDSource, LiveW
|
||||
*/
|
||||
public Encoder(final int channelA, final int channelB, final int indexChannel,
|
||||
boolean reverseDirection) {
|
||||
m_allocatedA = true;
|
||||
m_allocatedB = true;
|
||||
this(channelA, channelB, reverseDirection);
|
||||
m_allocatedI = true;
|
||||
m_aSource = new DigitalInput(channelA);
|
||||
m_bSource = new DigitalInput(channelB);
|
||||
m_indexSource = new DigitalInput(indexChannel);
|
||||
initEncoder(reverseDirection, EncodingType.k4X);
|
||||
addChild(m_indexSource);
|
||||
setIndexSource(m_indexSource);
|
||||
}
|
||||
|
||||
@@ -195,15 +187,7 @@ public class Encoder extends SensorBase implements CounterBase, PIDSource, LiveW
|
||||
* if necessary so forward represents positive values.
|
||||
*/
|
||||
public Encoder(DigitalSource sourceA, DigitalSource sourceB, boolean reverseDirection) {
|
||||
requireNonNull(sourceA, "Digital Source A was null");
|
||||
requireNonNull(sourceB, "Digital Source B was null");
|
||||
|
||||
m_allocatedA = false;
|
||||
m_allocatedB = false;
|
||||
m_allocatedI = false;
|
||||
m_aSource = sourceA;
|
||||
m_bSource = sourceB;
|
||||
initEncoder(reverseDirection, EncodingType.k4X);
|
||||
this(sourceA, sourceB, reverseDirection, EncodingType.k4X);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -267,16 +251,9 @@ public class Encoder extends SensorBase implements CounterBase, PIDSource, LiveW
|
||||
*/
|
||||
public Encoder(DigitalSource sourceA, DigitalSource sourceB, DigitalSource indexSource,
|
||||
boolean reverseDirection) {
|
||||
requireNonNull(sourceA, "Digital Source A was null");
|
||||
requireNonNull(sourceB, "Digital Source B was null");
|
||||
|
||||
m_allocatedA = false;
|
||||
m_allocatedB = false;
|
||||
this(sourceA, sourceB, reverseDirection);
|
||||
m_allocatedI = false;
|
||||
m_aSource = sourceA;
|
||||
m_bSource = sourceB;
|
||||
m_indexSource = indexSource;
|
||||
initEncoder(reverseDirection, EncodingType.k4X);
|
||||
setIndexSource(indexSource);
|
||||
}
|
||||
|
||||
@@ -317,7 +294,9 @@ public class Encoder extends SensorBase implements CounterBase, PIDSource, LiveW
|
||||
/**
|
||||
* Free the resources used by this object.
|
||||
*/
|
||||
@Override
|
||||
public void free() {
|
||||
super.free();
|
||||
if (m_aSource != null && m_allocatedA) {
|
||||
m_aSource.free();
|
||||
m_allocatedA = false;
|
||||
@@ -456,6 +435,15 @@ public class Encoder extends SensorBase implements CounterBase, PIDSource, LiveW
|
||||
EncoderJNI.setEncoderDistancePerPulse(m_encoder, distancePerPulse);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the distance per pulse for this encoder.
|
||||
*
|
||||
* @return The scale factor that will be used to convert pulses to useful units.
|
||||
*/
|
||||
public double getDistancePerPulse() {
|
||||
return EncoderJNI.getEncoderDistancePerPulse(m_encoder);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the direction sensing for this encoder. This sets the direction sensing on the encoder so
|
||||
* that it could count in the correct software direction regardless of the mounting.
|
||||
@@ -567,52 +555,16 @@ public class Encoder extends SensorBase implements CounterBase, PIDSource, LiveW
|
||||
source.getAnalogTriggerTypeForRouting(), type.value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Live Window code, only does anything if live window is activated.
|
||||
*/
|
||||
public String getSmartDashboardType() {
|
||||
@Override
|
||||
public void initSendable(SendableBuilder builder) {
|
||||
if (EncoderJNI.getEncoderEncodingType(m_encoder) == EncodingType.k4X.value) {
|
||||
return "Quadrature Encoder";
|
||||
}
|
||||
return "Encoder";
|
||||
}
|
||||
|
||||
private NetworkTableEntry m_speedEntry;
|
||||
private NetworkTableEntry m_distanceEntry;
|
||||
private NetworkTableEntry m_distancePerTickEntry;
|
||||
|
||||
@Override
|
||||
public void initTable(NetworkTable subtable) {
|
||||
if (subtable != null) {
|
||||
m_speedEntry = subtable.getEntry("Speed");
|
||||
m_distanceEntry = subtable.getEntry("Distance");
|
||||
m_distancePerTickEntry = subtable.getEntry("Distance per Tick");
|
||||
updateTable();
|
||||
builder.setSmartDashboardType("Quadrature Encoder");
|
||||
} else {
|
||||
m_speedEntry = null;
|
||||
m_distanceEntry = null;
|
||||
m_distancePerTickEntry = null;
|
||||
builder.setSmartDashboardType("Encoder");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateTable() {
|
||||
if (m_speedEntry != null) {
|
||||
m_speedEntry.setDouble(getRate());
|
||||
}
|
||||
if (m_distanceEntry != null) {
|
||||
m_distanceEntry.setDouble(getDistance());
|
||||
}
|
||||
if (m_distancePerTickEntry != null) {
|
||||
m_distancePerTickEntry.setDouble(EncoderJNI.getEncoderDistancePerPulse(m_encoder));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void startLiveWindowMode() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stopLiveWindowMode() {
|
||||
builder.addDoubleProperty("Speed", this::getRate, null);
|
||||
builder.addDoubleProperty("Distance", this::getDistance, null);
|
||||
builder.addDoubleProperty("Distance per Tick", this::getDistancePerPulse, null);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,7 +9,7 @@ package edu.wpi.first.wpilibj;
|
||||
|
||||
import edu.wpi.first.wpilibj.hal.FRCNetComm.tResourceType;
|
||||
import edu.wpi.first.wpilibj.hal.HAL;
|
||||
import edu.wpi.first.wpilibj.livewindow.LiveWindow;
|
||||
import edu.wpi.first.wpilibj.smartdashboard.SendableBuilder;
|
||||
|
||||
/**
|
||||
* Alias for counter class. Implement the gear tooth sensor supplied by FIRST. Currently there is no
|
||||
@@ -56,7 +56,7 @@ public class GearTooth extends Counter {
|
||||
} else {
|
||||
HAL.report(tResourceType.kResourceType_GearTooth, channel, 0);
|
||||
}
|
||||
LiveWindow.addSensor("GearTooth", channel, this);
|
||||
setName("GearTooth", channel);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -70,6 +70,12 @@ public class GearTooth extends Counter {
|
||||
public GearTooth(DigitalSource source, boolean directionSensitive) {
|
||||
super(source);
|
||||
enableDirectionSensing(directionSensitive);
|
||||
if (directionSensitive) {
|
||||
HAL.report(tResourceType.kResourceType_GearTooth, source.getChannel(), 0, "D");
|
||||
} else {
|
||||
HAL.report(tResourceType.kResourceType_GearTooth, source.getChannel(), 0);
|
||||
}
|
||||
setName("GearTooth", source.getChannel());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -84,10 +90,9 @@ public class GearTooth extends Counter {
|
||||
this(source, false);
|
||||
}
|
||||
|
||||
/*
|
||||
* Live Window code, only does anything if live window is activated.
|
||||
*/
|
||||
public String getSmartDashboardType() {
|
||||
return "Gear Tooth";
|
||||
@Override
|
||||
public void initSendable(SendableBuilder builder) {
|
||||
super.initSendable(builder);
|
||||
builder.setSmartDashboardType("Gear Tooth");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,15 +7,13 @@
|
||||
|
||||
package edu.wpi.first.wpilibj;
|
||||
|
||||
import edu.wpi.first.networktables.NetworkTable;
|
||||
import edu.wpi.first.networktables.NetworkTableEntry;
|
||||
import edu.wpi.first.wpilibj.interfaces.Gyro;
|
||||
import edu.wpi.first.wpilibj.livewindow.LiveWindowSendable;
|
||||
import edu.wpi.first.wpilibj.smartdashboard.SendableBuilder;
|
||||
|
||||
/**
|
||||
* GyroBase is the common base class for Gyro implementations such as AnalogGyro.
|
||||
*/
|
||||
public abstract class GyroBase extends SensorBase implements Gyro, PIDSource, LiveWindowSendable {
|
||||
public abstract class GyroBase extends SensorBase implements Gyro, PIDSource, Sendable {
|
||||
private PIDSourceType m_pidSource = PIDSourceType.kDisplacement;
|
||||
|
||||
/**
|
||||
@@ -52,38 +50,9 @@ public abstract class GyroBase extends SensorBase implements Gyro, PIDSource, Li
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Live Window code, only does anything if live window is activated.
|
||||
*/
|
||||
@Override
|
||||
public String getSmartDashboardType() {
|
||||
return "Gyro";
|
||||
}
|
||||
|
||||
private NetworkTableEntry m_valueEntry;
|
||||
|
||||
@Override
|
||||
public void initTable(NetworkTable subtable) {
|
||||
if (subtable != null) {
|
||||
m_valueEntry = subtable.getEntry("Value");
|
||||
updateTable();
|
||||
} else {
|
||||
m_valueEntry = null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateTable() {
|
||||
if (m_valueEntry != null) {
|
||||
m_valueEntry.setDouble(getAngle());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void startLiveWindowMode() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stopLiveWindowMode() {
|
||||
public void initSendable(SendableBuilder builder) {
|
||||
builder.setSmartDashboardType("Gyro");
|
||||
builder.addDoubleProperty("Value", this::getAngle, null);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,7 +22,7 @@ import static java.util.Objects.requireNonNull;
|
||||
* <p>This class is intended to be used by sensor (and other I2C device) drivers. It probably should
|
||||
* not be used directly.
|
||||
*/
|
||||
public class I2C extends SensorBase {
|
||||
public class I2C {
|
||||
public enum Port {
|
||||
kOnboard(0), kMXP(1);
|
||||
|
||||
@@ -56,6 +56,7 @@ public class I2C extends SensorBase {
|
||||
* Destructor.
|
||||
*/
|
||||
public void free() {
|
||||
I2CJNI.i2CClose(m_port);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -45,6 +45,17 @@ public abstract class InterruptableSensorBase extends SensorBase {
|
||||
m_interrupt = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Frees the resources for this output.
|
||||
*/
|
||||
@Override
|
||||
public void free() {
|
||||
super.free();
|
||||
if (m_interrupt != 0) {
|
||||
cancelInterrupts();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* If this is an analog trigger.
|
||||
*
|
||||
|
||||
@@ -222,5 +222,6 @@ public abstract class IterativeRobotBase extends RobotBase {
|
||||
testPeriodic();
|
||||
}
|
||||
robotPeriodic();
|
||||
LiveWindow.updateValues();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,7 +9,6 @@ package edu.wpi.first.wpilibj;
|
||||
|
||||
import edu.wpi.first.wpilibj.hal.FRCNetComm.tResourceType;
|
||||
import edu.wpi.first.wpilibj.hal.HAL;
|
||||
import edu.wpi.first.wpilibj.livewindow.LiveWindow;
|
||||
|
||||
/**
|
||||
* Texas Instruments / Vex Robotics Jaguar Speed Controller as a PWM device.
|
||||
@@ -39,6 +38,6 @@ public class Jaguar extends PWMSpeedController {
|
||||
setZeroLatch();
|
||||
|
||||
HAL.report(tResourceType.kResourceType_Jaguar, getChannel());
|
||||
LiveWindow.addActuator("Jaguar", getChannel(), this);
|
||||
setName("Jaguar", getChannel());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,23 +0,0 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) 2016-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. */
|
||||
/*----------------------------------------------------------------------------*/
|
||||
|
||||
package edu.wpi.first.wpilibj;
|
||||
|
||||
|
||||
/**
|
||||
* The interface for sendable objects that gives the sendable a default name in the Smart
|
||||
* Dashboard.
|
||||
*/
|
||||
public interface NamedSendable extends Sendable {
|
||||
|
||||
/**
|
||||
* The name of the subtable.
|
||||
*
|
||||
* @return the name of the subtable of SmartDashboard that the Sendable object will use.
|
||||
*/
|
||||
String getName();
|
||||
}
|
||||
@@ -7,18 +7,14 @@
|
||||
|
||||
package edu.wpi.first.wpilibj;
|
||||
|
||||
import edu.wpi.first.networktables.EntryListenerFlags;
|
||||
import edu.wpi.first.networktables.NetworkTable;
|
||||
import edu.wpi.first.networktables.NetworkTableEntry;
|
||||
import edu.wpi.first.wpilibj.hal.FRCNetComm.tResourceType;
|
||||
import edu.wpi.first.wpilibj.hal.HAL;
|
||||
import edu.wpi.first.wpilibj.livewindow.LiveWindow;
|
||||
import edu.wpi.first.wpilibj.livewindow.LiveWindowSendable;
|
||||
import edu.wpi.first.wpilibj.smartdashboard.SendableBuilder;
|
||||
|
||||
/**
|
||||
* Nidec Brushless Motor.
|
||||
*/
|
||||
public class NidecBrushless implements SpeedController, MotorSafety, LiveWindowSendable {
|
||||
public class NidecBrushless extends SendableBase implements SpeedController, MotorSafety, Sendable {
|
||||
private final MotorSafetyHelper m_safetyHelper;
|
||||
private boolean m_isInverted = false;
|
||||
private DigitalOutput m_dio;
|
||||
@@ -41,14 +37,26 @@ public class NidecBrushless implements SpeedController, MotorSafety, LiveWindowS
|
||||
|
||||
// the dio controls the output (in PWM mode)
|
||||
m_dio = new DigitalOutput(dioChannel);
|
||||
addChild(m_dio);
|
||||
m_dio.setPWMRate(15625);
|
||||
m_dio.enablePWM(0.5);
|
||||
|
||||
// the pwm enables the controller
|
||||
m_pwm = new PWM(pwmChannel);
|
||||
addChild(m_pwm);
|
||||
|
||||
LiveWindow.addActuator("Nidec Brushless", pwmChannel, this);
|
||||
HAL.report(tResourceType.kResourceType_NidecBrushless, pwmChannel);
|
||||
setName("Nidec Brushless", pwmChannel);
|
||||
}
|
||||
|
||||
/**
|
||||
* Free the resources used by this object.
|
||||
*/
|
||||
@Override
|
||||
public void free() {
|
||||
super.free();
|
||||
m_dio.free();
|
||||
m_pwm.free();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -188,45 +196,10 @@ public class NidecBrushless implements SpeedController, MotorSafety, LiveWindowS
|
||||
return m_pwm.getChannel();
|
||||
}
|
||||
|
||||
/*
|
||||
* Live Window code, only does anything if live window is activated.
|
||||
*/
|
||||
@Override
|
||||
public String getSmartDashboardType() {
|
||||
return "Nidec Brushless";
|
||||
}
|
||||
|
||||
private NetworkTableEntry m_valueEntry;
|
||||
private int m_valueListener;
|
||||
|
||||
@Override
|
||||
public void initTable(NetworkTable subtable) {
|
||||
if (subtable != null) {
|
||||
m_valueEntry = subtable.getEntry("Value");
|
||||
updateTable();
|
||||
} else {
|
||||
m_valueEntry = null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateTable() {
|
||||
if (m_valueEntry != null) {
|
||||
m_valueEntry.setDouble(get());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void startLiveWindowMode() {
|
||||
set(0); // Stop for safety
|
||||
m_valueListener = m_valueEntry.addListener((event) -> set(event.value.getDouble()),
|
||||
EntryListenerFlags.kImmediate | EntryListenerFlags.kNew | EntryListenerFlags.kUpdate);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stopLiveWindowMode() {
|
||||
set(0); // Stop for safety
|
||||
m_valueEntry.removeListener(m_valueListener);
|
||||
m_valueListener = 0;
|
||||
public void initSendable(SendableBuilder builder) {
|
||||
builder.setSmartDashboardType("Nidec Brushless");
|
||||
builder.setSafeState(this::stopMotor);
|
||||
builder.addDoubleProperty("Value", this::get, this::set);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,11 +10,8 @@ package edu.wpi.first.wpilibj;
|
||||
import java.util.TimerTask;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
|
||||
import edu.wpi.first.networktables.EntryListenerFlags;
|
||||
import edu.wpi.first.networktables.NetworkTable;
|
||||
import edu.wpi.first.networktables.NetworkTableEntry;
|
||||
import edu.wpi.first.wpilibj.filters.LinearDigitalFilter;
|
||||
import edu.wpi.first.wpilibj.livewindow.LiveWindowSendable;
|
||||
import edu.wpi.first.wpilibj.smartdashboard.SendableBuilder;
|
||||
import edu.wpi.first.wpilibj.util.BoundaryException;
|
||||
|
||||
import static java.util.Objects.requireNonNull;
|
||||
@@ -29,7 +26,7 @@ import static java.util.Objects.requireNonNull;
|
||||
* and derivative calculations. Therefore, the sample rate affects the controller's behavior for a
|
||||
* given set of PID constants.
|
||||
*/
|
||||
public class PIDController implements PIDInterface, LiveWindowSendable, Controller {
|
||||
public class PIDController extends SendableBase implements PIDInterface, Sendable, Controller {
|
||||
|
||||
public static final double kDefaultPeriod = .05;
|
||||
private static int instances = 0;
|
||||
@@ -153,6 +150,7 @@ public class PIDController implements PIDInterface, LiveWindowSendable, Controll
|
||||
@SuppressWarnings("ParameterName")
|
||||
public PIDController(double Kp, double Ki, double Kd, double Kf, PIDSource source,
|
||||
PIDOutput output, double period) {
|
||||
super(false);
|
||||
requireNonNull(source, "Null PIDSource was given");
|
||||
requireNonNull(output, "Null PIDOutput was given");
|
||||
|
||||
@@ -180,6 +178,7 @@ public class PIDController implements PIDInterface, LiveWindowSendable, Controll
|
||||
instances++;
|
||||
HLUsageReporting.reportPIDController(instances);
|
||||
m_tolerance = new NullTolerance();
|
||||
setName("PIDController", instances);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -232,7 +231,9 @@ public class PIDController implements PIDInterface, LiveWindowSendable, Controll
|
||||
/**
|
||||
* Free the PID object.
|
||||
*/
|
||||
@Override
|
||||
public void free() {
|
||||
super.free();
|
||||
m_controlLoop.cancel();
|
||||
m_thisMutex.lock();
|
||||
try {
|
||||
@@ -242,7 +243,6 @@ public class PIDController implements PIDInterface, LiveWindowSendable, Controll
|
||||
} finally {
|
||||
m_thisMutex.unlock();
|
||||
}
|
||||
removeListeners();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -395,16 +395,6 @@ public class PIDController implements PIDInterface, LiveWindowSendable, Controll
|
||||
} finally {
|
||||
m_thisMutex.unlock();
|
||||
}
|
||||
|
||||
if (m_pEntry != null) {
|
||||
m_pEntry.setDouble(p);
|
||||
}
|
||||
if (m_iEntry != null) {
|
||||
m_iEntry.setDouble(i);
|
||||
}
|
||||
if (m_dEntry != null) {
|
||||
m_dEntry.setDouble(d);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -427,18 +417,65 @@ public class PIDController implements PIDInterface, LiveWindowSendable, Controll
|
||||
} finally {
|
||||
m_thisMutex.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
if (m_pEntry != null) {
|
||||
m_pEntry.setDouble(p);
|
||||
/**
|
||||
* Set the Proportional coefficient of the PID controller gain.
|
||||
*
|
||||
* @param p Proportional coefficient
|
||||
*/
|
||||
@SuppressWarnings("ParameterName")
|
||||
public void setP(double p) {
|
||||
m_thisMutex.lock();
|
||||
try {
|
||||
m_P = p;
|
||||
} finally {
|
||||
m_thisMutex.unlock();
|
||||
}
|
||||
if (m_iEntry != null) {
|
||||
m_iEntry.setDouble(i);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the Integral coefficient of the PID controller gain.
|
||||
*
|
||||
* @param i Integral coefficient
|
||||
*/
|
||||
@SuppressWarnings("ParameterName")
|
||||
public void setI(double i) {
|
||||
m_thisMutex.lock();
|
||||
try {
|
||||
m_I = i;
|
||||
} finally {
|
||||
m_thisMutex.unlock();
|
||||
}
|
||||
if (m_dEntry != null) {
|
||||
m_dEntry.setDouble(d);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the Differential coefficient of the PID controller gain.
|
||||
*
|
||||
* @param d differential coefficient
|
||||
*/
|
||||
@SuppressWarnings("ParameterName")
|
||||
public void setD(double d) {
|
||||
m_thisMutex.lock();
|
||||
try {
|
||||
m_D = d;
|
||||
} finally {
|
||||
m_thisMutex.unlock();
|
||||
}
|
||||
if (m_fEntry != null) {
|
||||
m_fEntry.setDouble(f);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the Feed forward coefficient of the PID controller gain.
|
||||
*
|
||||
* @param f feed forward coefficient
|
||||
*/
|
||||
@SuppressWarnings("ParameterName")
|
||||
public void setF(double f) {
|
||||
m_thisMutex.lock();
|
||||
try {
|
||||
m_F = f;
|
||||
} finally {
|
||||
m_thisMutex.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -601,10 +638,6 @@ public class PIDController implements PIDInterface, LiveWindowSendable, Controll
|
||||
} finally {
|
||||
m_thisMutex.unlock();
|
||||
}
|
||||
|
||||
if (m_setpointEntry != null) {
|
||||
m_setpointEntry.setDouble(m_setpoint);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -776,10 +809,6 @@ public class PIDController implements PIDInterface, LiveWindowSendable, Controll
|
||||
} finally {
|
||||
m_thisMutex.unlock();
|
||||
}
|
||||
|
||||
if (m_enabledEntry != null) {
|
||||
m_enabledEntry.setBoolean(true);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -801,9 +830,16 @@ public class PIDController implements PIDInterface, LiveWindowSendable, Controll
|
||||
} finally {
|
||||
m_pidWriteMutex.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
if (m_enabledEntry != null) {
|
||||
m_enabledEntry.setBoolean(false);
|
||||
/**
|
||||
* Set the enabled state of the PIDController.
|
||||
*/
|
||||
public void setEnabled(boolean enable) {
|
||||
if (enable) {
|
||||
enable();
|
||||
} else {
|
||||
disable();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -824,7 +860,7 @@ public class PIDController implements PIDInterface, LiveWindowSendable, Controll
|
||||
* Reset the previous error,, the integral term, and disable the controller.
|
||||
*/
|
||||
@Override
|
||||
public synchronized void reset() {
|
||||
public void reset() {
|
||||
disable();
|
||||
|
||||
m_thisMutex.lock();
|
||||
@@ -838,130 +874,15 @@ public class PIDController implements PIDInterface, LiveWindowSendable, Controll
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSmartDashboardType() {
|
||||
return "PIDController";
|
||||
}
|
||||
|
||||
@SuppressWarnings("MemberName")
|
||||
private NetworkTableEntry m_pEntry;
|
||||
@SuppressWarnings("MemberName")
|
||||
private NetworkTableEntry m_iEntry;
|
||||
@SuppressWarnings("MemberName")
|
||||
private NetworkTableEntry m_dEntry;
|
||||
@SuppressWarnings("MemberName")
|
||||
private NetworkTableEntry m_fEntry;
|
||||
private NetworkTableEntry m_setpointEntry;
|
||||
private NetworkTableEntry m_enabledEntry;
|
||||
@SuppressWarnings("MemberName")
|
||||
private int m_pListener;
|
||||
@SuppressWarnings("MemberName")
|
||||
private int m_iListener;
|
||||
@SuppressWarnings("MemberName")
|
||||
private int m_dListener;
|
||||
@SuppressWarnings("MemberName")
|
||||
private int m_fListener;
|
||||
private int m_setpointListener;
|
||||
private int m_enabledListener;
|
||||
|
||||
private void removeListeners() {
|
||||
if (m_pEntry != null) {
|
||||
m_pEntry.removeListener(m_pListener);
|
||||
}
|
||||
if (m_iEntry != null) {
|
||||
m_iEntry.removeListener(m_iListener);
|
||||
}
|
||||
if (m_dEntry != null) {
|
||||
m_dEntry.removeListener(m_dListener);
|
||||
}
|
||||
if (m_fEntry != null) {
|
||||
m_fEntry.removeListener(m_fListener);
|
||||
}
|
||||
if (m_setpointEntry != null) {
|
||||
m_setpointEntry.removeListener(m_setpointListener);
|
||||
}
|
||||
if (m_enabledEntry != null) {
|
||||
m_enabledEntry.removeListener(m_enabledListener);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initTable(NetworkTable table) {
|
||||
removeListeners();
|
||||
if (table != null) {
|
||||
m_pEntry = table.getEntry("p");
|
||||
m_pEntry.setDouble(getP());
|
||||
m_iEntry = table.getEntry("i");
|
||||
m_iEntry.setDouble(getI());
|
||||
m_dEntry = table.getEntry("d");
|
||||
m_dEntry.setDouble(getD());
|
||||
m_fEntry = table.getEntry("f");
|
||||
m_fEntry.setDouble(getF());
|
||||
m_setpointEntry = table.getEntry("setpoint");
|
||||
m_setpointEntry.setDouble(getSetpoint());
|
||||
m_enabledEntry = table.getEntry("enabled");
|
||||
m_enabledEntry.setBoolean(isEnabled());
|
||||
|
||||
m_pListener = m_pEntry.addListener((entry) -> {
|
||||
m_thisMutex.lock();
|
||||
try {
|
||||
m_P = entry.value.getDouble();
|
||||
} finally {
|
||||
m_thisMutex.unlock();
|
||||
}
|
||||
}, EntryListenerFlags.kNew | EntryListenerFlags.kUpdate);
|
||||
|
||||
m_iListener = m_iEntry.addListener((entry) -> {
|
||||
m_thisMutex.lock();
|
||||
try {
|
||||
m_I = entry.value.getDouble();
|
||||
} finally {
|
||||
m_thisMutex.unlock();
|
||||
}
|
||||
}, EntryListenerFlags.kNew | EntryListenerFlags.kUpdate);
|
||||
|
||||
m_dListener = m_dEntry.addListener((entry) -> {
|
||||
m_thisMutex.lock();
|
||||
try {
|
||||
m_D = entry.value.getDouble();
|
||||
} finally {
|
||||
m_thisMutex.unlock();
|
||||
}
|
||||
}, EntryListenerFlags.kNew | EntryListenerFlags.kUpdate);
|
||||
|
||||
m_fListener = m_fEntry.addListener((entry) -> {
|
||||
m_thisMutex.lock();
|
||||
try {
|
||||
m_F = entry.value.getDouble();
|
||||
} finally {
|
||||
m_thisMutex.unlock();
|
||||
}
|
||||
}, EntryListenerFlags.kNew | EntryListenerFlags.kUpdate);
|
||||
|
||||
m_setpointListener = m_setpointEntry.addListener((entry) -> {
|
||||
double val = entry.value.getDouble();
|
||||
if (getSetpoint() != val) {
|
||||
setSetpoint(val);
|
||||
}
|
||||
}, EntryListenerFlags.kNew | EntryListenerFlags.kUpdate);
|
||||
|
||||
m_enabledListener = m_enabledEntry.addListener((entry) -> {
|
||||
boolean val = entry.value.getBoolean();
|
||||
if (isEnabled() != val) {
|
||||
if (val) {
|
||||
enable();
|
||||
} else {
|
||||
disable();
|
||||
}
|
||||
}
|
||||
}, EntryListenerFlags.kNew | EntryListenerFlags.kUpdate);
|
||||
} else {
|
||||
m_pEntry = null;
|
||||
m_iEntry = null;
|
||||
m_dEntry = null;
|
||||
m_fEntry = null;
|
||||
m_setpointEntry = null;
|
||||
m_enabledEntry = null;
|
||||
}
|
||||
public void initSendable(SendableBuilder builder) {
|
||||
builder.setSmartDashboardType("PIDController");
|
||||
builder.setSafeState(this::reset);
|
||||
builder.addDoubleProperty("p", this::getP, this::setP);
|
||||
builder.addDoubleProperty("i", this::getI, this::setI);
|
||||
builder.addDoubleProperty("d", this::getD, this::setD);
|
||||
builder.addDoubleProperty("f", this::getF, this::setF);
|
||||
builder.addDoubleProperty("setpoint", this::getSetpoint, this::setSetpoint);
|
||||
builder.addBooleanProperty("enabled", this::isEnabled, this::setEnabled);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -986,21 +907,6 @@ public class PIDController implements PIDInterface, LiveWindowSendable, Controll
|
||||
return error;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateTable() {
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void startLiveWindowMode() {
|
||||
disable();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void stopLiveWindowMode() {
|
||||
}
|
||||
|
||||
private static double clamp(double value, double low, double high) {
|
||||
return Math.max(low, Math.min(value, high));
|
||||
}
|
||||
|
||||
@@ -7,14 +7,11 @@
|
||||
|
||||
package edu.wpi.first.wpilibj;
|
||||
|
||||
import edu.wpi.first.networktables.EntryListenerFlags;
|
||||
import edu.wpi.first.networktables.NetworkTable;
|
||||
import edu.wpi.first.networktables.NetworkTableEntry;
|
||||
import edu.wpi.first.wpilibj.hal.DIOJNI;
|
||||
import edu.wpi.first.wpilibj.hal.FRCNetComm.tResourceType;
|
||||
import edu.wpi.first.wpilibj.hal.HAL;
|
||||
import edu.wpi.first.wpilibj.hal.PWMJNI;
|
||||
import edu.wpi.first.wpilibj.livewindow.LiveWindowSendable;
|
||||
import edu.wpi.first.wpilibj.smartdashboard.SendableBuilder;
|
||||
|
||||
/**
|
||||
* Class implements the PWM generation in the FPGA.
|
||||
@@ -28,7 +25,7 @@ import edu.wpi.first.wpilibj.livewindow.LiveWindowSendable;
|
||||
* center value - 999 to 2 = linear scaling from "center" to "full reverse" - 1 = minimum pulse
|
||||
* width (currently .5ms) - 0 = disabled (i.e. PWM output is held low)
|
||||
*/
|
||||
public class PWM extends SensorBase implements LiveWindowSendable {
|
||||
public class PWM extends SendableBase implements Sendable {
|
||||
/**
|
||||
* Represents the amount to multiply the minimum servo-pulse pwm period by.
|
||||
*/
|
||||
@@ -56,7 +53,7 @@ public class PWM extends SensorBase implements LiveWindowSendable {
|
||||
* @param channel The PWM channel number. 0-9 are on-board, 10-19 are on the MXP port
|
||||
*/
|
||||
public PWM(final int channel) {
|
||||
checkPWMChannel(channel);
|
||||
SensorBase.checkPWMChannel(channel);
|
||||
m_channel = channel;
|
||||
|
||||
m_handle = PWMJNI.initializePWMPort(DIOJNI.getPort((byte) channel));
|
||||
@@ -66,6 +63,7 @@ public class PWM extends SensorBase implements LiveWindowSendable {
|
||||
PWMJNI.setPWMEliminateDeadband(m_handle, false);
|
||||
|
||||
HAL.report(tResourceType.kResourceType_PWM, channel);
|
||||
setName("PWM", channel);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -73,7 +71,9 @@ public class PWM extends SensorBase implements LiveWindowSendable {
|
||||
*
|
||||
* <p>Free the resource associated with the PWM channel and set the value to 0.
|
||||
*/
|
||||
@Override
|
||||
public void free() {
|
||||
super.free();
|
||||
if (m_handle == 0) {
|
||||
return;
|
||||
}
|
||||
@@ -242,45 +242,10 @@ public class PWM extends SensorBase implements LiveWindowSendable {
|
||||
PWMJNI.latchPWMZero(m_handle);
|
||||
}
|
||||
|
||||
/*
|
||||
* Live Window code, only does anything if live window is activated.
|
||||
*/
|
||||
@Override
|
||||
public String getSmartDashboardType() {
|
||||
return "Speed Controller";
|
||||
}
|
||||
|
||||
private NetworkTableEntry m_valueEntry;
|
||||
private int m_valueListener;
|
||||
|
||||
@Override
|
||||
public void initTable(NetworkTable subtable) {
|
||||
if (subtable != null) {
|
||||
m_valueEntry = subtable.getEntry("Value");
|
||||
updateTable();
|
||||
} else {
|
||||
m_valueEntry = null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateTable() {
|
||||
if (m_valueEntry != null) {
|
||||
m_valueEntry.setDouble(getSpeed());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void startLiveWindowMode() {
|
||||
setSpeed(0); // Stop for safety
|
||||
m_valueListener = m_valueEntry.addListener((event) -> setSpeed(event.value.getDouble()),
|
||||
EntryListenerFlags.kImmediate | EntryListenerFlags.kNew | EntryListenerFlags.kUpdate);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stopLiveWindowMode() {
|
||||
setSpeed(0); // Stop for safety
|
||||
m_valueEntry.removeListener(m_valueListener);
|
||||
m_valueListener = 0;
|
||||
public void initSendable(SendableBuilder builder) {
|
||||
builder.setSmartDashboardType("Speed Controller");
|
||||
builder.setSafeState(this::setDisabled);
|
||||
builder.addDoubleProperty("Value", this::getSpeed, this::setSpeed);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,7 +9,6 @@ package edu.wpi.first.wpilibj;
|
||||
|
||||
import edu.wpi.first.wpilibj.hal.FRCNetComm.tResourceType;
|
||||
import edu.wpi.first.wpilibj.hal.HAL;
|
||||
import edu.wpi.first.wpilibj.livewindow.LiveWindow;
|
||||
|
||||
/**
|
||||
* Cross the Road Electronics (CTRE) Talon SRX Speed Controller with PWM control.
|
||||
@@ -41,7 +40,7 @@ public class PWMTalonSRX extends PWMSpeedController {
|
||||
setSpeed(0.0);
|
||||
setZeroLatch();
|
||||
|
||||
LiveWindow.addActuator("PWMTalonSRX", getChannel(), this);
|
||||
HAL.report(tResourceType.kResourceType_PWMTalonSRX, getChannel());
|
||||
setName("PWMTalonSRX", getChannel());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,16 +7,14 @@
|
||||
|
||||
package edu.wpi.first.wpilibj;
|
||||
|
||||
import edu.wpi.first.networktables.NetworkTable;
|
||||
import edu.wpi.first.networktables.NetworkTableEntry;
|
||||
import edu.wpi.first.wpilibj.hal.PDPJNI;
|
||||
import edu.wpi.first.wpilibj.livewindow.LiveWindowSendable;
|
||||
import edu.wpi.first.wpilibj.smartdashboard.SendableBuilder;
|
||||
|
||||
/**
|
||||
* Class for getting voltage, current, temperature, power and energy from the Power Distribution
|
||||
* Panel over CAN.
|
||||
*/
|
||||
public class PowerDistributionPanel extends SensorBase implements LiveWindowSendable {
|
||||
public class PowerDistributionPanel extends SensorBase implements Sendable {
|
||||
|
||||
private final int m_module;
|
||||
|
||||
@@ -29,6 +27,7 @@ public class PowerDistributionPanel extends SensorBase implements LiveWindowSend
|
||||
m_module = module;
|
||||
checkPDPModule(module);
|
||||
PDPJNI.initializePDP(module);
|
||||
setName("PowerDistributionPanel", module);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -111,61 +110,13 @@ public class PowerDistributionPanel extends SensorBase implements LiveWindowSend
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSmartDashboardType() {
|
||||
return "PowerDistributionPanel";
|
||||
}
|
||||
|
||||
/*
|
||||
* Live Window code, only does anything if live window is activated.
|
||||
*/
|
||||
private NetworkTableEntry[] m_chanEntry;
|
||||
private NetworkTableEntry m_voltageEntry;
|
||||
private NetworkTableEntry m_totalCurrentEntry;
|
||||
|
||||
@Override
|
||||
public void initTable(NetworkTable subtable) {
|
||||
if (subtable != null) {
|
||||
m_chanEntry = new NetworkTableEntry[16];
|
||||
for (int i = 0; i < m_chanEntry.length; i++) {
|
||||
m_chanEntry[i] = subtable.getEntry("Chan" + i);
|
||||
}
|
||||
m_voltageEntry = subtable.getEntry("Voltage");
|
||||
m_totalCurrentEntry = subtable.getEntry("TotalCurrent");
|
||||
updateTable();
|
||||
} else {
|
||||
m_chanEntry = null;
|
||||
m_voltageEntry = null;
|
||||
m_totalCurrentEntry = null;
|
||||
public void initSendable(SendableBuilder builder) {
|
||||
builder.setSmartDashboardType("PowerDistributionPanel");
|
||||
for (int i = 0; i < kPDPChannels; ++i) {
|
||||
final int chan = i;
|
||||
builder.addDoubleProperty("Chan" + i, () -> getCurrent(chan), null);
|
||||
}
|
||||
builder.addDoubleProperty("Voltage", this::getVoltage, null);
|
||||
builder.addDoubleProperty("TotalCurrent", this::getTotalCurrent, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateTable() {
|
||||
if (m_chanEntry != null) {
|
||||
for (int i = 0; i < m_chanEntry.length; i++) {
|
||||
m_chanEntry[i].setDouble(getCurrent(i));
|
||||
}
|
||||
}
|
||||
if (m_voltageEntry != null) {
|
||||
m_voltageEntry.setDouble(getVoltage());
|
||||
}
|
||||
if (m_totalCurrentEntry != null) {
|
||||
m_totalCurrentEntry.setDouble(getTotalCurrent());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* PDP doesn't have to do anything special when entering the LiveWindow. {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public void startLiveWindowMode() {
|
||||
}
|
||||
|
||||
/**
|
||||
* PDP doesn't have to do anything special when exiting the LiveWindow. {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public void stopLiveWindowMode() {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -7,14 +7,10 @@
|
||||
|
||||
package edu.wpi.first.wpilibj;
|
||||
|
||||
import edu.wpi.first.networktables.EntryListenerFlags;
|
||||
import edu.wpi.first.networktables.NetworkTable;
|
||||
import edu.wpi.first.networktables.NetworkTableEntry;
|
||||
import edu.wpi.first.wpilibj.hal.FRCNetComm.tResourceType;
|
||||
import edu.wpi.first.wpilibj.hal.HAL;
|
||||
import edu.wpi.first.wpilibj.hal.RelayJNI;
|
||||
import edu.wpi.first.wpilibj.livewindow.LiveWindow;
|
||||
import edu.wpi.first.wpilibj.livewindow.LiveWindowSendable;
|
||||
import edu.wpi.first.wpilibj.smartdashboard.SendableBuilder;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Optional;
|
||||
@@ -30,7 +26,7 @@ import static java.util.Objects.requireNonNull;
|
||||
* channels (forward and reverse) to be used independently for something that does not care about
|
||||
* voltage polarity (like a solenoid).
|
||||
*/
|
||||
public class Relay extends SensorBase implements MotorSafety, LiveWindowSendable {
|
||||
public class Relay extends SendableBase implements MotorSafety, Sendable {
|
||||
private MotorSafetyHelper m_safetyHelper;
|
||||
|
||||
/**
|
||||
@@ -120,7 +116,7 @@ public class Relay extends SensorBase implements MotorSafety, LiveWindowSendable
|
||||
m_safetyHelper = new MotorSafetyHelper(this);
|
||||
m_safetyHelper.setSafetyEnabled(false);
|
||||
|
||||
LiveWindow.addActuator("Relay", m_channel, this);
|
||||
setName("Relay", m_channel);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -147,6 +143,11 @@ public class Relay extends SensorBase implements MotorSafety, LiveWindowSendable
|
||||
|
||||
@Override
|
||||
public void free() {
|
||||
super.free();
|
||||
freeRelay();
|
||||
}
|
||||
|
||||
private void freeRelay() {
|
||||
try {
|
||||
RelayJNI.setRelay(m_forwardHandle, false);
|
||||
} catch (RuntimeException ex) {
|
||||
@@ -324,49 +325,16 @@ public class Relay extends SensorBase implements MotorSafety, LiveWindowSendable
|
||||
return;
|
||||
}
|
||||
|
||||
free();
|
||||
freeRelay();
|
||||
m_direction = direction;
|
||||
initRelay();
|
||||
}
|
||||
|
||||
/*
|
||||
* Live Window code, only does anything if live window is activated.
|
||||
*/
|
||||
@Override
|
||||
public String getSmartDashboardType() {
|
||||
return "Relay";
|
||||
}
|
||||
|
||||
private NetworkTableEntry m_valueEntry;
|
||||
private int m_valueListener;
|
||||
|
||||
@Override
|
||||
public void initTable(NetworkTable subtable) {
|
||||
if (subtable != null) {
|
||||
m_valueEntry = subtable.getEntry("Value");
|
||||
updateTable();
|
||||
} else {
|
||||
m_valueEntry = null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateTable() {
|
||||
if (m_valueEntry != null) {
|
||||
m_valueEntry.setString(get().getPrettyValue());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void startLiveWindowMode() {
|
||||
m_valueListener = m_valueEntry.addListener(
|
||||
(event) -> set(Value.getValueOf(event.value.getString()).orElse(Value.kOff)),
|
||||
EntryListenerFlags.kImmediate | EntryListenerFlags.kNew | EntryListenerFlags.kUpdate);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stopLiveWindowMode() {
|
||||
m_valueEntry.removeListener(m_valueListener);
|
||||
m_valueListener = 0;
|
||||
public void initSendable(SendableBuilder builder) {
|
||||
builder.setSmartDashboardType("Relay");
|
||||
builder.setSafeState(() -> set(Value.kOff));
|
||||
builder.addStringProperty("Value", () -> get().getPrettyValue(),
|
||||
(value) -> set(Value.getValueOf(value).orElse(Value.kOff)));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,7 +9,6 @@ package edu.wpi.first.wpilibj;
|
||||
|
||||
import edu.wpi.first.wpilibj.hal.FRCNetComm.tResourceType;
|
||||
import edu.wpi.first.wpilibj.hal.HAL;
|
||||
import edu.wpi.first.wpilibj.livewindow.LiveWindow;
|
||||
|
||||
/**
|
||||
* Mindsensors SD540 Speed Controller.
|
||||
@@ -35,8 +34,8 @@ public class SD540 extends PWMSpeedController {
|
||||
setSpeed(0.0);
|
||||
setZeroLatch();
|
||||
|
||||
LiveWindow.addActuator("SD540", getChannel(), this);
|
||||
HAL.report(tResourceType.kResourceType_MindsensorsSD540, getChannel());
|
||||
setName("SD540", getChannel());
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -16,7 +16,7 @@ import edu.wpi.first.wpilibj.hal.SPIJNI;
|
||||
/**
|
||||
* Represents a SPI bus port.
|
||||
*/
|
||||
public class SPI extends SensorBase {
|
||||
public class SPI {
|
||||
|
||||
public enum Port {
|
||||
kOnboardCS0(0), kOnboardCS1(1), kOnboardCS2(2), kOnboardCS3(3), kMXP(4);
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
|
||||
package edu.wpi.first.wpilibj;
|
||||
|
||||
import edu.wpi.first.networktables.NetworkTable;
|
||||
import edu.wpi.first.wpilibj.smartdashboard.SendableBuilder;
|
||||
|
||||
|
||||
/**
|
||||
@@ -15,17 +15,48 @@ import edu.wpi.first.networktables.NetworkTable;
|
||||
*/
|
||||
public interface Sendable {
|
||||
/**
|
||||
* Initializes a table for this {@link Sendable} object.
|
||||
* Gets the name of this {@link Sendable} object.
|
||||
*
|
||||
* @param subtable The table to put the values in.
|
||||
* @return Name
|
||||
*/
|
||||
void initTable(NetworkTable subtable);
|
||||
String getName();
|
||||
|
||||
/**
|
||||
* The string representation of the named data type that will be used by the smart dashboard for
|
||||
* this {@link Sendable}.
|
||||
* Sets the name of this {@link Sendable} object.
|
||||
*
|
||||
* @return The type of this {@link Sendable}.
|
||||
* @param name name
|
||||
*/
|
||||
String getSmartDashboardType();
|
||||
void setName(String name);
|
||||
|
||||
/**
|
||||
* Sets both the subsystem name and device name of this {@link Sendable} object.
|
||||
*
|
||||
* @param subsystem subsystem name
|
||||
* @param name device name
|
||||
*/
|
||||
default void setName(String subsystem, String name) {
|
||||
setSubsystem(subsystem);
|
||||
setName(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the subsystem name of this {@link Sendable} object.
|
||||
*
|
||||
* @return Subsystem name
|
||||
*/
|
||||
String getSubsystem();
|
||||
|
||||
/**
|
||||
* Sets the subsystem name of this {@link Sendable} object.
|
||||
*
|
||||
* @param subsystem subsystem name
|
||||
*/
|
||||
void setSubsystem(String subsystem);
|
||||
|
||||
/**
|
||||
* Initializes this {@link Sendable} object.
|
||||
*
|
||||
* @param builder sendable builder
|
||||
*/
|
||||
void initSendable(SendableBuilder builder);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,94 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* 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. */
|
||||
/*----------------------------------------------------------------------------*/
|
||||
|
||||
package edu.wpi.first.wpilibj;
|
||||
|
||||
import edu.wpi.first.wpilibj.livewindow.LiveWindow;
|
||||
|
||||
/**
|
||||
* Base class for all sensors. Stores most recent status information as well as containing utility
|
||||
* functions for checking channels and error processing.
|
||||
*/
|
||||
public abstract class SendableBase implements Sendable {
|
||||
private String m_name = "";
|
||||
private String m_subsystem = "Ungrouped";
|
||||
|
||||
/**
|
||||
* Creates an instance of the sensor base.
|
||||
*/
|
||||
public SendableBase() {
|
||||
this(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an instance of the sensor base.
|
||||
*
|
||||
* @param addLiveWindow if true, add this Sendable to LiveWindow
|
||||
*/
|
||||
public SendableBase(boolean addLiveWindow) {
|
||||
if (addLiveWindow) {
|
||||
LiveWindow.add(this);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Free the resources used by this object.
|
||||
*/
|
||||
public void free() {
|
||||
LiveWindow.remove(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final synchronized String getName() {
|
||||
return m_name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final synchronized void setName(String name) {
|
||||
m_name = name;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
protected final void setName(String moduleType, int channel) {
|
||||
setName(moduleType + "[" + channel + "]");
|
||||
}
|
||||
|
||||
/**
|
||||
* 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)
|
||||
*/
|
||||
protected final void setName(String moduleType, int moduleNumber, int channel) {
|
||||
setName(moduleType + "[" + moduleNumber + "," + channel + "]");
|
||||
}
|
||||
|
||||
@Override
|
||||
public final synchronized String getSubsystem() {
|
||||
return m_subsystem;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final synchronized void setSubsystem(String subsystem) {
|
||||
m_subsystem = subsystem;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a child component.
|
||||
*
|
||||
* @param child child component
|
||||
*/
|
||||
protected final void addChild(Object child) {
|
||||
LiveWindow.addChild(this, child);
|
||||
}
|
||||
}
|
||||
@@ -20,7 +20,7 @@ import edu.wpi.first.wpilibj.hal.SolenoidJNI;
|
||||
* Base class for all sensors. Stores most recent status information as well as containing utility
|
||||
* functions for checking channels and error processing.
|
||||
*/
|
||||
public abstract class SensorBase {
|
||||
public abstract class SensorBase extends SendableBase {
|
||||
/**
|
||||
* Ticks per microsecond.
|
||||
*/
|
||||
@@ -65,12 +65,6 @@ public abstract class SensorBase {
|
||||
|
||||
private static int m_defaultSolenoidModule = 0;
|
||||
|
||||
/**
|
||||
* Creates an instance of the sensor base and gets an FPGA handle.
|
||||
*/
|
||||
public SensorBase() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the default location for the Solenoid module.
|
||||
*
|
||||
@@ -86,7 +80,7 @@ public abstract class SensorBase {
|
||||
*
|
||||
* @param moduleNumber The solenoid module module number to check.
|
||||
*/
|
||||
protected static void checkSolenoidModule(final int moduleNumber) {
|
||||
public static void checkSolenoidModule(final int moduleNumber) {
|
||||
if (!SolenoidJNI.checkSolenoidModule(moduleNumber)) {
|
||||
StringBuilder buf = new StringBuilder();
|
||||
buf.append("Requested solenoid module is out of range. Minimum: 0, Maximum: ")
|
||||
@@ -103,7 +97,7 @@ public abstract class SensorBase {
|
||||
*
|
||||
* @param channel The channel number to check.
|
||||
*/
|
||||
protected static void checkDigitalChannel(final int channel) {
|
||||
public static void checkDigitalChannel(final int channel) {
|
||||
if (!DIOJNI.checkDIOChannel(channel)) {
|
||||
StringBuilder buf = new StringBuilder();
|
||||
buf.append("Requested DIO channel is out of range. Minimum: 0, Maximum: ")
|
||||
@@ -120,7 +114,7 @@ public abstract class SensorBase {
|
||||
*
|
||||
* @param channel The channel number to check.
|
||||
*/
|
||||
protected static void checkRelayChannel(final int channel) {
|
||||
public static void checkRelayChannel(final int channel) {
|
||||
if (!RelayJNI.checkRelayChannel(channel)) {
|
||||
StringBuilder buf = new StringBuilder();
|
||||
buf.append("Requested relay channel is out of range. Minimum: 0, Maximum: ")
|
||||
@@ -137,7 +131,7 @@ public abstract class SensorBase {
|
||||
*
|
||||
* @param channel The channel number to check.
|
||||
*/
|
||||
protected static void checkPWMChannel(final int channel) {
|
||||
public static void checkPWMChannel(final int channel) {
|
||||
if (!PWMJNI.checkPWMChannel(channel)) {
|
||||
StringBuilder buf = new StringBuilder();
|
||||
buf.append("Requested PWM channel is out of range. Minimum: 0, Maximum: ")
|
||||
@@ -154,7 +148,7 @@ public abstract class SensorBase {
|
||||
*
|
||||
* @param channel The channel number to check.
|
||||
*/
|
||||
protected static void checkAnalogInputChannel(final int channel) {
|
||||
public static void checkAnalogInputChannel(final int channel) {
|
||||
if (!AnalogJNI.checkAnalogInputChannel(channel)) {
|
||||
StringBuilder buf = new StringBuilder();
|
||||
buf.append("Requested analog input channel is out of range. Minimum: 0, Maximum: ")
|
||||
@@ -171,7 +165,7 @@ public abstract class SensorBase {
|
||||
*
|
||||
* @param channel The channel number to check.
|
||||
*/
|
||||
protected static void checkAnalogOutputChannel(final int channel) {
|
||||
public static void checkAnalogOutputChannel(final int channel) {
|
||||
if (!AnalogJNI.checkAnalogOutputChannel(channel)) {
|
||||
StringBuilder buf = new StringBuilder();
|
||||
buf.append("Requested analog output channel is out of range. Minimum: 0, Maximum: ")
|
||||
@@ -187,7 +181,7 @@ public abstract class SensorBase {
|
||||
*
|
||||
* @param channel The channel number to check.
|
||||
*/
|
||||
protected static void checkSolenoidChannel(final int channel) {
|
||||
public static void checkSolenoidChannel(final int channel) {
|
||||
if (!SolenoidJNI.checkSolenoidChannel(channel)) {
|
||||
StringBuilder buf = new StringBuilder();
|
||||
buf.append("Requested solenoid channel is out of range. Minimum: 0, Maximum: ")
|
||||
@@ -204,7 +198,7 @@ public abstract class SensorBase {
|
||||
*
|
||||
* @param channel The channel number to check.
|
||||
*/
|
||||
protected static void checkPDPChannel(final int channel) {
|
||||
public static void checkPDPChannel(final int channel) {
|
||||
if (!PDPJNI.checkPDPChannel(channel)) {
|
||||
StringBuilder buf = new StringBuilder();
|
||||
buf.append("Requested PDP channel is out of range. Minimum: 0, Maximum: ")
|
||||
@@ -220,7 +214,7 @@ public abstract class SensorBase {
|
||||
*
|
||||
* @param module The module number to check.
|
||||
*/
|
||||
protected static void checkPDPModule(final int module) {
|
||||
public static void checkPDPModule(final int module) {
|
||||
if (!PDPJNI.checkPDPModule(module)) {
|
||||
StringBuilder buf = new StringBuilder();
|
||||
buf.append("Requested PDP module is out of range. Minimum: 0, Maximum: ")
|
||||
@@ -239,10 +233,4 @@ public abstract class SensorBase {
|
||||
public static int getDefaultSolenoidModule() {
|
||||
return SensorBase.m_defaultSolenoidModule;
|
||||
}
|
||||
|
||||
/**
|
||||
* Free the resources used by this object.
|
||||
*/
|
||||
public void free() {
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,12 +7,9 @@
|
||||
|
||||
package edu.wpi.first.wpilibj;
|
||||
|
||||
import edu.wpi.first.networktables.EntryListenerFlags;
|
||||
import edu.wpi.first.networktables.NetworkTable;
|
||||
import edu.wpi.first.networktables.NetworkTableEntry;
|
||||
import edu.wpi.first.wpilibj.hal.FRCNetComm.tResourceType;
|
||||
import edu.wpi.first.wpilibj.hal.HAL;
|
||||
import edu.wpi.first.wpilibj.livewindow.LiveWindow;
|
||||
import edu.wpi.first.wpilibj.smartdashboard.SendableBuilder;
|
||||
|
||||
/**
|
||||
* Standard hobby style servo.
|
||||
@@ -42,8 +39,8 @@ public class Servo extends PWM {
|
||||
setBounds(kDefaultMaxServoPWM, 0, 0, 0, kDefaultMinServoPWM);
|
||||
setPeriodMultiplier(PeriodMultiplier.k4X);
|
||||
|
||||
LiveWindow.addActuator("Servo", getChannel(), this);
|
||||
HAL.report(tResourceType.kResourceType_Servo, getChannel());
|
||||
setName("Servo", getChannel());
|
||||
}
|
||||
|
||||
|
||||
@@ -108,44 +105,9 @@ public class Servo extends PWM {
|
||||
return kMaxServoAngle - kMinServoAngle;
|
||||
}
|
||||
|
||||
/*
|
||||
* Live Window code, only does anything if live window is activated.
|
||||
*/
|
||||
public String getSmartDashboardType() {
|
||||
return "Servo";
|
||||
}
|
||||
|
||||
private NetworkTable m_table;
|
||||
private NetworkTableEntry m_valueEntry;
|
||||
private int m_valueListener;
|
||||
|
||||
@Override
|
||||
public void initTable(NetworkTable subtable) {
|
||||
m_table = subtable;
|
||||
if (m_table != null) {
|
||||
m_valueEntry = m_table.getEntry("Value");
|
||||
updateTable();
|
||||
} else {
|
||||
m_valueEntry = null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateTable() {
|
||||
if (m_valueEntry != null) {
|
||||
m_valueEntry.setDouble(get());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void startLiveWindowMode() {
|
||||
m_valueListener = m_valueEntry.addListener((event) -> set(event.value.getDouble()),
|
||||
EntryListenerFlags.kImmediate | EntryListenerFlags.kNew | EntryListenerFlags.kUpdate);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stopLiveWindowMode() {
|
||||
m_valueEntry.removeListener(m_valueListener);
|
||||
m_valueListener = 0;
|
||||
public void initSendable(SendableBuilder builder) {
|
||||
builder.setSmartDashboardType("Servo");
|
||||
builder.addDoubleProperty("Value", this::get, this::set);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,14 +7,10 @@
|
||||
|
||||
package edu.wpi.first.wpilibj;
|
||||
|
||||
import edu.wpi.first.networktables.EntryListenerFlags;
|
||||
import edu.wpi.first.networktables.NetworkTable;
|
||||
import edu.wpi.first.networktables.NetworkTableEntry;
|
||||
import edu.wpi.first.wpilibj.hal.FRCNetComm.tResourceType;
|
||||
import edu.wpi.first.wpilibj.hal.HAL;
|
||||
import edu.wpi.first.wpilibj.hal.SolenoidJNI;
|
||||
import edu.wpi.first.wpilibj.livewindow.LiveWindow;
|
||||
import edu.wpi.first.wpilibj.livewindow.LiveWindowSendable;
|
||||
import edu.wpi.first.wpilibj.smartdashboard.SendableBuilder;
|
||||
|
||||
/**
|
||||
* Solenoid class for running high voltage Digital Output on the PCM.
|
||||
@@ -22,7 +18,7 @@ import edu.wpi.first.wpilibj.livewindow.LiveWindowSendable;
|
||||
* <p>The Solenoid class is typically used for pneumatic solenoids, but could be used for any
|
||||
* device within the current spec of the PCM.
|
||||
*/
|
||||
public class Solenoid extends SolenoidBase implements LiveWindowSendable {
|
||||
public class Solenoid extends SolenoidBase implements Sendable {
|
||||
|
||||
private final int m_channel; // The channel to control.
|
||||
private int m_solenoidHandle;
|
||||
@@ -33,7 +29,7 @@ public class Solenoid extends SolenoidBase implements LiveWindowSendable {
|
||||
* @param channel The channel on the PCM to control (0..7).
|
||||
*/
|
||||
public Solenoid(final int channel) {
|
||||
this(getDefaultSolenoidModule(), channel);
|
||||
this(SensorBase.getDefaultSolenoidModule(), channel);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -46,26 +42,24 @@ public class Solenoid extends SolenoidBase implements LiveWindowSendable {
|
||||
super(moduleNumber);
|
||||
m_channel = channel;
|
||||
|
||||
checkSolenoidModule(m_moduleNumber);
|
||||
checkSolenoidChannel(m_channel);
|
||||
SensorBase.checkSolenoidModule(m_moduleNumber);
|
||||
SensorBase.checkSolenoidChannel(m_channel);
|
||||
|
||||
int portHandle = SolenoidJNI.getPortWithModule((byte) m_moduleNumber, (byte) m_channel);
|
||||
m_solenoidHandle = SolenoidJNI.initializeSolenoidPort(portHandle);
|
||||
|
||||
LiveWindow.addActuator("Solenoid", m_moduleNumber, m_channel, this);
|
||||
HAL.report(tResourceType.kResourceType_Solenoid, m_channel, m_moduleNumber);
|
||||
setName("Solenoid", m_moduleNumber, m_channel);
|
||||
}
|
||||
|
||||
/**
|
||||
* Destructor.
|
||||
*/
|
||||
@Override
|
||||
public synchronized void free() {
|
||||
super.free();
|
||||
SolenoidJNI.freeSolenoidPort(m_solenoidHandle);
|
||||
m_solenoidHandle = 0;
|
||||
if (m_valueEntry != null) {
|
||||
m_valueEntry.removeListener(m_valueListener);
|
||||
}
|
||||
super.free();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -122,44 +116,10 @@ public class Solenoid extends SolenoidBase implements LiveWindowSendable {
|
||||
SolenoidJNI.fireOneShot(m_solenoidHandle);
|
||||
}
|
||||
|
||||
/*
|
||||
* Live Window code, only does anything if live window is activated.
|
||||
*/
|
||||
public String getSmartDashboardType() {
|
||||
return "Solenoid";
|
||||
}
|
||||
|
||||
private NetworkTableEntry m_valueEntry;
|
||||
private int m_valueListener;
|
||||
|
||||
@Override
|
||||
public void initTable(NetworkTable subtable) {
|
||||
if (subtable != null) {
|
||||
m_valueEntry = subtable.getEntry("Value");
|
||||
updateTable();
|
||||
} else {
|
||||
m_valueEntry = null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateTable() {
|
||||
if (m_valueEntry != null) {
|
||||
m_valueEntry.setBoolean(get());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void startLiveWindowMode() {
|
||||
set(false); // Stop for safety
|
||||
m_valueListener = m_valueEntry.addListener((event) -> set(event.value.getBoolean()),
|
||||
EntryListenerFlags.kImmediate | EntryListenerFlags.kNew | EntryListenerFlags.kUpdate);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stopLiveWindowMode() {
|
||||
set(false); // Stop for safety
|
||||
m_valueEntry.removeListener(m_valueListener);
|
||||
m_valueListener = 0;
|
||||
public void initSendable(SendableBuilder builder) {
|
||||
builder.setSmartDashboardType("Solenoid");
|
||||
builder.setSafeState(() -> set(false));
|
||||
builder.addBooleanProperty("Value", this::get, this::set);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@ import edu.wpi.first.wpilibj.hal.SolenoidJNI;
|
||||
* SolenoidBase class is the common base class for the {@link Solenoid} and {@link DoubleSolenoid}
|
||||
* classes.
|
||||
*/
|
||||
public abstract class SolenoidBase extends SensorBase {
|
||||
public abstract class SolenoidBase extends SendableBase {
|
||||
|
||||
protected final int m_moduleNumber; // The number of the solenoid module being used.
|
||||
|
||||
|
||||
@@ -9,7 +9,6 @@ package edu.wpi.first.wpilibj;
|
||||
|
||||
import edu.wpi.first.wpilibj.hal.FRCNetComm.tResourceType;
|
||||
import edu.wpi.first.wpilibj.hal.HAL;
|
||||
import edu.wpi.first.wpilibj.livewindow.LiveWindow;
|
||||
|
||||
/**
|
||||
* REV Robotics SPARK Speed Controller.
|
||||
@@ -35,8 +34,8 @@ public class Spark extends PWMSpeedController {
|
||||
setSpeed(0.0);
|
||||
setZeroLatch();
|
||||
|
||||
LiveWindow.addActuator("Spark", getChannel(), this);
|
||||
HAL.report(tResourceType.kResourceType_RevSPARK, getChannel());
|
||||
setName("Spark", getChannel());
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -7,13 +7,16 @@
|
||||
|
||||
package edu.wpi.first.wpilibj;
|
||||
|
||||
import edu.wpi.first.wpilibj.smartdashboard.SendableBuilder;
|
||||
|
||||
/**
|
||||
* Allows multiple {@link SpeedController} objects to be linked together.
|
||||
*/
|
||||
public class SpeedControllerGroup implements SpeedController {
|
||||
public class SpeedControllerGroup extends SendableBase implements SpeedController {
|
||||
|
||||
private boolean m_isInverted = false;
|
||||
private final SpeedController[] m_speedControllers;
|
||||
private static int instances = 0;
|
||||
|
||||
/**
|
||||
* Create a new SpeedControllerGroup with the provided SpeedControllers.
|
||||
@@ -24,9 +27,13 @@ public class SpeedControllerGroup implements SpeedController {
|
||||
SpeedController... speedControllers) {
|
||||
m_speedControllers = new SpeedController[speedControllers.length + 1];
|
||||
m_speedControllers[0] = speedController;
|
||||
addChild(speedController);
|
||||
for (int i = 0; i < speedControllers.length; i++) {
|
||||
m_speedControllers[i + 1] = speedControllers[i];
|
||||
addChild(speedControllers[i]);
|
||||
}
|
||||
instances++;
|
||||
setName("SpeedControllerGroup", instances);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -74,4 +81,11 @@ public class SpeedControllerGroup implements SpeedController {
|
||||
speedController.pidWrite(output);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initSendable(SendableBuilder builder) {
|
||||
builder.setSmartDashboardType("Speed Controller");
|
||||
builder.setSafeState(this::stopMotor);
|
||||
builder.addDoubleProperty("Value", this::get, this::set);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,7 +9,6 @@ package edu.wpi.first.wpilibj;
|
||||
|
||||
import edu.wpi.first.wpilibj.hal.FRCNetComm.tResourceType;
|
||||
import edu.wpi.first.wpilibj.hal.HAL;
|
||||
import edu.wpi.first.wpilibj.livewindow.LiveWindow;
|
||||
|
||||
/**
|
||||
* Cross the Road Electronics (CTRE) Talon and Talon SR Speed Controller.
|
||||
@@ -40,7 +39,7 @@ public class Talon extends PWMSpeedController {
|
||||
setSpeed(0.0);
|
||||
setZeroLatch();
|
||||
|
||||
LiveWindow.addActuator("Talon", getChannel(), this);
|
||||
HAL.report(tResourceType.kResourceType_Talon, getChannel());
|
||||
setName("Talon", getChannel());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,12 +7,9 @@
|
||||
|
||||
package edu.wpi.first.wpilibj;
|
||||
|
||||
import edu.wpi.first.networktables.NetworkTable;
|
||||
import edu.wpi.first.networktables.NetworkTableEntry;
|
||||
import edu.wpi.first.wpilibj.hal.FRCNetComm.tResourceType;
|
||||
import edu.wpi.first.wpilibj.hal.HAL;
|
||||
import edu.wpi.first.wpilibj.livewindow.LiveWindow;
|
||||
import edu.wpi.first.wpilibj.livewindow.LiveWindowSendable;
|
||||
import edu.wpi.first.wpilibj.smartdashboard.SendableBuilder;
|
||||
|
||||
import static java.util.Objects.requireNonNull;
|
||||
|
||||
@@ -25,7 +22,7 @@ import static java.util.Objects.requireNonNull;
|
||||
* echo is received. The time that the line is high determines the round trip distance (time of
|
||||
* flight).
|
||||
*/
|
||||
public class Ultrasonic extends SensorBase implements PIDSource, LiveWindowSendable {
|
||||
public class Ultrasonic extends SensorBase implements PIDSource, Sendable {
|
||||
|
||||
/**
|
||||
* The units to return when PIDGet is called.
|
||||
@@ -107,6 +104,7 @@ public class Ultrasonic extends SensorBase implements PIDSource, LiveWindowSenda
|
||||
m_firstSensor = this;
|
||||
|
||||
m_counter = new Counter(m_echoChannel); // set up counter for this
|
||||
addChild(m_counter);
|
||||
// sensor
|
||||
m_counter.setMaxPeriod(1.0);
|
||||
m_counter.setSemiPeriodMode(true);
|
||||
@@ -116,7 +114,7 @@ public class Ultrasonic extends SensorBase implements PIDSource, LiveWindowSenda
|
||||
|
||||
m_instances++;
|
||||
HAL.report(tResourceType.kResourceType_Ultrasonic, m_instances);
|
||||
LiveWindow.addSensor("Ultrasonic", m_echoChannel.getChannel(), this);
|
||||
setName("Ultrasonic", m_echoChannel.getChannel());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -133,6 +131,8 @@ public class Ultrasonic extends SensorBase implements PIDSource, LiveWindowSenda
|
||||
public Ultrasonic(final int pingChannel, final int echoChannel, Unit units) {
|
||||
m_pingChannel = new DigitalOutput(pingChannel);
|
||||
m_echoChannel = new DigitalInput(echoChannel);
|
||||
addChild(m_pingChannel);
|
||||
addChild(m_echoChannel);
|
||||
m_allocatedChannels = true;
|
||||
m_units = units;
|
||||
initialize();
|
||||
@@ -194,6 +194,7 @@ public class Ultrasonic extends SensorBase implements PIDSource, LiveWindowSenda
|
||||
*/
|
||||
@Override
|
||||
public synchronized void free() {
|
||||
super.free();
|
||||
final boolean wasAutomaticMode = m_automaticEnabled;
|
||||
setAutomaticMode(false);
|
||||
if (m_allocatedChannels) {
|
||||
@@ -391,38 +392,9 @@ public class Ultrasonic extends SensorBase implements PIDSource, LiveWindowSenda
|
||||
m_enabled = enable;
|
||||
}
|
||||
|
||||
/**
|
||||
* Live Window code, only does anything if live window is activated.
|
||||
*/
|
||||
@Override
|
||||
public String getSmartDashboardType() {
|
||||
return "Ultrasonic";
|
||||
}
|
||||
|
||||
private NetworkTableEntry m_valueEntry;
|
||||
|
||||
@Override
|
||||
public void initTable(NetworkTable subtable) {
|
||||
if (subtable != null) {
|
||||
m_valueEntry = subtable.getEntry("Value");
|
||||
updateTable();
|
||||
} else {
|
||||
m_valueEntry = null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateTable() {
|
||||
if (m_valueEntry != null) {
|
||||
m_valueEntry.setDouble(getRangeInches());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void startLiveWindowMode() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stopLiveWindowMode() {
|
||||
public void initSendable(SendableBuilder builder) {
|
||||
builder.setSmartDashboardType("Ultrasonic");
|
||||
builder.addDoubleProperty("Value", this::getRangeInches, null);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,7 +9,6 @@ package edu.wpi.first.wpilibj;
|
||||
|
||||
import edu.wpi.first.wpilibj.hal.FRCNetComm.tResourceType;
|
||||
import edu.wpi.first.wpilibj.hal.HAL;
|
||||
import edu.wpi.first.wpilibj.livewindow.LiveWindow;
|
||||
|
||||
/**
|
||||
* VEX Robotics Victor 888 Speed Controller The Vex Robotics Victor 884 Speed Controller can also
|
||||
@@ -42,7 +41,7 @@ public class Victor extends PWMSpeedController {
|
||||
setSpeed(0.0);
|
||||
setZeroLatch();
|
||||
|
||||
LiveWindow.addActuator("Victor", getChannel(), this);
|
||||
HAL.report(tResourceType.kResourceType_Victor, getChannel());
|
||||
setName("Victor", getChannel());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,7 +9,6 @@ package edu.wpi.first.wpilibj;
|
||||
|
||||
import edu.wpi.first.wpilibj.hal.FRCNetComm.tResourceType;
|
||||
import edu.wpi.first.wpilibj.hal.HAL;
|
||||
import edu.wpi.first.wpilibj.livewindow.LiveWindow;
|
||||
|
||||
/**
|
||||
* VEX Robotics Victor SP Speed Controller.
|
||||
@@ -40,7 +39,7 @@ public class VictorSP extends PWMSpeedController {
|
||||
setSpeed(0.0);
|
||||
setZeroLatch();
|
||||
|
||||
LiveWindow.addActuator("VictorSP", getChannel(), this);
|
||||
HAL.report(tResourceType.kResourceType_VictorSP, getChannel());
|
||||
setName("VictorSP", getChannel());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,11 +7,10 @@
|
||||
|
||||
package edu.wpi.first.wpilibj.buttons;
|
||||
|
||||
import edu.wpi.first.networktables.NetworkTable;
|
||||
import edu.wpi.first.networktables.NetworkTableEntry;
|
||||
import edu.wpi.first.wpilibj.Sendable;
|
||||
import edu.wpi.first.wpilibj.SendableBase;
|
||||
import edu.wpi.first.wpilibj.command.Command;
|
||||
import edu.wpi.first.wpilibj.command.Scheduler;
|
||||
import edu.wpi.first.wpilibj.smartdashboard.SendableBuilder;
|
||||
|
||||
/**
|
||||
* This class provides an easy way to link commands to inputs.
|
||||
@@ -24,7 +23,9 @@ import edu.wpi.first.wpilibj.command.Scheduler;
|
||||
* certain sensor input). For this, they only have to write the {@link Trigger#get()} method to get
|
||||
* the full functionality of the Trigger class.
|
||||
*/
|
||||
public abstract class Trigger implements Sendable {
|
||||
public abstract class Trigger extends SendableBase {
|
||||
|
||||
private volatile boolean m_sendablePressed = false;
|
||||
|
||||
/**
|
||||
* Returns whether or not the trigger is active.
|
||||
@@ -42,8 +43,7 @@ public abstract class Trigger implements Sendable {
|
||||
*/
|
||||
@SuppressWarnings("PMD.UselessParentheses")
|
||||
private boolean grab() {
|
||||
return get() || (m_pressedEntry != null && m_pressedEntry.getBoolean(false));
|
||||
|
||||
return get() || m_sendablePressed;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -186,24 +186,14 @@ public abstract class Trigger implements Sendable {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* These methods continue to return the "Button" SmartDashboard type until we decided to create a
|
||||
* Trigger widget type for the dashboard.
|
||||
*/
|
||||
@Override
|
||||
public String getSmartDashboardType() {
|
||||
return "Button";
|
||||
}
|
||||
|
||||
private NetworkTableEntry m_pressedEntry;
|
||||
|
||||
@Override
|
||||
public void initTable(NetworkTable table) {
|
||||
if (table != null) {
|
||||
m_pressedEntry = table.getEntry("pressed");
|
||||
m_pressedEntry.setBoolean(get());
|
||||
} else {
|
||||
m_pressedEntry = null;
|
||||
}
|
||||
public void initSendable(SendableBuilder builder) {
|
||||
builder.setSmartDashboardType("Button");
|
||||
builder.setSafeState(() -> {
|
||||
m_sendablePressed = false;
|
||||
});
|
||||
builder.addBooleanProperty("pressed", this::grab, (value) -> {
|
||||
m_sendablePressed = value;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,12 +9,11 @@ package edu.wpi.first.wpilibj.command;
|
||||
|
||||
import java.util.Enumeration;
|
||||
|
||||
import edu.wpi.first.networktables.EntryListenerFlags;
|
||||
import edu.wpi.first.networktables.NetworkTable;
|
||||
import edu.wpi.first.networktables.NetworkTableEntry;
|
||||
import edu.wpi.first.wpilibj.NamedSendable;
|
||||
import edu.wpi.first.wpilibj.RobotState;
|
||||
import edu.wpi.first.wpilibj.Sendable;
|
||||
import edu.wpi.first.wpilibj.SendableBase;
|
||||
import edu.wpi.first.wpilibj.Timer;
|
||||
import edu.wpi.first.wpilibj.smartdashboard.SendableBuilder;
|
||||
|
||||
/**
|
||||
* The Command class is at the very core of the entire command framework. Every command can be
|
||||
@@ -41,12 +40,7 @@ import edu.wpi.first.wpilibj.Timer;
|
||||
* @see CommandGroup
|
||||
* @see IllegalUseOfCommandException
|
||||
*/
|
||||
public abstract class Command implements NamedSendable {
|
||||
/**
|
||||
* The name of this command.
|
||||
*/
|
||||
private String m_name;
|
||||
|
||||
public abstract class Command extends SendableBase implements Sendable {
|
||||
/**
|
||||
* The time since this command was initialized.
|
||||
*/
|
||||
@@ -101,8 +95,9 @@ public abstract class Command implements NamedSendable {
|
||||
* Creates a new command. The name of this command will be set to its class name.
|
||||
*/
|
||||
public Command() {
|
||||
m_name = getClass().getName();
|
||||
m_name = m_name.substring(m_name.lastIndexOf('.') + 1);
|
||||
super(false);
|
||||
String name = getClass().getName();
|
||||
setName(name.substring(name.lastIndexOf('.') + 1));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -112,10 +107,11 @@ public abstract class Command implements NamedSendable {
|
||||
* @throws IllegalArgumentException if name is null
|
||||
*/
|
||||
public Command(String name) {
|
||||
super(false);
|
||||
if (name == null) {
|
||||
throw new IllegalArgumentException("Name must not be null.");
|
||||
}
|
||||
m_name = name;
|
||||
setName(name);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -150,16 +146,6 @@ public abstract class Command implements NamedSendable {
|
||||
m_timeout = timeout;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the name of this command. If no name was specified in the constructor, then the default
|
||||
* is the name of the class.
|
||||
*
|
||||
* @return the name of this command
|
||||
*/
|
||||
public String getName() {
|
||||
return m_name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the timeout of this command.
|
||||
*
|
||||
@@ -222,9 +208,6 @@ public abstract class Command implements NamedSendable {
|
||||
m_initialized = false;
|
||||
m_canceled = false;
|
||||
m_running = false;
|
||||
if (m_runningEntry != null) {
|
||||
m_runningEntry.setBoolean(false);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -387,9 +370,15 @@ public abstract class Command implements NamedSendable {
|
||||
}
|
||||
lockChanges();
|
||||
m_parent = parent;
|
||||
if (m_isParentedEntry != null) {
|
||||
m_isParentedEntry.setBoolean(true);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the command has a parent.
|
||||
*
|
||||
* @param True if the command has a parent.
|
||||
*/
|
||||
synchronized boolean isParented() {
|
||||
return m_parent != null;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -429,9 +418,6 @@ public abstract class Command implements NamedSendable {
|
||||
synchronized void startRunning() {
|
||||
m_running = true;
|
||||
m_startTime = -1;
|
||||
if (m_runningEntry != null) {
|
||||
m_runningEntry.setBoolean(true);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -550,36 +536,21 @@ public abstract class Command implements NamedSendable {
|
||||
return getName();
|
||||
}
|
||||
|
||||
|
||||
public String getSmartDashboardType() {
|
||||
return "Command";
|
||||
}
|
||||
|
||||
private NetworkTableEntry m_runningEntry;
|
||||
private NetworkTableEntry m_isParentedEntry;
|
||||
private int m_runningListener;
|
||||
|
||||
@Override
|
||||
public void initTable(NetworkTable table) {
|
||||
if (m_runningEntry != null) {
|
||||
m_runningEntry.removeListener(m_runningListener);
|
||||
}
|
||||
if (table != null) {
|
||||
m_runningEntry = table.getEntry("running");
|
||||
m_isParentedEntry = table.getEntry(".isParented");
|
||||
table.getEntry(".name").setString(getName());
|
||||
m_runningEntry.setBoolean(isRunning());
|
||||
m_isParentedEntry.setBoolean(m_parent != null);
|
||||
m_runningListener = m_runningEntry.addListener((event) -> {
|
||||
if (event.value.getBoolean()) {
|
||||
public void initSendable(SendableBuilder builder) {
|
||||
builder.setSmartDashboardType("Command");
|
||||
builder.addStringProperty(".name", this::getName, null);
|
||||
builder.addBooleanProperty("running", this::isRunning, (value) -> {
|
||||
if (value) {
|
||||
if (!isRunning()) {
|
||||
start();
|
||||
} else {
|
||||
}
|
||||
} else {
|
||||
if (isRunning()) {
|
||||
cancel();
|
||||
}
|
||||
}, EntryListenerFlags.kImmediate | EntryListenerFlags.kNew | EntryListenerFlags.kUpdate);
|
||||
} else {
|
||||
m_runningEntry = null;
|
||||
m_isParentedEntry = null;
|
||||
}
|
||||
}
|
||||
});
|
||||
builder.addBooleanProperty(".isParented", this::isParented, null);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,12 +7,12 @@
|
||||
|
||||
package edu.wpi.first.wpilibj.command;
|
||||
|
||||
import edu.wpi.first.networktables.NetworkTable;
|
||||
import edu.wpi.first.wpilibj.PIDController;
|
||||
import edu.wpi.first.wpilibj.PIDOutput;
|
||||
import edu.wpi.first.wpilibj.PIDSource;
|
||||
import edu.wpi.first.wpilibj.PIDSourceType;
|
||||
import edu.wpi.first.wpilibj.Sendable;
|
||||
import edu.wpi.first.wpilibj.smartdashboard.SendableBuilder;
|
||||
|
||||
/**
|
||||
* This class defines a {@link Command} which interacts heavily with a PID loop.
|
||||
@@ -209,12 +209,10 @@ public abstract class PIDCommand extends Command implements Sendable {
|
||||
*/
|
||||
protected abstract void usePIDOutput(double output);
|
||||
|
||||
public String getSmartDashboardType() {
|
||||
return "PIDCommand";
|
||||
}
|
||||
|
||||
public void initTable(NetworkTable table) {
|
||||
m_controller.initTable(table);
|
||||
super.initTable(table);
|
||||
@Override
|
||||
public void initSendable(SendableBuilder builder) {
|
||||
m_controller.initSendable(builder);
|
||||
super.initSendable(builder);
|
||||
builder.setSmartDashboardType("PIDCommand");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,7 +7,6 @@
|
||||
|
||||
package edu.wpi.first.wpilibj.command;
|
||||
|
||||
import edu.wpi.first.networktables.NetworkTable;
|
||||
import edu.wpi.first.wpilibj.PIDController;
|
||||
import edu.wpi.first.wpilibj.PIDOutput;
|
||||
import edu.wpi.first.wpilibj.PIDSource;
|
||||
@@ -62,6 +61,7 @@ public abstract class PIDSubsystem extends Subsystem implements Sendable {
|
||||
public PIDSubsystem(String name, double p, double i, double d) {
|
||||
super(name);
|
||||
m_controller = new PIDController(p, i, d, m_source, m_output);
|
||||
addChild("PIDController", m_controller);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -77,6 +77,7 @@ public abstract class PIDSubsystem extends Subsystem implements Sendable {
|
||||
public PIDSubsystem(String name, double p, double i, double d, double f) {
|
||||
super(name);
|
||||
m_controller = new PIDController(p, i, d, f, m_source, m_output);
|
||||
addChild("PIDController", m_controller);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -93,6 +94,7 @@ public abstract class PIDSubsystem extends Subsystem implements Sendable {
|
||||
public PIDSubsystem(String name, double p, double i, double d, double f, double period) {
|
||||
super(name);
|
||||
m_controller = new PIDController(p, i, d, f, m_source, m_output, period);
|
||||
addChild("PIDController", m_controller);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -106,6 +108,7 @@ public abstract class PIDSubsystem extends Subsystem implements Sendable {
|
||||
@SuppressWarnings("ParameterName")
|
||||
public PIDSubsystem(double p, double i, double d) {
|
||||
m_controller = new PIDController(p, i, d, m_source, m_output);
|
||||
addChild("PIDController", m_controller);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -122,6 +125,7 @@ public abstract class PIDSubsystem extends Subsystem implements Sendable {
|
||||
@SuppressWarnings("ParameterName")
|
||||
public PIDSubsystem(double p, double i, double d, double period, double f) {
|
||||
m_controller = new PIDController(p, i, d, f, m_source, m_output, period);
|
||||
addChild("PIDController", m_controller);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -137,6 +141,7 @@ public abstract class PIDSubsystem extends Subsystem implements Sendable {
|
||||
@SuppressWarnings("ParameterName")
|
||||
public PIDSubsystem(double p, double i, double d, double period) {
|
||||
m_controller = new PIDController(p, i, d, m_source, m_output, period);
|
||||
addChild("PIDController", m_controller);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -277,15 +282,4 @@ public abstract class PIDSubsystem extends Subsystem implements Sendable {
|
||||
public void disable() {
|
||||
m_controller.disable();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSmartDashboardType() {
|
||||
return "PIDSubsystem";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initTable(NetworkTable table) {
|
||||
m_controller.initTable(table);
|
||||
super.initTable(table);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,11 +11,12 @@ import java.util.Enumeration;
|
||||
import java.util.Hashtable;
|
||||
import java.util.Vector;
|
||||
|
||||
import edu.wpi.first.networktables.NetworkTable;
|
||||
import edu.wpi.first.networktables.NetworkTableEntry;
|
||||
import edu.wpi.first.wpilibj.HLUsageReporting;
|
||||
import edu.wpi.first.wpilibj.NamedSendable;
|
||||
import edu.wpi.first.wpilibj.Sendable;
|
||||
import edu.wpi.first.wpilibj.SendableBase;
|
||||
import edu.wpi.first.wpilibj.buttons.Trigger.ButtonScheduler;
|
||||
import edu.wpi.first.wpilibj.smartdashboard.SendableBuilder;
|
||||
|
||||
/**
|
||||
* The {@link Scheduler} is a singleton which holds the top-level running commands. It is in charge
|
||||
@@ -29,7 +30,7 @@ import edu.wpi.first.wpilibj.buttons.Trigger.ButtonScheduler;
|
||||
*
|
||||
* @see Command
|
||||
*/
|
||||
public class Scheduler implements NamedSendable {
|
||||
public class Scheduler extends SendableBase implements Sendable {
|
||||
|
||||
/**
|
||||
* The Singleton Instance.
|
||||
@@ -91,6 +92,7 @@ public class Scheduler implements NamedSendable {
|
||||
*/
|
||||
private Scheduler() {
|
||||
HLUsageReporting.reportScheduler();
|
||||
setName("Scheduler");
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -237,8 +239,6 @@ public class Scheduler implements NamedSendable {
|
||||
}
|
||||
lock.confirmCommand();
|
||||
}
|
||||
|
||||
updateTable();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -307,67 +307,44 @@ public class Scheduler implements NamedSendable {
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "Scheduler";
|
||||
}
|
||||
|
||||
public String getType() {
|
||||
return "Scheduler";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initTable(NetworkTable subtable) {
|
||||
if (subtable != null) {
|
||||
m_namesEntry = subtable.getEntry("Names");
|
||||
m_idsEntry = subtable.getEntry("Ids");
|
||||
m_cancelEntry = subtable.getEntry("Cancel");
|
||||
m_namesEntry.setStringArray(new String[0]);
|
||||
m_idsEntry.setDoubleArray(new double[0]);
|
||||
m_cancelEntry.setDoubleArray(new double[0]);
|
||||
} else {
|
||||
m_namesEntry = null;
|
||||
m_idsEntry = null;
|
||||
m_cancelEntry = null;
|
||||
}
|
||||
}
|
||||
|
||||
private void updateTable() {
|
||||
if (m_namesEntry != null && m_idsEntry != null && m_cancelEntry != null) {
|
||||
// Get the commands to cancel
|
||||
double[] toCancel = m_cancelEntry.getDoubleArray(new double[0]);
|
||||
if (toCancel.length > 0) {
|
||||
for (LinkedListElement e = m_firstCommand; e != null; e = e.getNext()) {
|
||||
for (double d : toCancel) {
|
||||
if (e.getData().hashCode() == d) {
|
||||
e.getData().cancel();
|
||||
public void initSendable(SendableBuilder builder) {
|
||||
builder.setSmartDashboardType("Scheduler");
|
||||
m_namesEntry = builder.getEntry("Names");
|
||||
m_idsEntry = builder.getEntry("Ids");
|
||||
m_cancelEntry = builder.getEntry("Cancel");
|
||||
builder.setUpdateTable(() -> {
|
||||
if (m_namesEntry != null && m_idsEntry != null && m_cancelEntry != null) {
|
||||
// Get the commands to cancel
|
||||
double[] toCancel = m_cancelEntry.getDoubleArray(new double[0]);
|
||||
if (toCancel.length > 0) {
|
||||
for (LinkedListElement e = m_firstCommand; e != null; e = e.getNext()) {
|
||||
for (double d : toCancel) {
|
||||
if (e.getData().hashCode() == d) {
|
||||
e.getData().cancel();
|
||||
}
|
||||
}
|
||||
}
|
||||
m_cancelEntry.setDoubleArray(new double[0]);
|
||||
}
|
||||
m_cancelEntry.setDoubleArray(new double[0]);
|
||||
}
|
||||
|
||||
if (m_runningCommandsChanged) {
|
||||
// Set the the running commands
|
||||
int number = 0;
|
||||
for (LinkedListElement e = m_firstCommand; e != null; e = e.getNext()) {
|
||||
number++;
|
||||
if (m_runningCommandsChanged) {
|
||||
// Set the the running commands
|
||||
int number = 0;
|
||||
for (LinkedListElement e = m_firstCommand; e != null; e = e.getNext()) {
|
||||
number++;
|
||||
}
|
||||
String[] commands = new String[number];
|
||||
double[] ids = new double[number];
|
||||
number = 0;
|
||||
for (LinkedListElement e = m_firstCommand; e != null; e = e.getNext()) {
|
||||
commands[number] = e.getData().getName();
|
||||
ids[number] = e.getData().hashCode();
|
||||
number++;
|
||||
}
|
||||
m_namesEntry.setStringArray(commands);
|
||||
m_idsEntry.setDoubleArray(ids);
|
||||
}
|
||||
String[] commands = new String[number];
|
||||
double[] ids = new double[number];
|
||||
number = 0;
|
||||
for (LinkedListElement e = m_firstCommand; e != null; e = e.getNext()) {
|
||||
commands[number] = e.getData().getName();
|
||||
ids[number] = e.getData().hashCode();
|
||||
number++;
|
||||
}
|
||||
m_namesEntry.setStringArray(commands);
|
||||
m_idsEntry.setDoubleArray(ids);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSmartDashboardType() {
|
||||
return "Scheduler";
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,9 +9,10 @@ package edu.wpi.first.wpilibj.command;
|
||||
|
||||
import java.util.Enumeration;
|
||||
|
||||
import edu.wpi.first.networktables.NetworkTable;
|
||||
import edu.wpi.first.networktables.NetworkTableEntry;
|
||||
import edu.wpi.first.wpilibj.NamedSendable;
|
||||
import edu.wpi.first.wpilibj.Sendable;
|
||||
import edu.wpi.first.wpilibj.SendableBase;
|
||||
import edu.wpi.first.wpilibj.livewindow.LiveWindow;
|
||||
import edu.wpi.first.wpilibj.smartdashboard.SendableBuilder;
|
||||
|
||||
/**
|
||||
* This class defines a major component of the robot.
|
||||
@@ -27,7 +28,7 @@ import edu.wpi.first.wpilibj.NamedSendable;
|
||||
*
|
||||
* @see Command
|
||||
*/
|
||||
public abstract class Subsystem implements NamedSendable {
|
||||
public abstract class Subsystem extends SendableBase implements Sendable {
|
||||
|
||||
/**
|
||||
* Whether or not getDefaultCommand() was called.
|
||||
@@ -43,10 +44,6 @@ public abstract class Subsystem implements NamedSendable {
|
||||
* The default command.
|
||||
*/
|
||||
private Command m_defaultCommand;
|
||||
/**
|
||||
* The name.
|
||||
*/
|
||||
private String m_name;
|
||||
|
||||
/**
|
||||
* Creates a subsystem with the given name.
|
||||
@@ -54,7 +51,7 @@ public abstract class Subsystem implements NamedSendable {
|
||||
* @param name the name of the subsystem
|
||||
*/
|
||||
public Subsystem(String name) {
|
||||
m_name = name;
|
||||
setName(name, name);
|
||||
Scheduler.getInstance().registerSubsystem(this);
|
||||
}
|
||||
|
||||
@@ -62,7 +59,9 @@ public abstract class Subsystem implements NamedSendable {
|
||||
* Creates a subsystem. This will set the name to the name of the class.
|
||||
*/
|
||||
public Subsystem() {
|
||||
m_name = getClass().getName().substring(getClass().getName().lastIndexOf('.') + 1);
|
||||
String name = getClass().getName();
|
||||
name = name.substring(name.lastIndexOf('.') + 1);
|
||||
setName(name, name);
|
||||
Scheduler.getInstance().registerSubsystem(this);
|
||||
m_currentCommandChanged = true;
|
||||
}
|
||||
@@ -110,14 +109,6 @@ public abstract class Subsystem implements NamedSendable {
|
||||
}
|
||||
m_defaultCommand = command;
|
||||
}
|
||||
if (m_hasDefaultEntry != null && m_defaultEntry != null) {
|
||||
if (m_defaultCommand != null) {
|
||||
m_hasDefaultEntry.setBoolean(true);
|
||||
m_defaultEntry.setString(m_defaultCommand.getName());
|
||||
} else {
|
||||
m_hasDefaultEntry.setBoolean(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -125,7 +116,7 @@ public abstract class Subsystem implements NamedSendable {
|
||||
*
|
||||
* @return the default command
|
||||
*/
|
||||
protected Command getDefaultCommand() {
|
||||
public Command getDefaultCommand() {
|
||||
if (!m_initializedDefaultCommand) {
|
||||
m_initializedDefaultCommand = true;
|
||||
initDefaultCommand();
|
||||
@@ -133,6 +124,20 @@ public abstract class Subsystem implements NamedSendable {
|
||||
return m_defaultCommand;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the default command name, or empty string is there is none.
|
||||
*
|
||||
* @return the default command name
|
||||
*/
|
||||
public String getDefaultCommandName() {
|
||||
Command defaultCommand = getDefaultCommand();
|
||||
if (defaultCommand != null) {
|
||||
return defaultCommand.getName();
|
||||
} else {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the current command.
|
||||
*
|
||||
@@ -150,14 +155,6 @@ public abstract class Subsystem implements NamedSendable {
|
||||
*/
|
||||
void confirmCommand() {
|
||||
if (m_currentCommandChanged) {
|
||||
if (m_hasCommandEntry != null && m_commandEntry != null) {
|
||||
if (m_currentCommand != null) {
|
||||
m_hasCommandEntry.setBoolean(true);
|
||||
m_commandEntry.setString(m_currentCommand.getName());
|
||||
} else {
|
||||
m_hasCommandEntry.setBoolean(false);
|
||||
}
|
||||
}
|
||||
m_currentCommandChanged = false;
|
||||
}
|
||||
}
|
||||
@@ -171,51 +168,54 @@ public abstract class Subsystem implements NamedSendable {
|
||||
return m_currentCommand;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return getName();
|
||||
/**
|
||||
* Returns the current command name, or empty string if no current command.
|
||||
*
|
||||
* @return the current command name
|
||||
*/
|
||||
public String getCurrentCommandName() {
|
||||
Command currentCommand = getCurrentCommand();
|
||||
if (currentCommand != null) {
|
||||
return currentCommand.getName();
|
||||
} else {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the name of this subsystem, which is by default the class name.
|
||||
* Associate a {@link Sendable} with this Subsystem.
|
||||
* Also update the child's name.
|
||||
*
|
||||
* @return the name of this subsystem
|
||||
* @param name name to give child
|
||||
* @param child sendable
|
||||
*/
|
||||
@Override
|
||||
public String getName() {
|
||||
return m_name;
|
||||
public void addChild(String name, Sendable child) {
|
||||
child.setName(getSubsystem(), name);
|
||||
LiveWindow.add(child);
|
||||
}
|
||||
|
||||
/**
|
||||
* Associate a {@link Sendable} with this Subsystem.
|
||||
*
|
||||
* @param child sendable
|
||||
*/
|
||||
public void addChild(Sendable child) {
|
||||
child.setSubsystem(getSubsystem());
|
||||
LiveWindow.add(child);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSmartDashboardType() {
|
||||
return "Subsystem";
|
||||
public String toString() {
|
||||
return getSubsystem();
|
||||
}
|
||||
|
||||
private NetworkTableEntry m_hasDefaultEntry;
|
||||
private NetworkTableEntry m_defaultEntry;
|
||||
private NetworkTableEntry m_hasCommandEntry;
|
||||
private NetworkTableEntry m_commandEntry;
|
||||
|
||||
@Override
|
||||
public void initTable(NetworkTable table) {
|
||||
if (table != null) {
|
||||
m_hasDefaultEntry = table.getEntry("hasDefault");
|
||||
m_defaultEntry = table.getEntry("default");
|
||||
m_hasCommandEntry = table.getEntry("hasCommand");
|
||||
m_commandEntry = table.getEntry("command");
|
||||
public void initSendable(SendableBuilder builder) {
|
||||
builder.setSmartDashboardType("Subsystem");
|
||||
|
||||
if (m_defaultCommand != null) {
|
||||
m_hasDefaultEntry.setBoolean(true);
|
||||
m_defaultEntry.setString(m_defaultCommand.getName());
|
||||
} else {
|
||||
m_hasDefaultEntry.setBoolean(false);
|
||||
}
|
||||
if (m_currentCommand != null) {
|
||||
m_hasCommandEntry.setBoolean(true);
|
||||
m_commandEntry.setString(m_currentCommand.getName());
|
||||
} else {
|
||||
m_hasCommandEntry.setBoolean(false);
|
||||
}
|
||||
}
|
||||
builder.addBooleanProperty("hasDefault", () -> m_defaultCommand != null, null);
|
||||
builder.addStringProperty("default", this::getDefaultCommandName, null);
|
||||
builder.addBooleanProperty("hasCommand", () -> m_currentCommand != null, null);
|
||||
builder.addStringProperty("command", this::getCurrentCommandName, null);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@ import edu.wpi.first.wpilibj.SpeedController;
|
||||
import edu.wpi.first.wpilibj.hal.FRCNetComm.tInstances;
|
||||
import edu.wpi.first.wpilibj.hal.FRCNetComm.tResourceType;
|
||||
import edu.wpi.first.wpilibj.hal.HAL;
|
||||
import edu.wpi.first.wpilibj.smartdashboard.SendableBuilder;
|
||||
|
||||
/**
|
||||
* A class for driving differential drive/skid-steer drive platforms such as the Kit of Parts drive
|
||||
@@ -93,6 +94,8 @@ public class DifferentialDrive extends RobotDriveBase {
|
||||
public static final double kDefaultQuickStopThreshold = 0.2;
|
||||
public static final double kDefaultQuickStopAlpha = 0.1;
|
||||
|
||||
private static int instances = 0;
|
||||
|
||||
private SpeedController m_leftMotor;
|
||||
private SpeedController m_rightMotor;
|
||||
|
||||
@@ -110,6 +113,10 @@ public class DifferentialDrive extends RobotDriveBase {
|
||||
public DifferentialDrive(SpeedController leftMotor, SpeedController rightMotor) {
|
||||
m_leftMotor = leftMotor;
|
||||
m_rightMotor = rightMotor;
|
||||
addChild(m_leftMotor);
|
||||
addChild(m_rightMotor);
|
||||
instances++;
|
||||
setName("DifferentialDrive", instances);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -349,4 +356,11 @@ public class DifferentialDrive extends RobotDriveBase {
|
||||
public String getDescription() {
|
||||
return "DifferentialDrive";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initSendable(SendableBuilder builder) {
|
||||
builder.setSmartDashboardType("DifferentialDrive");
|
||||
builder.addDoubleProperty("Left Motor Speed", m_leftMotor::get, m_leftMotor::set);
|
||||
builder.addDoubleProperty("Right Motor Speed", m_rightMotor::get, m_rightMotor::set);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
package edu.wpi.first.wpilibj.drive;
|
||||
|
||||
import edu.wpi.first.wpilibj.SpeedController;
|
||||
import edu.wpi.first.wpilibj.smartdashboard.SendableBuilder;
|
||||
// import edu.wpi.first.wpilibj.hal.FRCNetComm.tInstances;
|
||||
// import edu.wpi.first.wpilibj.hal.FRCNetComm.tResourceType;
|
||||
// import edu.wpi.first.wpilibj.hal.HAL;
|
||||
@@ -41,6 +42,8 @@ public class KilloughDrive extends RobotDriveBase {
|
||||
public static final double kDefaultRightMotorAngle = 120.0;
|
||||
public static final double kDefaultBackMotorAngle = 270.0;
|
||||
|
||||
private static int instances = 0;
|
||||
|
||||
private SpeedController m_leftMotor;
|
||||
private SpeedController m_rightMotor;
|
||||
private SpeedController m_backMotor;
|
||||
@@ -93,6 +96,11 @@ public class KilloughDrive extends RobotDriveBase {
|
||||
Math.sin(rightMotorAngle * (Math.PI / 180.0)));
|
||||
m_backVec = new Vector2d(Math.cos(backMotorAngle * (Math.PI / 180.0)),
|
||||
Math.sin(backMotorAngle * (Math.PI / 180.0)));
|
||||
addChild(m_leftMotor);
|
||||
addChild(m_rightMotor);
|
||||
addChild(m_backMotor);
|
||||
instances++;
|
||||
setName("KilloughDrive", instances);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -192,4 +200,12 @@ public class KilloughDrive extends RobotDriveBase {
|
||||
public String getDescription() {
|
||||
return "KilloughDrive";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initSendable(SendableBuilder builder) {
|
||||
builder.setSmartDashboardType("KilloughDrive");
|
||||
builder.addDoubleProperty("Left Motor Speed", m_leftMotor::get, m_leftMotor::set);
|
||||
builder.addDoubleProperty("Right Motor Speed", m_rightMotor::get, m_rightMotor::set);
|
||||
builder.addDoubleProperty("Back Motor Speed", m_backMotor::get, m_backMotor::set);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@ import edu.wpi.first.wpilibj.SpeedController;
|
||||
import edu.wpi.first.wpilibj.hal.FRCNetComm.tInstances;
|
||||
import edu.wpi.first.wpilibj.hal.FRCNetComm.tResourceType;
|
||||
import edu.wpi.first.wpilibj.hal.HAL;
|
||||
import edu.wpi.first.wpilibj.smartdashboard.SendableBuilder;
|
||||
|
||||
/**
|
||||
* A class for driving Mecanum drive platforms.
|
||||
@@ -56,6 +57,8 @@ import edu.wpi.first.wpilibj.hal.HAL;
|
||||
* deadband of 0 is used.
|
||||
*/
|
||||
public class MecanumDrive extends RobotDriveBase {
|
||||
private static int instances = 0;
|
||||
|
||||
private SpeedController m_frontLeftMotor;
|
||||
private SpeedController m_rearLeftMotor;
|
||||
private SpeedController m_frontRightMotor;
|
||||
@@ -74,6 +77,12 @@ public class MecanumDrive extends RobotDriveBase {
|
||||
m_rearLeftMotor = rearLeftMotor;
|
||||
m_frontRightMotor = frontRightMotor;
|
||||
m_rearRightMotor = rearRightMotor;
|
||||
addChild(m_frontLeftMotor);
|
||||
addChild(m_rearLeftMotor);
|
||||
addChild(m_frontRightMotor);
|
||||
addChild(m_rearRightMotor);
|
||||
instances++;
|
||||
setName("MecanumDrive", instances);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -174,4 +183,17 @@ public class MecanumDrive extends RobotDriveBase {
|
||||
public String getDescription() {
|
||||
return "MecanumDrive";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initSendable(SendableBuilder builder) {
|
||||
builder.setSmartDashboardType("MecanumDrive");
|
||||
builder.addDoubleProperty("Front Left Motor Speed", m_frontLeftMotor::get,
|
||||
m_frontLeftMotor::set);
|
||||
builder.addDoubleProperty("Front Right Motor Speed", m_frontRightMotor::get,
|
||||
m_frontRightMotor::set);
|
||||
builder.addDoubleProperty("Rear Left Motor Speed", m_rearLeftMotor::get,
|
||||
m_rearLeftMotor::set);
|
||||
builder.addDoubleProperty("Rear Right Motor Speed", m_rearRightMotor::get,
|
||||
m_rearRightMotor::set);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,11 +9,12 @@ package edu.wpi.first.wpilibj.drive;
|
||||
|
||||
import edu.wpi.first.wpilibj.MotorSafety;
|
||||
import edu.wpi.first.wpilibj.MotorSafetyHelper;
|
||||
import edu.wpi.first.wpilibj.SendableBase;
|
||||
|
||||
/**
|
||||
* Common base class for drive platforms.
|
||||
*/
|
||||
public abstract class RobotDriveBase implements MotorSafety {
|
||||
public abstract class RobotDriveBase extends SendableBase implements MotorSafety {
|
||||
public static final double kDefaultDeadband = 0.02;
|
||||
public static final double kDefaultMaxOutput = 1.0;
|
||||
|
||||
@@ -38,6 +39,7 @@ public abstract class RobotDriveBase implements MotorSafety {
|
||||
|
||||
public RobotDriveBase() {
|
||||
m_safetyHelper.setSafetyEnabled(true);
|
||||
setName("RobotDriveBase");
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -7,14 +7,15 @@
|
||||
|
||||
package edu.wpi.first.wpilibj.livewindow;
|
||||
|
||||
import java.util.Enumeration;
|
||||
import java.util.Hashtable;
|
||||
import java.util.Vector;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import edu.wpi.first.networktables.NetworkTable;
|
||||
import edu.wpi.first.networktables.NetworkTableEntry;
|
||||
import edu.wpi.first.networktables.NetworkTableInstance;
|
||||
import edu.wpi.first.wpilibj.command.Scheduler;
|
||||
import edu.wpi.first.wpilibj.smartdashboard.SendableBuilderImpl;
|
||||
import edu.wpi.first.wpilibj.Sendable;
|
||||
|
||||
|
||||
/**
|
||||
@@ -23,42 +24,30 @@ import edu.wpi.first.wpilibj.command.Scheduler;
|
||||
*/
|
||||
public class LiveWindow {
|
||||
|
||||
private static Vector<LiveWindowSendable> sensors = new Vector<>();
|
||||
// private static Vector actuators = new Vector();
|
||||
private static Hashtable<LiveWindowSendable, LiveWindowComponent> components = new Hashtable<>();
|
||||
private static NetworkTable livewindowTable;
|
||||
private static NetworkTable statusTable;
|
||||
private static NetworkTableEntry enabledEntry;
|
||||
private static boolean liveWindowEnabled = false;
|
||||
private static boolean firstTime = true;
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
private static void initializeLiveWindowComponents() {
|
||||
System.out.println("Initializing the components first time");
|
||||
livewindowTable = NetworkTableInstance.getDefault().getTable("LiveWindow");
|
||||
statusTable = livewindowTable.getSubTable(".status");
|
||||
enabledEntry = statusTable.getEntry("LW Enabled");
|
||||
for (Enumeration e = components.keys(); e.hasMoreElements(); ) {
|
||||
LiveWindowSendable component = (LiveWindowSendable) e.nextElement();
|
||||
LiveWindowComponent liveWindowComponent = components.get(component);
|
||||
String subsystem = liveWindowComponent.getSubsystem();
|
||||
String name = liveWindowComponent.getName();
|
||||
System.out.println("Initializing table for '" + subsystem + "' '" + name + "'");
|
||||
livewindowTable.getSubTable(subsystem).getEntry(".type").setString("LW Subsystem");
|
||||
NetworkTable table = 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 (liveWindowComponent.isSensor()) {
|
||||
sensors.addElement(component);
|
||||
}
|
||||
private static class Component {
|
||||
Component(Sendable sendable, Sendable parent) {
|
||||
m_sendable = sendable;
|
||||
m_parent = parent;
|
||||
}
|
||||
|
||||
final Sendable m_sendable;
|
||||
Sendable m_parent;
|
||||
final SendableBuilderImpl m_builder = new SendableBuilderImpl();
|
||||
boolean m_firstTime = true;
|
||||
boolean m_telemetryEnabled = true;
|
||||
}
|
||||
|
||||
private static final Map<Object, Component> components = new HashMap<>();
|
||||
private static final NetworkTable liveWindowTable =
|
||||
NetworkTableInstance.getDefault().getTable("LiveWindow");
|
||||
private static final NetworkTable statusTable = liveWindowTable.getSubTable(".status");
|
||||
private static final NetworkTableEntry enabledEntry = statusTable.getEntry("LW Enabled");
|
||||
private static boolean startLiveWindow = false;
|
||||
private static boolean liveWindowEnabled = false;
|
||||
private static boolean telemetryEnabled = true;
|
||||
|
||||
public static synchronized boolean isEnabled() {
|
||||
return liveWindowEnabled;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -69,28 +58,21 @@ public class LiveWindow {
|
||||
* themselves when they get rescheduled. This prevents arms from starting to move around, etc.
|
||||
* after a period of adjusting them in LiveWindow mode.
|
||||
*/
|
||||
public static void setEnabled(boolean enabled) {
|
||||
public static synchronized void setEnabled(boolean enabled) {
|
||||
if (liveWindowEnabled != enabled) {
|
||||
Scheduler scheduler = Scheduler.getInstance();
|
||||
if (enabled) {
|
||||
System.out.println("Starting live window mode.");
|
||||
if (firstTime) {
|
||||
initializeLiveWindowComponents();
|
||||
firstTime = false;
|
||||
}
|
||||
Scheduler.getInstance().disable();
|
||||
Scheduler.getInstance().removeAll();
|
||||
for (Enumeration e = components.keys(); e.hasMoreElements(); ) {
|
||||
LiveWindowSendable component = (LiveWindowSendable) e.nextElement();
|
||||
component.startLiveWindowMode();
|
||||
}
|
||||
scheduler.disable();
|
||||
scheduler.removeAll();
|
||||
} else {
|
||||
System.out.println("stopping live window mode.");
|
||||
for (Enumeration e = components.keys(); e.hasMoreElements(); ) {
|
||||
LiveWindowSendable component = (LiveWindowSendable) e.nextElement();
|
||||
component.stopLiveWindowMode();
|
||||
for (Component component : components.values()) {
|
||||
component.m_builder.stopLiveWindowMode();
|
||||
}
|
||||
Scheduler.getInstance().enable();
|
||||
scheduler.enable();
|
||||
}
|
||||
startLiveWindow = enabled;
|
||||
liveWindowEnabled = enabled;
|
||||
enabledEntry.setBoolean(enabled);
|
||||
}
|
||||
@@ -98,7 +80,9 @@ public class LiveWindow {
|
||||
|
||||
/**
|
||||
* The run method is called repeatedly to keep the values refreshed on the screen in test mode.
|
||||
* @deprecated No longer required
|
||||
*/
|
||||
@Deprecated
|
||||
public static void run() {
|
||||
updateValues();
|
||||
}
|
||||
@@ -109,9 +93,12 @@ public class LiveWindow {
|
||||
* @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.
|
||||
* @deprecated Use {@link Sendable#setName(String, String)} instead.
|
||||
*/
|
||||
public static void addSensor(String subsystem, String name, LiveWindowSendable component) {
|
||||
components.put(component, new LiveWindowComponent(subsystem, name, true));
|
||||
@Deprecated
|
||||
public static synchronized void addSensor(String subsystem, String name, Sendable component) {
|
||||
add(component);
|
||||
component.setName(subsystem, name);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -121,13 +108,12 @@ public class LiveWindow {
|
||||
* @param moduleType A string indicating the type of the module used in the naming (above)
|
||||
* @param channel The channel number the device is connected to
|
||||
* @param component A reference to the object being added
|
||||
* @deprecated Use {@link edu.wpi.first.wpilibj.SensorBase#setName(String, int)} instead.
|
||||
*/
|
||||
public static void addSensor(String moduleType, int channel, LiveWindowSendable component) {
|
||||
addSensor("Ungrouped", moduleType + "[" + channel + "]", component);
|
||||
if (sensors.contains(component)) {
|
||||
sensors.removeElement(component);
|
||||
}
|
||||
sensors.addElement(component);
|
||||
@Deprecated
|
||||
public static void addSensor(String moduleType, int channel, Sendable component) {
|
||||
add(component);
|
||||
component.setName("Ungrouped", moduleType + "[" + channel + "]");
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -136,9 +122,12 @@ public class LiveWindow {
|
||||
* @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.
|
||||
* @deprecated Use {@link Sendable#setName(String, String)} instead.
|
||||
*/
|
||||
public static void addActuator(String subsystem, String name, LiveWindowSendable component) {
|
||||
components.put(component, new LiveWindowComponent(subsystem, name, false));
|
||||
@Deprecated
|
||||
public static synchronized void addActuator(String subsystem, String name, Sendable component) {
|
||||
add(component);
|
||||
component.setName(subsystem, name);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -148,9 +137,12 @@ public class LiveWindow {
|
||||
* @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 (usually PWM)
|
||||
* @param component The reference to the object being added
|
||||
* @deprecated Use {@link edu.wpi.first.wpilibj.SensorBase#setName(String, int)} instead.
|
||||
*/
|
||||
public static void addActuator(String moduleType, int channel, LiveWindowSendable component) {
|
||||
addActuator("Ungrouped", moduleType + "[" + channel + "]", component);
|
||||
@Deprecated
|
||||
public static void addActuator(String moduleType, int channel, Sendable component) {
|
||||
add(component);
|
||||
component.setName("Ungrouped", moduleType + "[" + channel + "]");
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -161,22 +153,137 @@ public class LiveWindow {
|
||||
* @param moduleNumber The number of the particular module type
|
||||
* @param channel The channel number the device is plugged into (usually PWM)
|
||||
* @param component The reference to the object being added
|
||||
* @deprecated Use {@link edu.wpi.first.wpilibj.SensorBase#setName(String, int, int)} instead.
|
||||
*/
|
||||
@Deprecated
|
||||
public static void addActuator(String moduleType, int moduleNumber, int channel,
|
||||
LiveWindowSendable component) {
|
||||
addActuator("Ungrouped", moduleType + "[" + moduleNumber + "," + channel + "]", component);
|
||||
Sendable component) {
|
||||
add(component);
|
||||
component.setName("Ungrouped", moduleType + "[" + moduleNumber + "," + channel + "]");
|
||||
}
|
||||
|
||||
/**
|
||||
* Puts all sensor values on the live window.
|
||||
* Add a component to the LiveWindow.
|
||||
*
|
||||
* @param sendable component to add
|
||||
*/
|
||||
private static void updateValues() {
|
||||
// TODO: gross - needs to be sped up
|
||||
for (int i = 0; i < sensors.size(); i++) {
|
||||
LiveWindowSendable lws = sensors.elementAt(i);
|
||||
lws.updateTable();
|
||||
public static synchronized void add(Sendable sendable) {
|
||||
components.putIfAbsent(sendable, new Component(sendable, null));
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a child component to a component.
|
||||
*
|
||||
* @param parent parent component
|
||||
* @param child child component
|
||||
*/
|
||||
public static synchronized void addChild(Sendable parent, Object child) {
|
||||
Component component = components.get(child);
|
||||
if (component == null) {
|
||||
component = new Component(null, parent);
|
||||
components.put(child, component);
|
||||
} else {
|
||||
component.m_parent = parent;
|
||||
}
|
||||
// TODO: Add actuators?
|
||||
// TODO: Add better rate limiting.
|
||||
component.m_telemetryEnabled = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove a component from the LiveWindow.
|
||||
*
|
||||
* @param sendable component to remove
|
||||
*/
|
||||
public static synchronized void remove(Sendable sendable) {
|
||||
Component component = components.remove(sendable);
|
||||
if (component != null && isEnabled()) {
|
||||
component.m_builder.stopLiveWindowMode();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable telemetry for a single component.
|
||||
*
|
||||
* @param sendable component
|
||||
*/
|
||||
public static synchronized void enableTelemetry(Sendable sendable) {
|
||||
// Re-enable global setting in case disableAllTelemetry() was called.
|
||||
telemetryEnabled = true;
|
||||
Component component = components.get(sendable);
|
||||
if (component != null) {
|
||||
component.m_telemetryEnabled = true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Disable telemetry for a single component.
|
||||
*
|
||||
* @param sendable component
|
||||
*/
|
||||
public static synchronized void disableTelemetry(Sendable sendable) {
|
||||
Component component = components.get(sendable);
|
||||
if (component != null) {
|
||||
component.m_telemetryEnabled = false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Disable ALL telemetry.
|
||||
*/
|
||||
public static synchronized void disableAllTelemetry() {
|
||||
telemetryEnabled = false;
|
||||
for (Component component : components.values()) {
|
||||
component.m_telemetryEnabled = false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tell all the sensors to update (send) their values.
|
||||
*
|
||||
* <p>Actuators are handled through callbacks on their value changing from the
|
||||
* SmartDashboard widgets.
|
||||
*/
|
||||
public static synchronized void updateValues() {
|
||||
// Only do this if either LiveWindow mode or telemetry is enabled.
|
||||
if (!liveWindowEnabled && !telemetryEnabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (Component component : components.values()) {
|
||||
if (component.m_sendable != null && component.m_parent == null
|
||||
&& (liveWindowEnabled || component.m_telemetryEnabled)) {
|
||||
if (component.m_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.
|
||||
String name = component.m_sendable.getName();
|
||||
if (name.isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
String subsystem = component.m_sendable.getSubsystem();
|
||||
NetworkTable ssTable = liveWindowTable.getSubTable(subsystem);
|
||||
NetworkTable table;
|
||||
// Treat name==subsystem as top level of subsystem
|
||||
if (name.equals(subsystem)) {
|
||||
table = ssTable;
|
||||
} else {
|
||||
table = ssTable.getSubTable(name);
|
||||
}
|
||||
table.getEntry(".name").setString(name);
|
||||
component.m_builder.setTable(table);
|
||||
component.m_sendable.initSendable(component.m_builder);
|
||||
ssTable.getEntry(".type").setString("LW Subsystem");
|
||||
|
||||
component.m_firstTime = false;
|
||||
}
|
||||
|
||||
if (startLiveWindow) {
|
||||
component.m_builder.startLiveWindowMode();
|
||||
}
|
||||
component.m_builder.updateTable();
|
||||
}
|
||||
}
|
||||
|
||||
startLiveWindow = false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,41 +0,0 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) 2016-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. */
|
||||
/*----------------------------------------------------------------------------*/
|
||||
|
||||
package edu.wpi.first.wpilibj.livewindow;
|
||||
|
||||
/**
|
||||
* A LiveWindow component is a device (sensor or actuator) that should be added to the
|
||||
* SmartDashboard in test mode. The components are cached until the first time the robot enters Test
|
||||
* mode. This allows the components to be inserted, then renamed.
|
||||
*/
|
||||
/*
|
||||
* This class is intentionally package private.
|
||||
*/
|
||||
class LiveWindowComponent {
|
||||
|
||||
String m_subsystem;
|
||||
String m_name;
|
||||
boolean m_isSensor;
|
||||
|
||||
LiveWindowComponent(String subsystem, String name, boolean isSensor) {
|
||||
m_subsystem = subsystem;
|
||||
m_name = name;
|
||||
m_isSensor = isSensor;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return m_name;
|
||||
}
|
||||
|
||||
public String getSubsystem() {
|
||||
return m_subsystem;
|
||||
}
|
||||
|
||||
public boolean isSensor() {
|
||||
return m_isSensor;
|
||||
}
|
||||
}
|
||||
@@ -1,31 +0,0 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) 2008-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. */
|
||||
/*----------------------------------------------------------------------------*/
|
||||
|
||||
package edu.wpi.first.wpilibj.livewindow;
|
||||
|
||||
import edu.wpi.first.wpilibj.Sendable;
|
||||
|
||||
/**
|
||||
* Live Window Sendable is a special type of object sendable to the live window.
|
||||
*/
|
||||
public interface LiveWindowSendable extends Sendable {
|
||||
/**
|
||||
* Update the table for this sendable object with the latest values.
|
||||
*/
|
||||
void updateTable();
|
||||
|
||||
/**
|
||||
* Start having this sendable object automatically respond to value changes reflect the value on
|
||||
* the table.
|
||||
*/
|
||||
void startLiveWindowMode();
|
||||
|
||||
/**
|
||||
* Stop having this sendable object automatically respond to value changes.
|
||||
*/
|
||||
void stopLiveWindowMode();
|
||||
}
|
||||
@@ -0,0 +1,143 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* 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. */
|
||||
/*----------------------------------------------------------------------------*/
|
||||
|
||||
package edu.wpi.first.wpilibj.smartdashboard;
|
||||
|
||||
import edu.wpi.first.networktables.NetworkTableEntry;
|
||||
import edu.wpi.first.networktables.NetworkTableValue;
|
||||
import java.util.function.BooleanSupplier;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.DoubleConsumer;
|
||||
import java.util.function.DoubleSupplier;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
public interface SendableBuilder {
|
||||
/**
|
||||
* Set the string representation of the named data type that will be used
|
||||
* by the smart dashboard for this sendable.
|
||||
*
|
||||
* @param type data type
|
||||
*/
|
||||
void setSmartDashboardType(String type);
|
||||
|
||||
/**
|
||||
* Set the function that should be called to set the Sendable into a safe
|
||||
* state. This is called when entering and exiting Live Window mode.
|
||||
*
|
||||
* @param func function
|
||||
*/
|
||||
void setSafeState(Runnable func);
|
||||
|
||||
/**
|
||||
* Set the function that should be called to update the network table
|
||||
* for things other than properties. Note this function is not passed
|
||||
* the network table object; instead it should use the entry handles
|
||||
* returned by getEntry().
|
||||
*
|
||||
* @param func function
|
||||
*/
|
||||
void setUpdateTable(Runnable func);
|
||||
|
||||
/**
|
||||
* Add a property without getters or setters. This can be used to get
|
||||
* entry handles for the function called by setUpdateTable().
|
||||
*
|
||||
* @param key property name
|
||||
* @return Network table entry
|
||||
*/
|
||||
NetworkTableEntry getEntry(String key);
|
||||
|
||||
/**
|
||||
* Represents an operation that accepts a single boolean-valued argument and
|
||||
* returns no result. This is the primitive type specialization of Consumer
|
||||
* for boolean. Unlike most other functional interfaces, BooleanConsumer is
|
||||
* expected to operate via side-effects.
|
||||
*
|
||||
* <p>This is a functional interface whose functional method is accept(boolean).
|
||||
*/
|
||||
@FunctionalInterface
|
||||
interface BooleanConsumer {
|
||||
/**
|
||||
* Performs the operation on the given value.
|
||||
* @param value the value
|
||||
*/
|
||||
void accept(boolean value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a boolean property.
|
||||
*
|
||||
* @param key property name
|
||||
* @param getter getter function (returns current value)
|
||||
* @param setter setter function (sets new value)
|
||||
*/
|
||||
void addBooleanProperty(String key, BooleanSupplier getter, BooleanConsumer setter);
|
||||
|
||||
/**
|
||||
* Add a double property.
|
||||
*
|
||||
* @param key property name
|
||||
* @param getter getter function (returns current value)
|
||||
* @param setter setter function (sets new value)
|
||||
*/
|
||||
void addDoubleProperty(String key, DoubleSupplier getter, DoubleConsumer setter);
|
||||
|
||||
/**
|
||||
* Add a string property.
|
||||
*
|
||||
* @param key property name
|
||||
* @param getter getter function (returns current value)
|
||||
* @param setter setter function (sets new value)
|
||||
*/
|
||||
void addStringProperty(String key, Supplier<String> getter, Consumer<String> setter);
|
||||
|
||||
/**
|
||||
* Add a boolean array property.
|
||||
*
|
||||
* @param key property name
|
||||
* @param getter getter function (returns current value)
|
||||
* @param setter setter function (sets new value)
|
||||
*/
|
||||
void addBooleanArrayProperty(String key, Supplier<boolean[]> getter, Consumer<boolean[]> setter);
|
||||
|
||||
/**
|
||||
* Add a double array property.
|
||||
*
|
||||
* @param key property name
|
||||
* @param getter getter function (returns current value)
|
||||
* @param setter setter function (sets new value)
|
||||
*/
|
||||
void addDoubleArrayProperty(String key, Supplier<double[]> getter, Consumer<double[]> setter);
|
||||
|
||||
/**
|
||||
* Add a string array property.
|
||||
*
|
||||
* @param key property name
|
||||
* @param getter getter function (returns current value)
|
||||
* @param setter setter function (sets new value)
|
||||
*/
|
||||
void addStringArrayProperty(String key, Supplier<String[]> getter, Consumer<String[]> setter);
|
||||
|
||||
/**
|
||||
* Add a raw property.
|
||||
*
|
||||
* @param key property name
|
||||
* @param getter getter function (returns current value)
|
||||
* @param setter setter function (sets new value)
|
||||
*/
|
||||
void addRawProperty(String key, Supplier<byte[]> getter, Consumer<byte[]> setter);
|
||||
|
||||
/**
|
||||
* Add a NetworkTableValue property.
|
||||
*
|
||||
* @param key property name
|
||||
* @param getter getter function (returns current value)
|
||||
* @param setter setter function (sets new value)
|
||||
*/
|
||||
void addValueProperty(String key, Supplier<NetworkTableValue> getter,
|
||||
Consumer<NetworkTableValue> setter);
|
||||
}
|
||||
@@ -0,0 +1,346 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* 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. */
|
||||
/*----------------------------------------------------------------------------*/
|
||||
|
||||
package edu.wpi.first.wpilibj.smartdashboard;
|
||||
|
||||
import edu.wpi.first.networktables.EntryListenerFlags;
|
||||
import edu.wpi.first.networktables.NetworkTable;
|
||||
import edu.wpi.first.networktables.NetworkTableEntry;
|
||||
import edu.wpi.first.networktables.NetworkTableValue;
|
||||
import java.util.function.BooleanSupplier;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.DoubleConsumer;
|
||||
import java.util.function.DoubleSupplier;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Supplier;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class SendableBuilderImpl implements SendableBuilder {
|
||||
private static class Property {
|
||||
Property(NetworkTable table, String key) {
|
||||
m_entry = table.getEntry(key);
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("NoFinalizer")
|
||||
public synchronized void finalize() {
|
||||
stopListener();
|
||||
}
|
||||
|
||||
void startListener() {
|
||||
if (m_entry.isValid() && m_listener == 0 && m_createListener != null) {
|
||||
m_listener = m_createListener.apply(m_entry);
|
||||
}
|
||||
}
|
||||
|
||||
void stopListener() {
|
||||
if (m_entry.isValid() && m_listener != 0) {
|
||||
m_entry.removeListener(m_listener);
|
||||
m_listener = 0;
|
||||
}
|
||||
}
|
||||
|
||||
final NetworkTableEntry m_entry;
|
||||
int m_listener = 0;
|
||||
Consumer<NetworkTableEntry> m_update;
|
||||
Function<NetworkTableEntry, Integer> m_createListener;
|
||||
}
|
||||
|
||||
private final List<Property> m_properties = new ArrayList<>();
|
||||
private Runnable m_safeState;
|
||||
private Runnable m_updateTable;
|
||||
private NetworkTable m_table;
|
||||
|
||||
/**
|
||||
* Set the network table. Must be called prior to any Add* functions being
|
||||
* called.
|
||||
* @param table Network table
|
||||
*/
|
||||
public void setTable(NetworkTable table) {
|
||||
m_table = table;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the network table.
|
||||
* @return The network table
|
||||
*/
|
||||
public NetworkTable getTable() {
|
||||
return m_table;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the network table values by calling the getters for all properties.
|
||||
*/
|
||||
public void updateTable() {
|
||||
for (Property property : m_properties) {
|
||||
if (property.m_update != null) {
|
||||
property.m_update.accept(property.m_entry);
|
||||
}
|
||||
}
|
||||
if (m_updateTable != null) {
|
||||
m_updateTable.run();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Start LiveWindow mode by hooking the setters for all properties.
|
||||
*/
|
||||
public void startLiveWindowMode() {
|
||||
if (m_safeState != null) {
|
||||
m_safeState.run();
|
||||
}
|
||||
for (Property property : m_properties) {
|
||||
property.startListener();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Stop LiveWindow mode by unhooking the setters for all properties.
|
||||
*/
|
||||
public void stopLiveWindowMode() {
|
||||
if (m_safeState != null) {
|
||||
m_safeState.run();
|
||||
}
|
||||
for (Property property : m_properties) {
|
||||
property.stopListener();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the string representation of the named data type that will be used
|
||||
* by the smart dashboard for this sendable.
|
||||
*
|
||||
* @param type data type
|
||||
*/
|
||||
@Override
|
||||
public void setSmartDashboardType(String type) {
|
||||
m_table.getEntry(".type").setString(type);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the function that should be called to set the Sendable into a safe
|
||||
* state. This is called when entering and exiting Live Window mode.
|
||||
*
|
||||
* @param func function
|
||||
*/
|
||||
@Override
|
||||
public void setSafeState(Runnable func) {
|
||||
m_safeState = func;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the function that should be called to update the network table
|
||||
* for things other than properties. Note this function is not passed
|
||||
* the network table object; instead it should use the entry handles
|
||||
* returned by getEntry().
|
||||
*
|
||||
* @param func function
|
||||
*/
|
||||
@Override
|
||||
public void setUpdateTable(Runnable func) {
|
||||
m_updateTable = func;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a property without getters or setters. This can be used to get
|
||||
* entry handles for the function called by setUpdateTable().
|
||||
*
|
||||
* @param key property name
|
||||
* @return Network table entry
|
||||
*/
|
||||
@Override
|
||||
public NetworkTableEntry getEntry(String key) {
|
||||
return m_table.getEntry(key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a boolean property.
|
||||
*
|
||||
* @param key property name
|
||||
* @param getter getter function (returns current value)
|
||||
* @param setter setter function (sets new value)
|
||||
*/
|
||||
@Override
|
||||
public void addBooleanProperty(String key, BooleanSupplier getter, BooleanConsumer setter) {
|
||||
Property property = new Property(m_table, key);
|
||||
if (getter != null) {
|
||||
property.m_update = (entry) -> entry.setBoolean(getter.getAsBoolean());
|
||||
}
|
||||
if (setter != null) {
|
||||
property.m_createListener = (entry) -> entry.addListener((event) -> {
|
||||
if (event.value.isBoolean()) {
|
||||
setter.accept(event.value.getBoolean());
|
||||
}
|
||||
}, EntryListenerFlags.kImmediate | EntryListenerFlags.kNew | EntryListenerFlags.kUpdate);
|
||||
}
|
||||
m_properties.add(property);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a double property.
|
||||
*
|
||||
* @param key property name
|
||||
* @param getter getter function (returns current value)
|
||||
* @param setter setter function (sets new value)
|
||||
*/
|
||||
@Override
|
||||
public void addDoubleProperty(String key, DoubleSupplier getter, DoubleConsumer setter) {
|
||||
Property property = new Property(m_table, key);
|
||||
if (getter != null) {
|
||||
property.m_update = (entry) -> entry.setDouble(getter.getAsDouble());
|
||||
}
|
||||
if (setter != null) {
|
||||
property.m_createListener = (entry) -> entry.addListener((event) -> {
|
||||
if (event.value.isDouble()) {
|
||||
setter.accept(event.value.getDouble());
|
||||
}
|
||||
}, EntryListenerFlags.kImmediate | EntryListenerFlags.kNew | EntryListenerFlags.kUpdate);
|
||||
}
|
||||
m_properties.add(property);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a string property.
|
||||
*
|
||||
* @param key property name
|
||||
* @param getter getter function (returns current value)
|
||||
* @param setter setter function (sets new value)
|
||||
*/
|
||||
@Override
|
||||
public void addStringProperty(String key, Supplier<String> getter, Consumer<String> setter) {
|
||||
Property property = new Property(m_table, key);
|
||||
if (getter != null) {
|
||||
property.m_update = (entry) -> entry.setString(getter.get());
|
||||
}
|
||||
if (setter != null) {
|
||||
property.m_createListener = (entry) -> entry.addListener((event) -> {
|
||||
if (event.value.isString()) {
|
||||
setter.accept(event.value.getString());
|
||||
}
|
||||
}, EntryListenerFlags.kImmediate | EntryListenerFlags.kNew | EntryListenerFlags.kUpdate);
|
||||
}
|
||||
m_properties.add(property);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a boolean array property.
|
||||
*
|
||||
* @param key property name
|
||||
* @param getter getter function (returns current value)
|
||||
* @param setter setter function (sets new value)
|
||||
*/
|
||||
@Override
|
||||
public void addBooleanArrayProperty(String key, Supplier<boolean[]> getter,
|
||||
Consumer<boolean[]> setter) {
|
||||
Property property = new Property(m_table, key);
|
||||
if (getter != null) {
|
||||
property.m_update = (entry) -> entry.setBooleanArray(getter.get());
|
||||
}
|
||||
if (setter != null) {
|
||||
property.m_createListener = (entry) -> entry.addListener((event) -> {
|
||||
if (event.value.isBooleanArray()) {
|
||||
setter.accept(event.value.getBooleanArray());
|
||||
}
|
||||
}, EntryListenerFlags.kImmediate | EntryListenerFlags.kNew | EntryListenerFlags.kUpdate);
|
||||
}
|
||||
m_properties.add(property);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a double array property.
|
||||
*
|
||||
* @param key property name
|
||||
* @param getter getter function (returns current value)
|
||||
* @param setter setter function (sets new value)
|
||||
*/
|
||||
@Override
|
||||
public void addDoubleArrayProperty(String key, Supplier<double[]> getter,
|
||||
Consumer<double[]> setter) {
|
||||
Property property = new Property(m_table, key);
|
||||
if (getter != null) {
|
||||
property.m_update = (entry) -> entry.setDoubleArray(getter.get());
|
||||
}
|
||||
if (setter != null) {
|
||||
property.m_createListener = (entry) -> entry.addListener((event) -> {
|
||||
if (event.value.isDoubleArray()) {
|
||||
setter.accept(event.value.getDoubleArray());
|
||||
}
|
||||
}, EntryListenerFlags.kImmediate | EntryListenerFlags.kNew | EntryListenerFlags.kUpdate);
|
||||
}
|
||||
m_properties.add(property);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a string array property.
|
||||
*
|
||||
* @param key property name
|
||||
* @param getter getter function (returns current value)
|
||||
* @param setter setter function (sets new value)
|
||||
*/
|
||||
@Override
|
||||
public void addStringArrayProperty(String key, Supplier<String[]> getter,
|
||||
Consumer<String[]> setter) {
|
||||
Property property = new Property(m_table, key);
|
||||
if (getter != null) {
|
||||
property.m_update = (entry) -> entry.setStringArray(getter.get());
|
||||
}
|
||||
if (setter != null) {
|
||||
property.m_createListener = (entry) -> entry.addListener((event) -> {
|
||||
if (event.value.isStringArray()) {
|
||||
setter.accept(event.value.getStringArray());
|
||||
}
|
||||
}, EntryListenerFlags.kImmediate | EntryListenerFlags.kNew | EntryListenerFlags.kUpdate);
|
||||
}
|
||||
m_properties.add(property);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a raw property.
|
||||
*
|
||||
* @param key property name
|
||||
* @param getter getter function (returns current value)
|
||||
* @param setter setter function (sets new value)
|
||||
*/
|
||||
@Override
|
||||
public void addRawProperty(String key, Supplier<byte[]> getter, Consumer<byte[]> setter) {
|
||||
Property property = new Property(m_table, key);
|
||||
if (getter != null) {
|
||||
property.m_update = (entry) -> entry.setRaw(getter.get());
|
||||
}
|
||||
if (setter != null) {
|
||||
property.m_createListener = (entry) -> entry.addListener((event) -> {
|
||||
if (event.value.isRaw()) {
|
||||
setter.accept(event.value.getRaw());
|
||||
}
|
||||
}, EntryListenerFlags.kImmediate | EntryListenerFlags.kNew | EntryListenerFlags.kUpdate);
|
||||
}
|
||||
m_properties.add(property);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a NetworkTableValue property.
|
||||
*
|
||||
* @param key property name
|
||||
* @param getter getter function (returns current value)
|
||||
* @param setter setter function (sets new value)
|
||||
*/
|
||||
@Override
|
||||
public void addValueProperty(String key, Supplier<NetworkTableValue> getter,
|
||||
Consumer<NetworkTableValue> setter) {
|
||||
Property property = new Property(m_table, key);
|
||||
if (getter != null) {
|
||||
property.m_update = (entry) -> entry.setValue(getter.get());
|
||||
}
|
||||
if (setter != null) {
|
||||
property.m_createListener = (entry) -> entry.addListener((event) -> {
|
||||
setter.accept(event.value);
|
||||
}, EntryListenerFlags.kImmediate | EntryListenerFlags.kNew | EntryListenerFlags.kUpdate);
|
||||
}
|
||||
m_properties.add(property);
|
||||
}
|
||||
}
|
||||
@@ -9,9 +9,9 @@ package edu.wpi.first.wpilibj.smartdashboard;
|
||||
|
||||
import java.util.LinkedHashMap;
|
||||
|
||||
import edu.wpi.first.networktables.NetworkTable;
|
||||
import edu.wpi.first.networktables.NetworkTableEntry;
|
||||
import edu.wpi.first.wpilibj.Sendable;
|
||||
import edu.wpi.first.wpilibj.SendableBase;
|
||||
import edu.wpi.first.wpilibj.command.Command;
|
||||
|
||||
import static java.util.Objects.requireNonNull;
|
||||
@@ -28,7 +28,7 @@ import static java.util.Objects.requireNonNull;
|
||||
*
|
||||
* @param <V> The type of the values to be stored
|
||||
*/
|
||||
public class SendableChooser<V> implements Sendable {
|
||||
public class SendableChooser<V> extends SendableBase implements Sendable {
|
||||
|
||||
/**
|
||||
* The key for the default value.
|
||||
@@ -46,7 +46,7 @@ public class SendableChooser<V> implements Sendable {
|
||||
* A map linking strings to the objects the represent.
|
||||
*/
|
||||
private final LinkedHashMap<String, V> m_map = new LinkedHashMap<>();
|
||||
private String m_defaultChoice = null;
|
||||
private String m_defaultChoice = "";
|
||||
|
||||
/**
|
||||
* Instantiates a {@link SendableChooser}.
|
||||
@@ -63,10 +63,6 @@ public class SendableChooser<V> implements Sendable {
|
||||
*/
|
||||
public void addObject(String name, V object) {
|
||||
m_map.put(name, object);
|
||||
|
||||
if (m_tableOptions != null) {
|
||||
m_tableOptions.setStringArray(m_map.keySet().toArray(new String[0]));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -81,9 +77,6 @@ public class SendableChooser<V> implements Sendable {
|
||||
requireNonNull(name, "Provided name was null");
|
||||
|
||||
m_defaultChoice = name;
|
||||
if (m_tableDefault != null) {
|
||||
m_tableDefault.setString(m_defaultChoice);
|
||||
}
|
||||
addObject(name, object);
|
||||
}
|
||||
|
||||
@@ -94,29 +87,24 @@ public class SendableChooser<V> implements Sendable {
|
||||
* @return the option selected
|
||||
*/
|
||||
public V getSelected() {
|
||||
String selected = m_tableSelected.getString(null);
|
||||
return m_map.getOrDefault(selected, m_map.get(m_defaultChoice));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSmartDashboardType() {
|
||||
return "String Chooser";
|
||||
}
|
||||
|
||||
private NetworkTableEntry m_tableDefault;
|
||||
private NetworkTableEntry m_tableSelected;
|
||||
private NetworkTableEntry m_tableOptions;
|
||||
|
||||
@Override
|
||||
public void initTable(NetworkTable table) {
|
||||
if (table != null) {
|
||||
m_tableDefault = table.getEntry(DEFAULT);
|
||||
m_tableSelected = table.getEntry(SELECTED);
|
||||
m_tableOptions = table.getEntry(OPTIONS);
|
||||
m_tableOptions.setStringArray(m_map.keySet().toArray(new String[0]));
|
||||
if (m_defaultChoice != null) {
|
||||
m_tableDefault.setString(m_defaultChoice);
|
||||
}
|
||||
String selected = m_defaultChoice;
|
||||
if (m_tableSelected != null) {
|
||||
selected = m_tableSelected.getString(m_defaultChoice);
|
||||
}
|
||||
return m_map.get(selected);
|
||||
}
|
||||
|
||||
private NetworkTableEntry m_tableSelected;
|
||||
|
||||
@Override
|
||||
public void initSendable(SendableBuilder builder) {
|
||||
builder.setSmartDashboardType("String Chooser");
|
||||
builder.addStringProperty(DEFAULT, () -> {
|
||||
return m_defaultChoice;
|
||||
}, null);
|
||||
builder.addStringArrayProperty(OPTIONS, () -> {
|
||||
return m_map.keySet().toArray(new String[0]);
|
||||
}, null);
|
||||
m_tableSelected = builder.getEntry(SELECTED);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,14 +8,14 @@
|
||||
package edu.wpi.first.wpilibj.smartdashboard;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.Hashtable;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import edu.wpi.first.networktables.NetworkTable;
|
||||
import edu.wpi.first.networktables.NetworkTableEntry;
|
||||
import edu.wpi.first.networktables.NetworkTableInstance;
|
||||
import edu.wpi.first.wpilibj.HLUsageReporting;
|
||||
import edu.wpi.first.wpilibj.NamedSendable;
|
||||
import edu.wpi.first.wpilibj.Sendable;
|
||||
|
||||
/**
|
||||
@@ -31,11 +31,17 @@ public class SmartDashboard {
|
||||
*/
|
||||
private static final NetworkTable table =
|
||||
NetworkTableInstance.getDefault().getTable("SmartDashboard");
|
||||
|
||||
private static class Data {
|
||||
Sendable m_sendable;
|
||||
final SendableBuilderImpl m_builder = new SendableBuilderImpl();
|
||||
}
|
||||
|
||||
/**
|
||||
* A table linking tables in the SmartDashboard to the {@link Sendable} objects they
|
||||
* came from.
|
||||
*/
|
||||
private static final Hashtable<NetworkTable, Sendable> tablesToData = new Hashtable<>();
|
||||
private static final Map<String, Data> tablesToData = new HashMap<>();
|
||||
|
||||
static {
|
||||
HLUsageReporting.reportSmartDashboard();
|
||||
@@ -49,25 +55,29 @@ public class SmartDashboard {
|
||||
* @param data the value
|
||||
* @throws IllegalArgumentException If key is null
|
||||
*/
|
||||
public static void putData(String key, Sendable data) {
|
||||
NetworkTable dataTable = table.getSubTable(key);
|
||||
dataTable.getEntry(".type").setString(data.getSmartDashboardType());
|
||||
data.initTable(dataTable);
|
||||
tablesToData.put(dataTable, data);
|
||||
public static synchronized void putData(String key, Sendable data) {
|
||||
Data sddata = tablesToData.get(key);
|
||||
if (sddata == null) {
|
||||
sddata = new Data();
|
||||
tablesToData.put(key, sddata);
|
||||
}
|
||||
if (sddata.m_sendable == null || sddata.m_sendable != data) {
|
||||
sddata.m_sendable = data;
|
||||
sddata.m_builder.setTable(table.getSubTable(key));
|
||||
data.initSendable(sddata.m_builder);
|
||||
}
|
||||
sddata.m_builder.updateTable();
|
||||
}
|
||||
|
||||
|
||||
// TODO should we reimplement NamedSendable?
|
||||
|
||||
/**
|
||||
* Maps the specified key (where the key is the name of the {@link NamedSendable}
|
||||
* SmartDashboardNamedData to the specified value in this table. The value can be retrieved by
|
||||
* 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
|
||||
* @throws IllegalArgumentException If key is null
|
||||
*/
|
||||
public static void putData(NamedSendable value) {
|
||||
public static void putData(Sendable value) {
|
||||
putData(value.getName(), value);
|
||||
}
|
||||
|
||||
@@ -78,13 +88,12 @@ public class SmartDashboard {
|
||||
* @return the value
|
||||
* @throws IllegalArgumentException if the key is null
|
||||
*/
|
||||
public static Sendable getData(String key) {
|
||||
NetworkTable subtable = table.getSubTable(key);
|
||||
Sendable data = tablesToData.get(subtable);
|
||||
public static synchronized Sendable getData(String key) {
|
||||
Data data = tablesToData.get(key);
|
||||
if (data == null) {
|
||||
throw new IllegalArgumentException("SmartDashboard data does not exist: " + key);
|
||||
} else {
|
||||
return data;
|
||||
return data.m_sendable;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user